@sideboard-ai/core 0.1.319 → 0.1.321
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/{abletime-L3ODNTBT.js → abletime-CRRLEYTE.js} +4 -4
- package/dist/{abletime-DVYO4IVS.js → abletime-ICW6Q2AB.js} +4 -4
- package/dist/{abletime-oauth-2VWQCXGT.js → abletime-oauth-P3KPPJE4.js} +3 -3
- package/dist/{abletime-oauth-6DTX7LB7.js → abletime-oauth-Q76XBSPG.js} +3 -3
- package/dist/{abletime-rest-PYQM234B.js → abletime-rest-DNFAYYLP.js} +3 -3
- package/dist/{abletime-rest-7NICZYOC.js → abletime-rest-DQ3PNKXP.js} +3 -3
- package/dist/agents/cursor-runner.js +2 -2
- package/dist/{agents-KABJUDPI.js → agents-PFVYC36J.js} +10 -10
- package/dist/{agents-2AR7I6B6.js → agents-ROFDNE7Z.js} +11 -11
- package/dist/{app-settings-CZVFMOI5.js → app-settings-KMPVI2B7.js} +1 -1
- package/dist/{app-settings-V6YPYY57.js → app-settings-P3H4SEIK.js} +1 -1
- package/dist/{chunk-QVN2WOKJ.js → chunk-2TUE6JKQ.js} +12 -0
- package/dist/{chunk-OO3R6CS2.js → chunk-45UB2J47.js} +537 -90
- package/dist/{chunk-DD67JWTN.js → chunk-4YXZOXMT.js} +1 -1
- package/dist/{chunk-5OM7UCTQ.js → chunk-56M6VEXI.js} +3 -3
- package/dist/{chunk-ZM43NTJJ.js → chunk-5OQONGHO.js} +5 -5
- package/dist/{chunk-V5BTGQ6M.js → chunk-6U6QRUHY.js} +1 -1
- package/dist/{chunk-QPLQXWND.js → chunk-72PUPPV2.js} +3 -3
- package/dist/{chunk-53OCOGND.js → chunk-7JV5QP5K.js} +3 -3
- package/dist/{chunk-HOLB6ZFZ.js → chunk-B4CDSSRN.js} +2 -0
- package/dist/{chunk-ST2UQBJT.js → chunk-BANN5HUX.js} +8 -8
- package/dist/{chunk-AESO2KJS.js → chunk-BPDVHB4U.js} +3 -3
- package/dist/{chunk-WLZHRNE6.js → chunk-BTIXTH4N.js} +3 -3
- package/dist/{chunk-AUJ4XB6H.js → chunk-DFUXW2IT.js} +2 -2
- package/dist/{chunk-I5TESHDN.js → chunk-EQ52JR3Q.js} +5 -5
- package/dist/{chunk-E52SQENB.js → chunk-FZKAAAEB.js} +3 -1
- package/dist/{chunk-YALFZKSC.js → chunk-H6GXYV5Q.js} +23 -20
- package/dist/{chunk-JD7CC6SW.js → chunk-HHPTGIKS.js} +2 -2
- package/dist/{chunk-GCHSJCCX.js → chunk-IFU4W4C4.js} +3 -1
- package/dist/{chunk-YEIHCSZS.js → chunk-IFWGG2M2.js} +9 -0
- package/dist/{chunk-IAPO7ZFG.js → chunk-JNEFEA2A.js} +8 -8
- package/dist/{chunk-U2N32EA6.js → chunk-LD2DXHBP.js} +543 -92
- package/dist/{chunk-7Q327QF2.js → chunk-QIC2JXHW.js} +5 -5
- package/dist/{chunk-2P4XKWV2.js → chunk-QKHEVSB5.js} +1 -1
- package/dist/{chunk-NRSC4N5X.js → chunk-RGUZPMTF.js} +8 -8
- package/dist/{chunk-AZ4GEEGL.js → chunk-RHJKZOPQ.js} +3 -3
- package/dist/{chunk-HH3VVTEC.js → chunk-S5CJUIPY.js} +5 -5
- package/dist/{chunk-A6C67DY5.js → chunk-SPMIZSKH.js} +16 -13
- package/dist/{chunk-FDXHNROD.js → chunk-TEFFR6PB.js} +2 -2
- package/dist/{chunk-TUJFCJJU.js → chunk-UWJUARFA.js} +546 -187
- package/dist/{chunk-MBYGWNLQ.js → chunk-UX6EDDGR.js} +1 -1
- package/dist/{chunk-LXBZQP2Q.js → chunk-V76MQ7MH.js} +5 -5
- package/dist/{chunk-GH7UMULC.js → chunk-XDQSHSL6.js} +8 -8
- package/dist/{chunk-2UG25RMK.js → chunk-YBTSZ2SW.js} +12 -0
- package/dist/{chunk-A46CIARU.js → chunk-YWBLQBSN.js} +549 -188
- package/dist/{chunk-Y3Y7SZBZ.js → chunk-ZHGMRBSC.js} +1 -1
- package/dist/{conductor-MG2RAQNT.js → conductor-CNT3VL3S.js} +8 -8
- package/dist/{conductor-NIUBJLTS.js → conductor-XLXJU24U.js} +8 -8
- package/dist/{connected-teams-IHK2WXUI.js → connected-teams-H4LZOJDC.js} +2 -2
- package/dist/{connected-teams-IFW3NQ6G.js → connected-teams-XYRZMQO4.js} +2 -2
- package/dist/{coordinator-prompt-X74F3JIC.js → coordinator-prompt-D5EE2YTV.js} +6 -6
- package/dist/{coordinator-prompt-3CT3D5UM.js → coordinator-prompt-TU24TQ4I.js} +6 -6
- package/dist/{global-workspace-BUWMRNW5.js → global-workspace-743TPQNF.js} +6 -6
- package/dist/{global-workspace-FTNJEML3.js → global-workspace-UPMXDQM7.js} +6 -6
- package/dist/index.cjs +2160 -867
- package/dist/index.d.cts +211 -74
- package/dist/index.d.ts +211 -74
- package/dist/index.js +496 -78
- package/dist/mcp/run-stdio.cjs +1377 -478
- package/dist/mcp/run-stdio.js +80 -32
- package/dist/{optional-cli-6GGESWGE.js → optional-cli-2YDQQCCD.js} +5 -5
- package/dist/{optional-cli-EMSZBYDE.js → optional-cli-USD6PROE.js} +4 -4
- package/dist/{orchestrator-NCA4LSCC.js → orchestrator-B4STIW4B.js} +14 -14
- package/dist/{orchestrator-H3DSZ5RM.js → orchestrator-VQ4HRYVB.js} +13 -13
- package/dist/{run-PCX5QWR4.js → run-7QMRYP3F.js} +3 -1
- package/dist/{run-TB7RBII2.js → run-UPNCCRCN.js} +3 -1
- package/dist/{thread-store-PLNIWFZ4.js → thread-store-3F7GR64A.js} +1 -1
- package/dist/{thread-store-7BBA63KV.js → thread-store-JRSL4HQY.js} +1 -1
- package/dist/{workspaces-MGKEAYNM.js → workspaces-47WQL5IG.js} +6 -6
- package/dist/{workspaces-2V5UYPYC.js → workspaces-75FD4QUR.js} +6 -6
- package/dist/{worktree-XJKLDYOL.js → worktree-G3E6WP66.js} +11 -9
- package/dist/{worktree-THAXW5U7.js → worktree-PDNPL5CQ.js} +11 -9
- package/dist/{worktree-exclude-RXZPTCNH.js → worktree-exclude-INRDQFWV.js} +2 -2
- package/dist/{worktree-exclude-5N2KTYIT.js → worktree-exclude-P5NJODWP.js} +2 -2
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
parseSessionQuotaResetAt,
|
|
15
15
|
planModeTurnInstruction,
|
|
16
16
|
resolveQuotaFallbackAgent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JNEFEA2A.js";
|
|
18
18
|
import {
|
|
19
19
|
applyWorktreePkgCacheEnv,
|
|
20
20
|
askBlockStillWaiting,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
worktreeDevProcessKey,
|
|
53
53
|
worktreeRunProcessKey,
|
|
54
54
|
worktreeSetupProcessKey
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-BANN5HUX.js";
|
|
56
56
|
import {
|
|
57
57
|
applyAgentEvent,
|
|
58
58
|
clipAgentEventForPaint,
|
|
@@ -67,14 +67,14 @@ import {
|
|
|
67
67
|
partsToAssistantText,
|
|
68
68
|
stripBrightsyNdjsonNoise,
|
|
69
69
|
toolDescription
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-QIC2JXHW.js";
|
|
71
71
|
import {
|
|
72
72
|
titleFromPrompt
|
|
73
73
|
} from "./chunk-7H655NEW.js";
|
|
74
74
|
import {
|
|
75
75
|
formatOptionalServicesDirectiveForTurn,
|
|
76
76
|
formatOptionalServicesReminderForTurn
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-TEFFR6PB.js";
|
|
78
78
|
import {
|
|
79
79
|
SLACK_REPLY_FORMATTING,
|
|
80
80
|
addWorkspace,
|
|
@@ -99,21 +99,24 @@ import {
|
|
|
99
99
|
stageAbsolutePathsAsAttachments,
|
|
100
100
|
stageBuffersAsAttachments,
|
|
101
101
|
syncWorkspacesFromThreads
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-H6GXYV5Q.js";
|
|
103
103
|
import {
|
|
104
104
|
addPrStackLayer,
|
|
105
105
|
allocateTeamSlug,
|
|
106
106
|
canonicalizeRepoPath,
|
|
107
107
|
ciChecksFailed,
|
|
108
|
+
clampGithubPrBody,
|
|
108
109
|
classifyPrMergeIssue,
|
|
109
110
|
commitAll,
|
|
110
111
|
connectedPrSelectors,
|
|
111
112
|
createExistingBranchWorktree,
|
|
112
|
-
|
|
113
|
+
createOrUpdateCursorPr,
|
|
113
114
|
createThreadWorktree,
|
|
114
115
|
currentBranch,
|
|
115
116
|
detectGhStack,
|
|
116
117
|
enqueueByKey,
|
|
118
|
+
ensureGhPreferOrigin,
|
|
119
|
+
entireUsesTrails,
|
|
117
120
|
fastForwardMainCheckoutIfSafe,
|
|
118
121
|
fetchOriginForWorktree,
|
|
119
122
|
fetchPrHead,
|
|
@@ -125,8 +128,11 @@ import {
|
|
|
125
128
|
getPrForHeadBranch,
|
|
126
129
|
getPrMeta,
|
|
127
130
|
getPrStack,
|
|
131
|
+
ghHeadRef,
|
|
132
|
+
ghRepoSelectArgs,
|
|
128
133
|
initPrStack,
|
|
129
134
|
isDirty,
|
|
135
|
+
isGhRateLimitError,
|
|
130
136
|
isSideboardScratchPath,
|
|
131
137
|
listWorktrees,
|
|
132
138
|
markPrReady,
|
|
@@ -139,11 +145,12 @@ import {
|
|
|
139
145
|
resolveDefaultBranch,
|
|
140
146
|
resolveDiffBaseRef,
|
|
141
147
|
resolveGithubRepoSlug,
|
|
148
|
+
resolveOriginRemote,
|
|
142
149
|
resolvePrSelector,
|
|
143
150
|
resolveRepoRoot,
|
|
144
151
|
switchWorktreeBranch,
|
|
145
152
|
withRepoGitLock
|
|
146
|
-
} from "./chunk-
|
|
153
|
+
} from "./chunk-UWJUARFA.js";
|
|
147
154
|
import {
|
|
148
155
|
REVIEW_TAB_TITLE,
|
|
149
156
|
agentNicknameFromWorktreePath,
|
|
@@ -171,7 +178,7 @@ import {
|
|
|
171
178
|
worktreeNameFromPath,
|
|
172
179
|
worktreeSlugForTicket,
|
|
173
180
|
writeThread
|
|
174
|
-
} from "./chunk-
|
|
181
|
+
} from "./chunk-IFWGG2M2.js";
|
|
175
182
|
import {
|
|
176
183
|
mcpServerIdForPermission,
|
|
177
184
|
mcpServerPermissionUpdate
|
|
@@ -182,7 +189,7 @@ import {
|
|
|
182
189
|
import {
|
|
183
190
|
applyAgentRunnerHeapEnv,
|
|
184
191
|
packagedMcpDir
|
|
185
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-ZHGMRBSC.js";
|
|
186
193
|
import {
|
|
187
194
|
fallbackTurnFailDetail,
|
|
188
195
|
formatAgentErrorContinuePrompt,
|
|
@@ -202,9 +209,10 @@ import {
|
|
|
202
209
|
clearStaleIndexLocks,
|
|
203
210
|
enrichPathWithNpmGlobalBin,
|
|
204
211
|
ensureAgentPath,
|
|
212
|
+
gh,
|
|
205
213
|
git,
|
|
206
214
|
resolveGitDirsForLockRecovery
|
|
207
|
-
} from "./chunk-
|
|
215
|
+
} from "./chunk-2TUE6JKQ.js";
|
|
208
216
|
import {
|
|
209
217
|
HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
|
|
210
218
|
applyTurnUsage,
|
|
@@ -239,7 +247,10 @@ import {
|
|
|
239
247
|
usageOnLimit,
|
|
240
248
|
withTurnScopedCost,
|
|
241
249
|
writeViewerContext
|
|
242
|
-
} from "./chunk-
|
|
250
|
+
} from "./chunk-FZKAAAEB.js";
|
|
251
|
+
import {
|
|
252
|
+
normalizeThinkingEffort
|
|
253
|
+
} from "./chunk-77WWLBCI.js";
|
|
243
254
|
import {
|
|
244
255
|
examplePrefixedBranch,
|
|
245
256
|
sanitizeGitBranchPrefix
|
|
@@ -461,9 +472,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
461
472
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
462
473
|
);
|
|
463
474
|
}
|
|
464
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
475
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-UPMXDQM7.js");
|
|
465
476
|
if (isGlobalThread2(thread)) {
|
|
466
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
477
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-D5EE2YTV.js");
|
|
467
478
|
ensureGlobalCoordinatorCwd2(
|
|
468
479
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
469
480
|
);
|
|
@@ -679,7 +690,9 @@ function resolveSidebarGitPrompt(action, opts) {
|
|
|
679
690
|
}
|
|
680
691
|
var RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
|
|
681
692
|
var MERGE_INTO_RE = /^Merge PR into (.+)\.$/;
|
|
682
|
-
function gitActionExpansion(action, base) {
|
|
693
|
+
function gitActionExpansion(action, base, forge) {
|
|
694
|
+
if (forge === "cursor") return cursorGitActionExpansion(action, base);
|
|
695
|
+
if (forge === "entire") return entireGitActionExpansion(action, base);
|
|
683
696
|
switch (action) {
|
|
684
697
|
case "commit-push":
|
|
685
698
|
return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Do not start a checks loop unless a goal was given.";
|
|
@@ -704,7 +717,57 @@ function gitActionExpansion(action, base) {
|
|
|
704
717
|
return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
|
|
705
718
|
}
|
|
706
719
|
}
|
|
707
|
-
function
|
|
720
|
+
function cursorGitActionExpansion(action, base) {
|
|
721
|
+
switch (action) {
|
|
722
|
+
case "commit-push":
|
|
723
|
+
return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Use `origin`, not `gh`. Do not start a checks loop unless a goal was given.";
|
|
724
|
+
case "create-draft":
|
|
725
|
+
return "Commit, push, then create a draft PR with `origin pr create --draft --push -R <origin-owner/name> --body-file <short.md>` (title/body from the change purpose). Take the URL from `--json url`. Update the existing PR with `origin pr edit` if one is linked. Do not use `gh`.";
|
|
726
|
+
case "create-web":
|
|
727
|
+
return "Commit, push, then `origin pr create --push -R <origin-owner/name>` and open the URL from `--json url`. Origin has no `--web` form. Add `--draft` when they asked for a draft. Do not use `gh`.";
|
|
728
|
+
case "resolve-conflicts":
|
|
729
|
+
if (base && !isMainishPrBase(base)) {
|
|
730
|
+
return `Fetch \`origin/${base}\` (this PR's base \u2014 not main/master), merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable. Do not merge origin/main.`;
|
|
731
|
+
}
|
|
732
|
+
if (base) {
|
|
733
|
+
return `Fetch the PR base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
|
|
734
|
+
}
|
|
735
|
+
return "Look up this PR's base with `origin pr view --json baseRefName` and merge that remote branch into this branch (do not assume main). Resolve conflicts carefully, then commit and push until the PR is mergeable. Do not use `gh`.";
|
|
736
|
+
case "ready-for-review":
|
|
737
|
+
return "This phrase is the explicit ask to mark this thread's draft pull request ready for review on Cursor (`origin pr ready -R <origin-owner/name>`). Update title/body if the purpose drifted. Do not merge. Do not use `gh`.";
|
|
738
|
+
case "merge":
|
|
739
|
+
if (base && !isMainishPrBase(base)) {
|
|
740
|
+
return `This phrase is the explicit ask to merge this thread's open pull request into \`${base}\` on Cursor with \`origin pr merge\`. This PR targets \`${base}\`, not main \u2014 do not use \`origin stack merge\` and do not retarget or merge into main/master. Do not force-push main/master or merge locally into the main checkout. Do not use \`gh\`.`;
|
|
741
|
+
}
|
|
742
|
+
return "This phrase is the explicit ask to merge this thread's open pull request on Cursor. If `origin stack view` shows a stack, use `origin stack merge`; otherwise `origin pr merge`. Do not force-push main/master or merge locally into the main checkout. Do not use `gh`.";
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
function entireGitActionExpansion(action, base) {
|
|
746
|
+
switch (action) {
|
|
747
|
+
case "commit-push":
|
|
748
|
+
return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`). Use `entire`, not `gh` or `origin`. Do not start a checks loop unless a goal was given.";
|
|
749
|
+
case "create-draft":
|
|
750
|
+
return 'Commit, push, then open a Trail with `entire trail create --title "<title>" --body "<short>"` (title/body from the change purpose). Take the URL from `--json`. If this branch already has a trail, `entire trail update` instead of creating another. Trails have no draft flag. Do not use `gh` or `origin`.';
|
|
751
|
+
case "create-web":
|
|
752
|
+
return 'Commit, push, then `entire trail create --title "<title>" --body "<short>"` and open the URL from `--json`. Entire has no `--web` form. Do not use `gh` or `origin`.';
|
|
753
|
+
case "resolve-conflicts":
|
|
754
|
+
if (base && !isMainishPrBase(base)) {
|
|
755
|
+
return `Fetch \`origin/${base}\` (this Trail's base \u2014 not main/master), merge it into this branch, resolve conflicts carefully, then commit and push. Do not merge origin/main.`;
|
|
756
|
+
}
|
|
757
|
+
if (base) {
|
|
758
|
+
return `Fetch the Trail base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push.`;
|
|
759
|
+
}
|
|
760
|
+
return "Look up this Trail's base with `entire trail show --json` and merge that remote branch into this branch (do not assume main). Resolve conflicts carefully, then commit and push. Do not use `gh`.";
|
|
761
|
+
case "ready-for-review":
|
|
762
|
+
return "This phrase means the Trail should be ready for a person to review. Trails have no draft flag and start open. Update title or body with `entire trail update` if the purpose drifted. Do not approve the trail and do not merge. Do not use `gh`.";
|
|
763
|
+
case "merge":
|
|
764
|
+
if (base && !isMainishPrBase(base)) {
|
|
765
|
+
return `This phrase is the explicit ask to merge this thread's Trail change into \`${base}\` with \`entire trail merge\`. This change targets \`${base}\`, not main \u2014 do not retarget or merge into main/master. Do not force-push main/master or merge locally into the main checkout. Do not use \`gh\`.`;
|
|
766
|
+
}
|
|
767
|
+
return "This phrase is the explicit ask to merge this thread's Trail change with `entire trail merge`. Do not force-push main/master or merge locally into the main checkout. Do not use `gh`.";
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
function expandCanonicalGitRequest(prompt, opts) {
|
|
708
771
|
const trimmed = prompt.trim();
|
|
709
772
|
let action = null;
|
|
710
773
|
let base = null;
|
|
@@ -729,11 +792,12 @@ function expandCanonicalGitRequest(prompt) {
|
|
|
729
792
|
base = m[1]?.trim() || null;
|
|
730
793
|
}
|
|
731
794
|
}
|
|
732
|
-
|
|
795
|
+
const forge = opts?.forge ?? null;
|
|
796
|
+
let expansion = action ? gitActionExpansion(action, base, forge) : null;
|
|
733
797
|
if (!expansion && trimmed === "Address review comments.") {
|
|
734
|
-
expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
|
|
798
|
+
expansion = forge === "cursor" ? "Read the PR review feedback (`origin pr view --comments`, `origin pr thread list`), make the requested changes, commit, and push. Do not use `gh`." : forge === "entire" ? "Read open findings (`entire trail finding list`), make the requested changes, commit, and push. Do not use `gh` or `entire trail comment` (agent sessions cannot post trail comments)." : "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
|
|
735
799
|
} else if (!expansion && FIX_CI_RE.test(trimmed)) {
|
|
736
|
-
expansion = "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
|
|
800
|
+
expansion = forge === "cursor" ? "Investigate that failing check (`origin pr checks`, `origin pr watch`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given. Do not use `gh run`." : forge === "entire" ? "Investigate the blocking gate (`entire trail merge --dry-run`, `entire trail finding list`, `entire trail watch`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given. Do not use `gh run`." : "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
|
|
737
801
|
}
|
|
738
802
|
if (!expansion) return prompt;
|
|
739
803
|
return `${trimmed}
|
|
@@ -2074,6 +2138,71 @@ function claimSteerRequest(threadId) {
|
|
|
2074
2138
|
});
|
|
2075
2139
|
}
|
|
2076
2140
|
|
|
2141
|
+
// src/orchestrator/ephemeral-automation.ts
|
|
2142
|
+
function ephemeralRunReadyToArchive(thread) {
|
|
2143
|
+
if (!thread.ephemeralAutomationId?.trim()) return false;
|
|
2144
|
+
if (thread.status !== "idle" && thread.status !== "error") return false;
|
|
2145
|
+
if (thread.queue.length > 0) return false;
|
|
2146
|
+
if (thread.agentBlock?.reason?.trim()) return false;
|
|
2147
|
+
if (thread.quotaResumeAt) return false;
|
|
2148
|
+
return true;
|
|
2149
|
+
}
|
|
2150
|
+
function markEphemeralAutomation(threadId, opts) {
|
|
2151
|
+
const id = opts.ephemeralAutomationId?.trim();
|
|
2152
|
+
const current = readThread(threadId);
|
|
2153
|
+
if (!current) throw new Error(`Thread not found: ${threadId}`);
|
|
2154
|
+
if (!id) return current;
|
|
2155
|
+
const title = opts.ephemeralTitle?.trim();
|
|
2156
|
+
return updateThread(threadId, {
|
|
2157
|
+
ephemeralAutomationId: id,
|
|
2158
|
+
...title ? { title, userSetTitle: true } : {}
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
async function archiveEphemeralAutomationIfReady(threadId, archive) {
|
|
2162
|
+
const keep = await withThreadLock(threadId, async () => {
|
|
2163
|
+
const thread = readThread(threadId);
|
|
2164
|
+
if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
|
|
2165
|
+
const automationId = thread.ephemeralAutomationId?.trim();
|
|
2166
|
+
if (!automationId) return null;
|
|
2167
|
+
await archive(thread.id);
|
|
2168
|
+
return {
|
|
2169
|
+
automationId,
|
|
2170
|
+
keepId: archivedContinuationId(automationId, threadId) ?? threadId
|
|
2171
|
+
};
|
|
2172
|
+
});
|
|
2173
|
+
if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
|
|
2174
|
+
}
|
|
2175
|
+
function archivedContinuationId(automationId, sourceId) {
|
|
2176
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
2177
|
+
if (thread.id === sourceId || thread.status !== "archived") continue;
|
|
2178
|
+
if (thread.ephemeralAutomationId !== automationId) continue;
|
|
2179
|
+
if (thread.quotaContinuedFromId !== sourceId) continue;
|
|
2180
|
+
return thread.id;
|
|
2181
|
+
}
|
|
2182
|
+
return null;
|
|
2183
|
+
}
|
|
2184
|
+
function clearEphemeralAutomation(threadId) {
|
|
2185
|
+
const thread = readThread(threadId);
|
|
2186
|
+
if (!thread?.ephemeralAutomationId?.trim()) return;
|
|
2187
|
+
updateThread(threadId, { ephemeralAutomationId: void 0 });
|
|
2188
|
+
}
|
|
2189
|
+
function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
2190
|
+
const id = automationId.trim();
|
|
2191
|
+
if (!id || !keepId) return [];
|
|
2192
|
+
const removed = [];
|
|
2193
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
2194
|
+
if (thread.id === keepId) continue;
|
|
2195
|
+
if (thread.status !== "archived") continue;
|
|
2196
|
+
if (thread.ephemeralAutomationId !== id) continue;
|
|
2197
|
+
try {
|
|
2198
|
+
deleteThreadRecord(thread.id);
|
|
2199
|
+
removed.push(thread.id);
|
|
2200
|
+
} catch {
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
return removed;
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2077
2206
|
// src/threads/agent-purpose-title.ts
|
|
2078
2207
|
function agentPurposeStamp(input) {
|
|
2079
2208
|
if (input.autoContinue) return null;
|
|
@@ -2930,7 +3059,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2930
3059
|
});
|
|
2931
3060
|
await requireAgent(resolved.agent);
|
|
2932
3061
|
if (input.cowboy) {
|
|
2933
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
3062
|
+
const { cowboyModeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
2934
3063
|
if (!cowboyModeEnabled()) {
|
|
2935
3064
|
throw new Error(
|
|
2936
3065
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2989,7 +3118,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2989
3118
|
let sourceIsFork = false;
|
|
2990
3119
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
2991
3120
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
2992
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
3121
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-ICW6Q2AB.js");
|
|
2993
3122
|
const task = await ensureAbleTimeTask({
|
|
2994
3123
|
title: title?.trim() || "Untitled work",
|
|
2995
3124
|
description: input.prompt?.trim() || void 0
|
|
@@ -3100,7 +3229,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3100
3229
|
return readThread(thread.id) ?? thread;
|
|
3101
3230
|
}
|
|
3102
3231
|
async function listLinearIssues(agent, repoPath) {
|
|
3103
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3232
|
+
const { getAdapter: getAdapter2 } = await import("./agents-ROFDNE7Z.js");
|
|
3104
3233
|
await requireAgent(agent, { requireLinear: true });
|
|
3105
3234
|
const adapter = getAdapter2(agent);
|
|
3106
3235
|
if (!adapter.listLinearIssues) {
|
|
@@ -3760,17 +3889,23 @@ async function isolateQuotaFailover(run) {
|
|
|
3760
3889
|
}
|
|
3761
3890
|
}
|
|
3762
3891
|
function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
3892
|
+
const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
|
|
3893
|
+
const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
|
|
3763
3894
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
3764
3895
|
const tab = createChatTab({
|
|
3765
3896
|
fromThreadId: from.id,
|
|
3766
3897
|
agent: fallbackAgent,
|
|
3767
3898
|
model: null,
|
|
3768
3899
|
attachments: [handoff],
|
|
3900
|
+
...ephemeralTitle ? { title: ephemeralTitle } : {},
|
|
3769
3901
|
...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
|
|
3770
3902
|
});
|
|
3771
3903
|
const patch = {
|
|
3772
3904
|
quotaContinuedFromId: from.id,
|
|
3773
|
-
sourceRef: from.sourceRef
|
|
3905
|
+
sourceRef: from.sourceRef,
|
|
3906
|
+
// The original drain archives as idle. This sibling has to carry the one-off
|
|
3907
|
+
// so it archives when the continued turn finishes and History keeps it.
|
|
3908
|
+
...ephemeralAutomationId ? { ephemeralAutomationId } : {}
|
|
3774
3909
|
};
|
|
3775
3910
|
if (isOrchestratorThread(from)) {
|
|
3776
3911
|
patch.parentThreadId = from.id;
|
|
@@ -3862,7 +3997,7 @@ async function adoptThread(input) {
|
|
|
3862
3997
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
3863
3998
|
}
|
|
3864
3999
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
3865
|
-
const { stdout: branch } = await import("./run-
|
|
4000
|
+
const { stdout: branch } = await import("./run-7QMRYP3F.js").then(
|
|
3866
4001
|
({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
|
|
3867
4002
|
);
|
|
3868
4003
|
const thread = createEmptyThread({
|
|
@@ -3877,9 +4012,9 @@ async function adoptThread(input) {
|
|
|
3877
4012
|
messages: input.messages ?? []
|
|
3878
4013
|
});
|
|
3879
4014
|
writeThread(thread);
|
|
3880
|
-
const { addWorkspace: addWorkspace2 } = await import("./workspaces-
|
|
4015
|
+
const { addWorkspace: addWorkspace2 } = await import("./workspaces-47WQL5IG.js");
|
|
3881
4016
|
await addWorkspace2(repoPath);
|
|
3882
|
-
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-
|
|
4017
|
+
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-INRDQFWV.js");
|
|
3883
4018
|
await ensureWorktreeSideboardIgnored(input.worktreePath);
|
|
3884
4019
|
return thread;
|
|
3885
4020
|
}
|
|
@@ -4371,9 +4506,177 @@ function stackAgentDefaultsFrom(input) {
|
|
|
4371
4506
|
};
|
|
4372
4507
|
}
|
|
4373
4508
|
|
|
4509
|
+
// src/git/pr-write.ts
|
|
4510
|
+
import { randomBytes } from "crypto";
|
|
4511
|
+
import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
|
|
4512
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
4513
|
+
import { join as join8 } from "path";
|
|
4514
|
+
async function lookupGithubGraphqlReset(cwd) {
|
|
4515
|
+
const result = await gh(["api", "rate_limit"], cwd, { reject: false });
|
|
4516
|
+
if (result.exitCode !== 0 || !result.stdout.trim()) return void 0;
|
|
4517
|
+
try {
|
|
4518
|
+
const data = JSON.parse(result.stdout);
|
|
4519
|
+
const reset = data.resources?.graphql?.reset;
|
|
4520
|
+
return typeof reset === "number" ? reset : void 0;
|
|
4521
|
+
} catch {
|
|
4522
|
+
return void 0;
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
async function formatPrCreateFailure(raw, cwd, ctx) {
|
|
4526
|
+
if (!isGhRateLimitError(raw)) {
|
|
4527
|
+
return formatGhLandError(raw, {
|
|
4528
|
+
targetedRepo: ctx?.slug,
|
|
4529
|
+
headRef: ctx?.head
|
|
4530
|
+
});
|
|
4531
|
+
}
|
|
4532
|
+
const resetAt = await lookupGithubGraphqlReset(cwd);
|
|
4533
|
+
return formatGhLandError(raw, {
|
|
4534
|
+
resetAt,
|
|
4535
|
+
targetedRepo: ctx?.slug,
|
|
4536
|
+
headRef: ctx?.head
|
|
4537
|
+
});
|
|
4538
|
+
}
|
|
4539
|
+
async function createCursorPullRequest(worktreePath, slug, opts) {
|
|
4540
|
+
const bodyText = (opts.body ?? opts.title).trim() || opts.title;
|
|
4541
|
+
const bodyFile = join8(
|
|
4542
|
+
tmpdir2(),
|
|
4543
|
+
`sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
|
|
4544
|
+
);
|
|
4545
|
+
writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
|
|
4546
|
+
`, "utf8");
|
|
4547
|
+
try {
|
|
4548
|
+
return await createOrUpdateCursorPr(worktreePath, slug, {
|
|
4549
|
+
title: opts.title,
|
|
4550
|
+
bodyFile,
|
|
4551
|
+
base: opts.base,
|
|
4552
|
+
head: opts.head,
|
|
4553
|
+
draft: opts.draft
|
|
4554
|
+
});
|
|
4555
|
+
} finally {
|
|
4556
|
+
try {
|
|
4557
|
+
unlinkSync3(bodyFile);
|
|
4558
|
+
} catch {
|
|
4559
|
+
}
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
function ghPrCreateAssigneeArgs(assignee) {
|
|
4563
|
+
const raw = assignee?.trim();
|
|
4564
|
+
if (raw && /^(none|unassigned)$/i.test(raw)) return [];
|
|
4565
|
+
return ["--assignee", raw || "@me"];
|
|
4566
|
+
}
|
|
4567
|
+
async function createOrUpdatePr(worktreePath, opts) {
|
|
4568
|
+
const origin = await resolveOriginRemote(worktreePath);
|
|
4569
|
+
if (origin?.forge === "entire") throw entireUsesTrails();
|
|
4570
|
+
const cursorSlug = origin?.forge === "cursor" ? origin.slug : null;
|
|
4571
|
+
if (cursorSlug) return createCursorPullRequest(worktreePath, cursorSlug, opts);
|
|
4572
|
+
await ensureGhPreferOrigin(worktreePath);
|
|
4573
|
+
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
4574
|
+
if (!slug) {
|
|
4575
|
+
throw new Error(
|
|
4576
|
+
"Could not resolve the origin GitHub repo (owner/name) for this worktree. Check that `git remote get-url origin` points at github.com."
|
|
4577
|
+
);
|
|
4578
|
+
}
|
|
4579
|
+
const repoArgs = ghRepoSelectArgs(slug);
|
|
4580
|
+
const headRef = ghHeadRef(slug, opts.head);
|
|
4581
|
+
const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
|
|
4582
|
+
const bodyText = clampGithubPrBody(opts.body ?? opts.title);
|
|
4583
|
+
const bodyFile = join8(
|
|
4584
|
+
tmpdir2(),
|
|
4585
|
+
`sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
|
|
4586
|
+
);
|
|
4587
|
+
writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
|
|
4588
|
+
`, "utf8");
|
|
4589
|
+
const bodyArgs = ["--body-file", bodyFile];
|
|
4590
|
+
try {
|
|
4591
|
+
return await createOrUpdatePrWithBodyFile(worktreePath, {
|
|
4592
|
+
...opts,
|
|
4593
|
+
slug,
|
|
4594
|
+
repoArgs,
|
|
4595
|
+
headRef,
|
|
4596
|
+
branchOnly,
|
|
4597
|
+
bodyArgs
|
|
4598
|
+
});
|
|
4599
|
+
} finally {
|
|
4600
|
+
try {
|
|
4601
|
+
unlinkSync3(bodyFile);
|
|
4602
|
+
} catch {
|
|
4603
|
+
}
|
|
4604
|
+
}
|
|
4605
|
+
}
|
|
4606
|
+
async function createOrUpdatePrWithBodyFile(worktreePath, opts) {
|
|
4607
|
+
const { slug, repoArgs, headRef, branchOnly, bodyArgs } = opts;
|
|
4608
|
+
const existing = await gh(
|
|
4609
|
+
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
4610
|
+
worktreePath,
|
|
4611
|
+
{ reject: false }
|
|
4612
|
+
);
|
|
4613
|
+
if (existing.exitCode === 0 && existing.stdout.trim() && !opts.web) {
|
|
4614
|
+
const url2 = existing.stdout.trim();
|
|
4615
|
+
await gh(
|
|
4616
|
+
[
|
|
4617
|
+
...repoArgs,
|
|
4618
|
+
"pr",
|
|
4619
|
+
"edit",
|
|
4620
|
+
branchOnly,
|
|
4621
|
+
"--title",
|
|
4622
|
+
opts.title,
|
|
4623
|
+
...bodyArgs
|
|
4624
|
+
],
|
|
4625
|
+
worktreePath,
|
|
4626
|
+
{ reject: false }
|
|
4627
|
+
);
|
|
4628
|
+
return url2;
|
|
4629
|
+
}
|
|
4630
|
+
if (opts.web) {
|
|
4631
|
+
const args2 = [
|
|
4632
|
+
...repoArgs,
|
|
4633
|
+
"pr",
|
|
4634
|
+
"create",
|
|
4635
|
+
"--web",
|
|
4636
|
+
"--title",
|
|
4637
|
+
opts.title,
|
|
4638
|
+
...bodyArgs,
|
|
4639
|
+
"--base",
|
|
4640
|
+
opts.base,
|
|
4641
|
+
"--head",
|
|
4642
|
+
headRef
|
|
4643
|
+
];
|
|
4644
|
+
if (opts.draft) args2.push("--draft");
|
|
4645
|
+
args2.push(...ghPrCreateAssigneeArgs(opts.assignee));
|
|
4646
|
+
await gh(args2, worktreePath, { reject: false });
|
|
4647
|
+
const again = await gh(
|
|
4648
|
+
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
4649
|
+
worktreePath,
|
|
4650
|
+
{ reject: false }
|
|
4651
|
+
);
|
|
4652
|
+
return again.stdout.trim() || "";
|
|
4653
|
+
}
|
|
4654
|
+
const args = [
|
|
4655
|
+
...repoArgs,
|
|
4656
|
+
"pr",
|
|
4657
|
+
"create",
|
|
4658
|
+
"--title",
|
|
4659
|
+
opts.title,
|
|
4660
|
+
...bodyArgs,
|
|
4661
|
+
"--base",
|
|
4662
|
+
opts.base,
|
|
4663
|
+
"--head",
|
|
4664
|
+
headRef
|
|
4665
|
+
];
|
|
4666
|
+
if (opts.draft) args.push("--draft");
|
|
4667
|
+
args.push(...ghPrCreateAssigneeArgs(opts.assignee));
|
|
4668
|
+
const created = await gh(args, worktreePath, { reject: false });
|
|
4669
|
+
if (created.exitCode !== 0) {
|
|
4670
|
+
const raw = created.stderr.trim() || created.stdout.trim() || "gh pr create failed";
|
|
4671
|
+
throw new Error(await formatPrCreateFailure(raw, worktreePath, { slug, head: headRef }));
|
|
4672
|
+
}
|
|
4673
|
+
const url = created.stdout.trim().split("\n").find((l) => l.startsWith("http")) ?? created.stdout.trim();
|
|
4674
|
+
return url;
|
|
4675
|
+
}
|
|
4676
|
+
|
|
4374
4677
|
// src/diff/diff.ts
|
|
4375
|
-
import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as
|
|
4376
|
-
import { dirname as dirname2, join as
|
|
4678
|
+
import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
4679
|
+
import { dirname as dirname2, join as join9 } from "path";
|
|
4377
4680
|
async function inspectGitWorktree(worktreePath) {
|
|
4378
4681
|
if (!worktreePath || !existsSync9(worktreePath)) return "missing_worktree";
|
|
4379
4682
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
@@ -4519,7 +4822,7 @@ new file mode 100644
|
|
|
4519
4822
|
};
|
|
4520
4823
|
}
|
|
4521
4824
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
4522
|
-
const abs =
|
|
4825
|
+
const abs = join9(worktreePath, path);
|
|
4523
4826
|
try {
|
|
4524
4827
|
const st = statSync2(abs);
|
|
4525
4828
|
if (st.isFile() && st.size > maxHunk) {
|
|
@@ -4991,7 +5294,7 @@ async function getDiff(worktreePath, repoPath, opts) {
|
|
|
4991
5294
|
}
|
|
4992
5295
|
function statWorktreePath(worktreePath, relativePath) {
|
|
4993
5296
|
assertSafeRelativePath(relativePath);
|
|
4994
|
-
const abs =
|
|
5297
|
+
const abs = join9(worktreePath, relativePath);
|
|
4995
5298
|
if (!existsSync9(abs)) return "missing";
|
|
4996
5299
|
const st = statSync2(abs);
|
|
4997
5300
|
if (st.isDirectory()) return "dir";
|
|
@@ -5033,7 +5336,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
5033
5336
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
5034
5337
|
assertSafeRelativePath(relativePath);
|
|
5035
5338
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
5036
|
-
const abs =
|
|
5339
|
+
const abs = join9(worktreePath, relativePath);
|
|
5037
5340
|
const st = statSync2(abs);
|
|
5038
5341
|
if (!st.isFile()) {
|
|
5039
5342
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5053,7 +5356,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
5053
5356
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
5054
5357
|
assertSafeRelativePath(relativePath);
|
|
5055
5358
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
5056
|
-
const abs =
|
|
5359
|
+
const abs = join9(worktreePath, relativePath);
|
|
5057
5360
|
const st = statSync2(abs);
|
|
5058
5361
|
if (!st.isFile()) {
|
|
5059
5362
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5101,9 +5404,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
5101
5404
|
}
|
|
5102
5405
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
5103
5406
|
assertSafeRelativePath(relativePath);
|
|
5104
|
-
const abs =
|
|
5407
|
+
const abs = join9(worktreePath, relativePath);
|
|
5105
5408
|
mkdirSync(dirname2(abs), { recursive: true });
|
|
5106
|
-
|
|
5409
|
+
writeFileSync6(abs, content, "utf8");
|
|
5107
5410
|
return { path: relativePath };
|
|
5108
5411
|
}
|
|
5109
5412
|
async function getWorktreeDirtyStat(worktreePath) {
|
|
@@ -5295,7 +5598,7 @@ async function confirmLand(thread, opts) {
|
|
|
5295
5598
|
if (preview.dirty) {
|
|
5296
5599
|
committed = await commitAll(thread.worktreePath, meta.commitMessage);
|
|
5297
5600
|
}
|
|
5298
|
-
const { git: git2 } = await import("./run-
|
|
5601
|
+
const { git: git2 } = await import("./run-7QMRYP3F.js");
|
|
5299
5602
|
const { stdout: headOut } = await git2(
|
|
5300
5603
|
["rev-parse", "--abbrev-ref", "HEAD"],
|
|
5301
5604
|
thread.worktreePath,
|
|
@@ -5326,13 +5629,13 @@ async function confirmLand(thread, opts) {
|
|
|
5326
5629
|
|
|
5327
5630
|
// src/diff/read-worktree-tail.ts
|
|
5328
5631
|
import { closeSync, fstatSync, openSync, readSync } from "fs";
|
|
5329
|
-
import { join as
|
|
5632
|
+
import { join as join10 } from "path";
|
|
5330
5633
|
var WORKTREE_TAIL_BYTES = 2e5;
|
|
5331
5634
|
function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TAIL_BYTES) {
|
|
5332
5635
|
if (!relativePath || relativePath.includes("..") || relativePath.startsWith("/")) {
|
|
5333
5636
|
throw new Error("Invalid path");
|
|
5334
5637
|
}
|
|
5335
|
-
const abs =
|
|
5638
|
+
const abs = join10(worktreePath, relativePath);
|
|
5336
5639
|
const fd = openSync(abs, "r");
|
|
5337
5640
|
try {
|
|
5338
5641
|
const st = fstatSync(fd);
|
|
@@ -5366,7 +5669,7 @@ function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TA
|
|
|
5366
5669
|
// src/skills/discover.ts
|
|
5367
5670
|
import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
|
|
5368
5671
|
import { homedir } from "os";
|
|
5369
|
-
import { join as
|
|
5672
|
+
import { join as join11 } from "path";
|
|
5370
5673
|
|
|
5371
5674
|
// src/skills/bundled/long-running.ts
|
|
5372
5675
|
var LONG_RUNNING_SKILL_COMMAND = "long-running";
|
|
@@ -5535,7 +5838,7 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5535
5838
|
}
|
|
5536
5839
|
for (const entry of entries) {
|
|
5537
5840
|
if (entry.startsWith(".")) continue;
|
|
5538
|
-
const skillMd =
|
|
5841
|
+
const skillMd = join11(dir, entry, "SKILL.md");
|
|
5539
5842
|
if (!existsSync10(skillMd)) continue;
|
|
5540
5843
|
try {
|
|
5541
5844
|
if (!statSync3(skillMd).isFile()) continue;
|
|
@@ -5557,12 +5860,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
5557
5860
|
return;
|
|
5558
5861
|
}
|
|
5559
5862
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
5560
|
-
const skill = readSkill(
|
|
5863
|
+
const skill = readSkill(join11(dir, "SKILL.md"), "cli");
|
|
5561
5864
|
if (skill) out.push(skill);
|
|
5562
5865
|
}
|
|
5563
5866
|
for (const entry of entries) {
|
|
5564
5867
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
5565
|
-
const full =
|
|
5868
|
+
const full = join11(dir, entry);
|
|
5566
5869
|
try {
|
|
5567
5870
|
if (!statSync3(full).isDirectory()) continue;
|
|
5568
5871
|
} catch {
|
|
@@ -5582,17 +5885,17 @@ function discoverSkills(worktreePath) {
|
|
|
5582
5885
|
const home = homedir();
|
|
5583
5886
|
const collected = [];
|
|
5584
5887
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
5585
|
-
scanSkillsDir(
|
|
5888
|
+
scanSkillsDir(join11(worktreePath, rel), "workspace", collected);
|
|
5586
5889
|
}
|
|
5587
5890
|
for (const abs of [
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5891
|
+
join11(home, ".claude/skills"),
|
|
5892
|
+
join11(home, ".cursor/skills"),
|
|
5893
|
+
join11(home, ".sideboard/skills"),
|
|
5894
|
+
join11(home, ".brightsy/skills")
|
|
5592
5895
|
]) {
|
|
5593
5896
|
scanSkillsDir(abs, "user", collected);
|
|
5594
5897
|
}
|
|
5595
|
-
scanClaudePluginSkills(
|
|
5898
|
+
scanClaudePluginSkills(join11(home, ".claude/plugins"), collected);
|
|
5596
5899
|
collected.push(...bundledSkills());
|
|
5597
5900
|
const rank = {
|
|
5598
5901
|
workspace: 0,
|
|
@@ -5820,7 +6123,7 @@ function promptForJoinedSteer(input) {
|
|
|
5820
6123
|
rewriteTrailingUserPrompt(input.threadId, input.promptText, input.latestPrompt);
|
|
5821
6124
|
const { agentPrompt: expandedLatest } = expandComposerPrompt(
|
|
5822
6125
|
input.worktreePath,
|
|
5823
|
-
expandCanonicalGitRequest(input.latestPrompt),
|
|
6126
|
+
expandCanonicalGitRequest(input.latestPrompt, { forge: input.gitForge }),
|
|
5824
6127
|
{ attachments: input.attachments }
|
|
5825
6128
|
);
|
|
5826
6129
|
return input.expandedPrompt && input.agentPrompt.endsWith(input.expandedPrompt) ? input.agentPrompt.slice(0, -input.expandedPrompt.length) + expandedLatest : `${input.agentPrompt}
|
|
@@ -5916,11 +6219,33 @@ async function enqueueThreadSend(host, threadRef, prompt, opts) {
|
|
|
5916
6219
|
|
|
5917
6220
|
// src/agents/instructions.ts
|
|
5918
6221
|
import { existsSync as existsSync12 } from "fs";
|
|
5919
|
-
import { join as
|
|
6222
|
+
import { join as join13 } from "path";
|
|
6223
|
+
|
|
6224
|
+
// src/agents/forge-git-directives.ts
|
|
6225
|
+
function formatCursorGitDirective(slug) {
|
|
6226
|
+
const repo = slug?.trim() || "<origin-owner/name>";
|
|
6227
|
+
return [
|
|
6228
|
+
`Git host (Settings \u2192 Git \u2192 Cursor): this checkout is on Cursor (\`origin.cursor.com\`, \`${repo}\`).`,
|
|
6229
|
+
"- Use the `origin` CLI, not `gh`. Where commands overlap, flags follow `gh` (`origin <command> --help`).",
|
|
6230
|
+
"- `origin` already authenticates from `CURSOR_AUTH_TOKEN`, then `CURSOR_API_KEY`, then the login stored in Settings \u2192 Git \u2192 Cursor. Do not read those values, set them, or run `origin auth login` from this turn.",
|
|
6231
|
+
"- Push with `git push -u origin HEAD`. If git asks for credentials, tell the user to open Settings \u2192 Git \u2192 Cursor and choose Configure git (`origin auth setup-git`). Do not wait for a Keychain dialog.",
|
|
6232
|
+
"- Origin has no issue tracker. Tickets for this repo come from Linear or AbleTime via `list_issues`. Do not use `gh issue`."
|
|
6233
|
+
].join("\n");
|
|
6234
|
+
}
|
|
6235
|
+
function formatEntireGitDirective(slug) {
|
|
6236
|
+
const repo = slug?.trim() || "<origin-owner/name>";
|
|
6237
|
+
return [
|
|
6238
|
+
`Git host (Settings \u2192 Git \u2192 Entire): this checkout is on Entire (\`${repo}\`).`,
|
|
6239
|
+
"- Use the `entire` CLI, not `gh` or `origin`. Trails replace pull requests and GitHub issues.",
|
|
6240
|
+
"- `entire` uses the login from Settings \u2192 Git \u2192 Entire. Do not read tokens, set `ENTIRE_TOKEN`, or run `entire login` from this turn.",
|
|
6241
|
+
"- Push with `git push -u origin HEAD`. If git asks for credentials, tell the user to open Settings \u2192 Git \u2192 Entire and log in. Do not wait for a Keychain dialog.",
|
|
6242
|
+
"- Tickets for this repo are Trails (`entire trail list` / `entire trail show`). Do not use `gh issue`."
|
|
6243
|
+
].join("\n");
|
|
6244
|
+
}
|
|
5920
6245
|
|
|
5921
6246
|
// src/skills/detached-job-path.ts
|
|
5922
6247
|
import { existsSync as existsSync11 } from "fs";
|
|
5923
|
-
import { dirname as dirname3, join as
|
|
6248
|
+
import { dirname as dirname3, join as join12 } from "path";
|
|
5924
6249
|
import { fileURLToPath } from "url";
|
|
5925
6250
|
var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
|
|
5926
6251
|
function compiledModuleDir() {
|
|
@@ -5937,7 +6262,7 @@ function compiledModuleDir() {
|
|
|
5937
6262
|
}
|
|
5938
6263
|
function detachedJobScriptIn(dir) {
|
|
5939
6264
|
for (const name of DETACHED_JOB_FILENAMES) {
|
|
5940
|
-
const script =
|
|
6265
|
+
const script = join12(dir, "scripts", name);
|
|
5941
6266
|
if (existsSync11(script)) return script;
|
|
5942
6267
|
}
|
|
5943
6268
|
return null;
|
|
@@ -6047,17 +6372,35 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
6047
6372
|
lines.push(
|
|
6048
6373
|
"- Always use this worktree's `origin` remote (`git remote get-url origin` from this cwd). Never push to or open PRs against `upstream` (template remotes)."
|
|
6049
6374
|
);
|
|
6050
|
-
|
|
6375
|
+
const cursorRepo = opts?.originForge === "cursor";
|
|
6376
|
+
const entireRepo = opts?.originForge === "entire";
|
|
6377
|
+
if (cursorRepo) {
|
|
6378
|
+
lines.push(formatCursorGitDirective(opts?.originSlug));
|
|
6379
|
+
} else if (entireRepo) {
|
|
6380
|
+
lines.push(formatEntireGitDirective(opts?.originSlug));
|
|
6381
|
+
} else {
|
|
6382
|
+
lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
|
|
6383
|
+
}
|
|
6051
6384
|
lines.push(
|
|
6052
6385
|
"- PR title/body and commit messages state what the change does and why (inspect the diff/commits and the user request) \u2014 never the worktree nickname or placeholder branch. Concise imperative title (Conventional Commits when it fits: feat:/fix:/chore:/docs:); body = intent, key changes, test notes."
|
|
6053
6386
|
);
|
|
6054
6387
|
lines.push(
|
|
6055
|
-
"- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
6388
|
+
cursorRepo ? "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via Origin from this worktree (`origin pr merge` / `origin stack merge`)." : entireRepo ? "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge only when this turn is a Merge PR request or the user explicitly asked \u2014 via Entire from this worktree (`entire trail merge`)." : "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
6056
6389
|
);
|
|
6057
6390
|
if (thread.prUrl) {
|
|
6058
6391
|
lines.push(
|
|
6059
6392
|
`- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
|
|
6060
6393
|
);
|
|
6394
|
+
} else if (entireRepo) {
|
|
6395
|
+
lines.push(
|
|
6396
|
+
'- Prefer a Trail: `entire trail create --title "<title>" --body "<short>"`. Take the URL from `--json`. If this branch already has a trail, `entire trail update` instead of creating another. Trails have no draft state. Do not use `gh` or `origin`.'
|
|
6397
|
+
);
|
|
6398
|
+
} else if (cursorRepo) {
|
|
6399
|
+
const slug = opts?.originSlug?.trim() || "<origin-owner/name>";
|
|
6400
|
+
const resolve = opts?.originSlug?.trim() ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
6401
|
+
lines.push(
|
|
6402
|
+
`- Prefer a draft PR first: \`origin pr create --draft --push -R ${slug}\` (update via \`origin pr edit -R ${slug}\`). Take the URL from \`--json url\` \u2014 do not build it. Do not use \`gh\`.${resolve} Mark ready only when asked (\`origin pr ready\`). If the body is too long, retry with a short \`--body-file\`.`
|
|
6403
|
+
);
|
|
6061
6404
|
} else {
|
|
6062
6405
|
const slug = opts?.githubSlug ?? "<origin-owner/name>";
|
|
6063
6406
|
const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
@@ -6072,7 +6415,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
6072
6415
|
lines.push(formatDevAccessHint(opts?.activeRuns));
|
|
6073
6416
|
lines.push("");
|
|
6074
6417
|
lines.push(
|
|
6075
|
-
"
|
|
6418
|
+
"Automations (sidebar, after Board): `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while automations are enabled."
|
|
6076
6419
|
);
|
|
6077
6420
|
lines.push(
|
|
6078
6421
|
"`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
|
|
@@ -6092,7 +6435,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
|
|
|
6092
6435
|
return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
|
|
6093
6436
|
}
|
|
6094
6437
|
function formatWorktreeReminder() {
|
|
6095
|
-
return "Sideboard workspace: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push.
|
|
6438
|
+
return "Sideboard workspace: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Automations: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
|
|
6096
6439
|
}
|
|
6097
6440
|
function formatClaudeSubagentReminder() {
|
|
6098
6441
|
return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself. That note is another worker in this chat, or a worker Claude still has marked running. Do not mention it to the user.';
|
|
@@ -6200,9 +6543,9 @@ function formatPrGateDirective() {
|
|
|
6200
6543
|
}
|
|
6201
6544
|
function formatProcessGuideDirective(opts) {
|
|
6202
6545
|
const worktree = opts?.worktreePath?.trim();
|
|
6203
|
-
const hasGraphSkill = !!worktree && existsSync12(
|
|
6204
|
-
const hasReviewSkill = !!worktree && existsSync12(
|
|
6205
|
-
const hasInstallSkill = !!worktree && existsSync12(
|
|
6546
|
+
const hasGraphSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
6547
|
+
const hasReviewSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/review/SKILL.md"));
|
|
6548
|
+
const hasInstallSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/worktree-install/SKILL.md"));
|
|
6206
6549
|
return [
|
|
6207
6550
|
"Process guides (recurring work only):",
|
|
6208
6551
|
hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
|
|
@@ -6356,6 +6699,7 @@ function compactIssueRow(issue, opts) {
|
|
|
6356
6699
|
function formatMcpIssueList(input) {
|
|
6357
6700
|
const truncated = input.truncated || Boolean(input.commentsTruncated);
|
|
6358
6701
|
const comments = input.comments ?? [];
|
|
6702
|
+
const pageHint = input.unavailableReason ? input.unavailableReason : truncated ? input.since ? "More issues or comments match. Pass a higher limit (max 250) or a tighter query." : "More issues match. Pass a higher limit (max 250) or a tighter query." : void 0;
|
|
6359
6703
|
return {
|
|
6360
6704
|
...input.source ? { source: input.source } : {},
|
|
6361
6705
|
...input.viewer ? { viewer: input.viewer } : {},
|
|
@@ -6363,9 +6707,8 @@ function formatMcpIssueList(input) {
|
|
|
6363
6707
|
returned: input.issues.length,
|
|
6364
6708
|
truncated,
|
|
6365
6709
|
...input.since ? { since: input.since } : {},
|
|
6366
|
-
...
|
|
6367
|
-
|
|
6368
|
-
} : {},
|
|
6710
|
+
...input.unavailableReason ? { unavailableReason: input.unavailableReason } : {},
|
|
6711
|
+
...pageHint ? { hint: pageHint } : {},
|
|
6369
6712
|
issues: input.issues.map((issue) => compactIssueRow(issue, { since: input.since })),
|
|
6370
6713
|
...input.since || comments.length > 0 ? { comments } : {}
|
|
6371
6714
|
};
|
|
@@ -6382,7 +6725,8 @@ function formatListedIssuesForMcp(result, page) {
|
|
|
6382
6725
|
truncated: windowed.truncated,
|
|
6383
6726
|
since: result.since,
|
|
6384
6727
|
comments: commentWindow.items,
|
|
6385
|
-
commentsTruncated: commentWindow.truncated
|
|
6728
|
+
commentsTruncated: commentWindow.truncated,
|
|
6729
|
+
unavailableReason: result.unavailableReason
|
|
6386
6730
|
});
|
|
6387
6731
|
}
|
|
6388
6732
|
function mcpJson(payload, isError = false) {
|
|
@@ -6710,7 +7054,7 @@ async function syncThreadBranchFromGit(threadId) {
|
|
|
6710
7054
|
// src/store/schedules.ts
|
|
6711
7055
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
6712
7056
|
import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
|
|
6713
|
-
import { join as
|
|
7057
|
+
import { join as join14 } from "path";
|
|
6714
7058
|
import { Cron } from "croner";
|
|
6715
7059
|
var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
6716
7060
|
var UNIT_MS = {
|
|
@@ -6720,7 +7064,7 @@ var UNIT_MS = {
|
|
|
6720
7064
|
d: 864e5
|
|
6721
7065
|
};
|
|
6722
7066
|
function schedulesPath() {
|
|
6723
|
-
return
|
|
7067
|
+
return join14(appDataDir(), "schedules.json");
|
|
6724
7068
|
}
|
|
6725
7069
|
function parseDurationMs(every) {
|
|
6726
7070
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -6732,7 +7076,7 @@ function parseDurationMs(every) {
|
|
|
6732
7076
|
}
|
|
6733
7077
|
function defaultScheduleName(prompt) {
|
|
6734
7078
|
const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
6735
|
-
if (!line) return "Untitled
|
|
7079
|
+
if (!line) return "Untitled automation";
|
|
6736
7080
|
return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
|
|
6737
7081
|
}
|
|
6738
7082
|
function resolveScheduleThreadId(raw, env = process.env) {
|
|
@@ -6803,6 +7147,45 @@ function normalizeWhen(raw) {
|
|
|
6803
7147
|
}
|
|
6804
7148
|
throw new Error("Schedule `when` must be once, every, or cron");
|
|
6805
7149
|
}
|
|
7150
|
+
var ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
|
|
7151
|
+
"transcript",
|
|
7152
|
+
"file",
|
|
7153
|
+
"issue",
|
|
7154
|
+
"workspace",
|
|
7155
|
+
"diff-comment",
|
|
7156
|
+
"code-ref"
|
|
7157
|
+
]);
|
|
7158
|
+
function normalizeOptionalBool(raw) {
|
|
7159
|
+
if (raw === true || raw === false) return raw;
|
|
7160
|
+
return null;
|
|
7161
|
+
}
|
|
7162
|
+
function normalizeAutonomy(raw) {
|
|
7163
|
+
return raw === "default" || raw === "full" ? raw : null;
|
|
7164
|
+
}
|
|
7165
|
+
function normalizeAttachments(raw) {
|
|
7166
|
+
if (!Array.isArray(raw)) return [];
|
|
7167
|
+
const out = [];
|
|
7168
|
+
for (const item of raw) {
|
|
7169
|
+
if (!item || typeof item !== "object") continue;
|
|
7170
|
+
const row = item;
|
|
7171
|
+
if (typeof row.id !== "string" || !row.id.trim()) continue;
|
|
7172
|
+
if (typeof row.name !== "string" || !row.name) continue;
|
|
7173
|
+
if (typeof row.content !== "string") continue;
|
|
7174
|
+
if (!ATTACHMENT_KINDS.has(row.kind)) continue;
|
|
7175
|
+
const next = {
|
|
7176
|
+
id: row.id,
|
|
7177
|
+
name: row.name,
|
|
7178
|
+
kind: row.kind,
|
|
7179
|
+
content: row.content
|
|
7180
|
+
};
|
|
7181
|
+
if (typeof row.path === "string" && row.path) next.path = row.path;
|
|
7182
|
+
if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
|
|
7183
|
+
next.previewDataUrl = row.previewDataUrl;
|
|
7184
|
+
}
|
|
7185
|
+
out.push(next);
|
|
7186
|
+
}
|
|
7187
|
+
return out;
|
|
7188
|
+
}
|
|
6806
7189
|
function normalizeTask(raw) {
|
|
6807
7190
|
const when = normalizeWhen(raw.when);
|
|
6808
7191
|
const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
|
|
@@ -6815,6 +7198,11 @@ function normalizeTask(raw) {
|
|
|
6815
7198
|
threadId: raw.threadId?.trim() || null,
|
|
6816
7199
|
agent,
|
|
6817
7200
|
model: raw.model?.trim() || null,
|
|
7201
|
+
effort: normalizeThinkingEffort(raw.effort),
|
|
7202
|
+
fast: normalizeOptionalBool(raw.fast),
|
|
7203
|
+
planMode: normalizeOptionalBool(raw.planMode),
|
|
7204
|
+
autonomy: normalizeAutonomy(raw.autonomy),
|
|
7205
|
+
attachments: normalizeAttachments(raw.attachments),
|
|
6818
7206
|
nextRunAt: raw.nextRunAt,
|
|
6819
7207
|
lastRunAt: raw.lastRunAt ?? null,
|
|
6820
7208
|
lastThreadId: raw.lastThreadId ?? null,
|
|
@@ -6861,6 +7249,11 @@ function buildTask(input, now) {
|
|
|
6861
7249
|
threadId: input.threadId?.trim() || null,
|
|
6862
7250
|
agent,
|
|
6863
7251
|
model: input.model?.trim() || null,
|
|
7252
|
+
effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
|
|
7253
|
+
fast: normalizeOptionalBool(input.fast),
|
|
7254
|
+
planMode: normalizeOptionalBool(input.planMode),
|
|
7255
|
+
autonomy: normalizeAutonomy(input.autonomy),
|
|
7256
|
+
attachments: normalizeAttachments(input.attachments),
|
|
6864
7257
|
nextRunAt,
|
|
6865
7258
|
lastRunAt: null,
|
|
6866
7259
|
lastThreadId: null,
|
|
@@ -6905,7 +7298,7 @@ function createSchedule(input) {
|
|
|
6905
7298
|
function updateSchedule(id, patch) {
|
|
6906
7299
|
const rows = readAll();
|
|
6907
7300
|
const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
|
|
6908
|
-
if (idx < 0) throw new Error(`
|
|
7301
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6909
7302
|
const prev = rows[idx];
|
|
6910
7303
|
const when = patch.when ? normalizeWhen(patch.when) : prev.when;
|
|
6911
7304
|
const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
|
|
@@ -6920,6 +7313,11 @@ function updateSchedule(id, patch) {
|
|
|
6920
7313
|
threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
|
|
6921
7314
|
agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
|
|
6922
7315
|
model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
|
|
7316
|
+
effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
|
|
7317
|
+
fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
|
|
7318
|
+
planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
|
|
7319
|
+
autonomy: patch.autonomy !== void 0 ? normalizeAutonomy(patch.autonomy) : prev.autonomy,
|
|
7320
|
+
attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
|
|
6923
7321
|
nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
|
|
6924
7322
|
lastError: whenChanged ? null : prev.lastError,
|
|
6925
7323
|
updatedAt: nowIso()
|
|
@@ -6934,13 +7332,13 @@ function deleteSchedule(id) {
|
|
|
6934
7332
|
const next = rows.filter(
|
|
6935
7333
|
(row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
|
|
6936
7334
|
);
|
|
6937
|
-
if (next.length === rows.length) throw new Error(`
|
|
7335
|
+
if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
|
|
6938
7336
|
writeAll(next);
|
|
6939
7337
|
}
|
|
6940
7338
|
function recordScheduleRun(id, result) {
|
|
6941
7339
|
const rows = readAll();
|
|
6942
7340
|
const idx = rows.findIndex((row) => row.id === id);
|
|
6943
|
-
if (idx < 0) throw new Error(`
|
|
7341
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6944
7342
|
const prev = rows[idx];
|
|
6945
7343
|
const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
|
|
6946
7344
|
const next = {
|
|
@@ -6967,21 +7365,56 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6967
7365
|
${prompt}`;
|
|
6968
7366
|
}
|
|
6969
7367
|
async function defaultDeps() {
|
|
6970
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
7368
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-B4STIW4B.js");
|
|
6971
7369
|
const orch = getOrchestrator2();
|
|
6972
7370
|
return {
|
|
6973
7371
|
findThread: (id) => findThreadByRef(id),
|
|
6974
|
-
send: (id, prompt) =>
|
|
7372
|
+
send: async (id, prompt, opts) => {
|
|
7373
|
+
if (opts?.options && Object.keys(opts.options).length > 0) {
|
|
7374
|
+
try {
|
|
7375
|
+
orch.setThreadOptions(id, opts.options);
|
|
7376
|
+
} catch {
|
|
7377
|
+
const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
|
|
7378
|
+
if (Object.keys(rest).length > 0) {
|
|
7379
|
+
try {
|
|
7380
|
+
orch.setThreadOptions(id, rest);
|
|
7381
|
+
} catch {
|
|
7382
|
+
}
|
|
7383
|
+
}
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
const thread = findThreadByRef(id);
|
|
7387
|
+
const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
|
|
7388
|
+
return orch.send(id, prompt, { attachments });
|
|
7389
|
+
},
|
|
6975
7390
|
startOrchestration: (opts) => startOrchestration2(opts)
|
|
6976
7391
|
};
|
|
6977
7392
|
}
|
|
7393
|
+
function scheduleOptionsAfterRefusedAgentSwitch(options) {
|
|
7394
|
+
const { agent: _agent, model: _model, ...rest } = options;
|
|
7395
|
+
return rest;
|
|
7396
|
+
}
|
|
7397
|
+
function scheduleSendOptions(schedule) {
|
|
7398
|
+
const patch = {};
|
|
7399
|
+
if (schedule.agent) {
|
|
7400
|
+
patch.agent = schedule.agent;
|
|
7401
|
+
patch.model = schedule.model;
|
|
7402
|
+
} else if (schedule.model) {
|
|
7403
|
+
patch.model = schedule.model;
|
|
7404
|
+
}
|
|
7405
|
+
if (schedule.effort) patch.effort = schedule.effort;
|
|
7406
|
+
if (schedule.fast != null) patch.fast = schedule.fast;
|
|
7407
|
+
if (schedule.planMode != null) patch.planMode = schedule.planMode;
|
|
7408
|
+
if (schedule.autonomy) patch.autonomy = schedule.autonomy;
|
|
7409
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
7410
|
+
}
|
|
6978
7411
|
function pickAgent(schedule) {
|
|
6979
7412
|
if (schedule.agent) return schedule.agent;
|
|
6980
7413
|
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
6981
7414
|
}
|
|
6982
7415
|
async function fireSchedule(id) {
|
|
6983
7416
|
const schedule = getSchedule(id);
|
|
6984
|
-
if (!schedule) throw new Error(`
|
|
7417
|
+
if (!schedule) throw new Error(`Automation not found: ${id}`);
|
|
6985
7418
|
if (firing.has(schedule.id)) return schedule;
|
|
6986
7419
|
firing.add(schedule.id);
|
|
6987
7420
|
try {
|
|
@@ -6989,18 +7422,28 @@ async function fireSchedule(id) {
|
|
|
6989
7422
|
const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
|
|
6990
7423
|
const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
|
|
6991
7424
|
if (target && target.status !== "archived") {
|
|
6992
|
-
const sent = await deps.send(target.id, prompt
|
|
7425
|
+
const sent = await deps.send(target.id, prompt, {
|
|
7426
|
+
attachments: schedule.attachments,
|
|
7427
|
+
options: scheduleSendOptions(schedule)
|
|
7428
|
+
});
|
|
6993
7429
|
return recordScheduleRun(schedule.id, {
|
|
6994
7430
|
lastThreadId: sent.id,
|
|
6995
7431
|
lastError: null
|
|
6996
7432
|
});
|
|
6997
7433
|
}
|
|
7434
|
+
const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
|
|
6998
7435
|
const created = await deps.startOrchestration({
|
|
6999
7436
|
goal: prompt,
|
|
7000
7437
|
agent: pickAgent(schedule),
|
|
7001
|
-
model: schedule.model
|
|
7438
|
+
model: schedule.model,
|
|
7439
|
+
...schedule.effort ? { effort: schedule.effort } : {},
|
|
7440
|
+
...schedule.fast != null ? { fast: schedule.fast } : {},
|
|
7441
|
+
...schedule.planMode != null ? { planMode: schedule.planMode } : {},
|
|
7442
|
+
...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
|
|
7443
|
+
attachments: schedule.attachments,
|
|
7444
|
+
...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
|
|
7002
7445
|
});
|
|
7003
|
-
if (
|
|
7446
|
+
if (pinReplacement) {
|
|
7004
7447
|
updateSchedule(schedule.id, { threadId: created.id });
|
|
7005
7448
|
}
|
|
7006
7449
|
return recordScheduleRun(schedule.id, {
|
|
@@ -7288,7 +7731,7 @@ var Orchestrator = class {
|
|
|
7288
7731
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
7289
7732
|
});
|
|
7290
7733
|
}
|
|
7291
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
7734
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
7292
7735
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
7293
7736
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
7294
7737
|
}
|
|
@@ -7682,7 +8125,7 @@ var Orchestrator = class {
|
|
|
7682
8125
|
}
|
|
7683
8126
|
await setup;
|
|
7684
8127
|
if (skipSetup) return;
|
|
7685
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
8128
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
7686
8129
|
if (autoRunAfterSetupEnabled()) {
|
|
7687
8130
|
try {
|
|
7688
8131
|
await this.startDev(threadId);
|
|
@@ -7891,6 +8334,7 @@ var Orchestrator = class {
|
|
|
7891
8334
|
} finally {
|
|
7892
8335
|
this.draining.delete(threadId);
|
|
7893
8336
|
}
|
|
8337
|
+
await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
|
|
7894
8338
|
}
|
|
7895
8339
|
async runTurn(threadId, prompt) {
|
|
7896
8340
|
const existing = readThread(threadId);
|
|
@@ -7974,7 +8418,8 @@ var Orchestrator = class {
|
|
|
7974
8418
|
return;
|
|
7975
8419
|
}
|
|
7976
8420
|
thread = this.requireThread(threadId);
|
|
7977
|
-
const
|
|
8421
|
+
const turnOrigin = thread.worktreePath?.trim() ? await resolveOriginRemote(thread.worktreePath).catch(() => null) : null;
|
|
8422
|
+
const gitPrompt = expandCanonicalGitRequest(promptText, { forge: turnOrigin?.forge });
|
|
7978
8423
|
const { agentPrompt: expandedPrompt } = expandComposerPrompt(
|
|
7979
8424
|
thread.worktreePath,
|
|
7980
8425
|
gitPrompt,
|
|
@@ -8058,14 +8503,12 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8058
8503
|
}
|
|
8059
8504
|
const isBrightsy = fresh.agent === "brightsy";
|
|
8060
8505
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
8061
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-
|
|
8506
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-P3H4SEIK.js");
|
|
8062
8507
|
const gitAuthMode = getGithubGitAuthMode();
|
|
8063
8508
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
8064
|
-
githubSlug: await withTimeout(
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
"resolveGithubRepoSlug"
|
|
8068
|
-
).catch(() => null),
|
|
8509
|
+
githubSlug: turnOrigin?.forge === "github" ? turnOrigin.slug : await withTimeout(resolveGithubRepoSlug(fresh.worktreePath), 8e3, "resolveGithubRepoSlug").catch(() => null),
|
|
8510
|
+
originForge: turnOrigin?.forge ?? null,
|
|
8511
|
+
originSlug: turnOrigin?.slug ?? null,
|
|
8069
8512
|
gitAuthMode,
|
|
8070
8513
|
activeRuns: annotateDevAccessRuns(
|
|
8071
8514
|
mergeWorktreeActiveRuns(
|
|
@@ -8158,7 +8601,8 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8158
8601
|
agentPrompt,
|
|
8159
8602
|
expandedPrompt,
|
|
8160
8603
|
worktreePath: fresh.worktreePath,
|
|
8161
|
-
attachments: autoContinue ? [] : sentAttachments ?? []
|
|
8604
|
+
attachments: autoContinue ? [] : sentAttachments ?? [],
|
|
8605
|
+
gitForge: turnOrigin?.forge
|
|
8162
8606
|
});
|
|
8163
8607
|
const handle = await spawnAgentTurn(
|
|
8164
8608
|
fresh,
|
|
@@ -9386,7 +9830,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9386
9830
|
if (Object.keys(patch).length === 0) continue;
|
|
9387
9831
|
updateThread(t.id, patch);
|
|
9388
9832
|
}
|
|
9389
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
9833
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
9390
9834
|
const latest = this.requireThread(thread.id);
|
|
9391
9835
|
if (!shouldAutoArchiveOnPrMerge({
|
|
9392
9836
|
previousPrState: prevState || null,
|
|
@@ -9710,7 +10154,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9710
10154
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
9711
10155
|
} catch {
|
|
9712
10156
|
}
|
|
9713
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
10157
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
9714
10158
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
9715
10159
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
9716
10160
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -9724,6 +10168,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9724
10168
|
if (thread.status !== "archived") {
|
|
9725
10169
|
throw new Error("Thread is not archived");
|
|
9726
10170
|
}
|
|
10171
|
+
clearEphemeralAutomation(thread.id);
|
|
9727
10172
|
if (isGlobalThread(thread)) {
|
|
9728
10173
|
const { globalAgentCwd } = await import("./paths-PHWEVXD5.js");
|
|
9729
10174
|
updateThread(thread.id, { worktreePath: globalAgentCwd() });
|
|
@@ -9741,7 +10186,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9741
10186
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
9742
10187
|
await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
|
|
9743
10188
|
});
|
|
9744
|
-
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-
|
|
10189
|
+
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-INRDQFWV.js");
|
|
9745
10190
|
await ensureWorktreeSideboardIgnored(dest);
|
|
9746
10191
|
}
|
|
9747
10192
|
const restorePatch = {};
|
|
@@ -9823,10 +10268,11 @@ async function startOrchestration(opts) {
|
|
|
9823
10268
|
planMode: opts.planMode,
|
|
9824
10269
|
attachments: opts.attachments
|
|
9825
10270
|
});
|
|
10271
|
+
const ready2 = markEphemeralAutomation(thread2.id, opts);
|
|
9826
10272
|
if (goal) {
|
|
9827
|
-
return orch.send(
|
|
10273
|
+
return orch.send(ready2.id, goal);
|
|
9828
10274
|
}
|
|
9829
|
-
return
|
|
10275
|
+
return ready2;
|
|
9830
10276
|
}
|
|
9831
10277
|
const { titleFromPrompt: titleFromPrompt2 } = await import("./title-Z7WAJN57.js");
|
|
9832
10278
|
const title = titleFromPrompt2(goal) || "Orchestration";
|
|
@@ -9846,7 +10292,7 @@ async function startOrchestration(opts) {
|
|
|
9846
10292
|
sourceRef: "default",
|
|
9847
10293
|
...createOpts
|
|
9848
10294
|
}).catch(async () => {
|
|
9849
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
10295
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-PDNPL5CQ.js");
|
|
9850
10296
|
const repo = await resolveRepoRoot2(repoPath);
|
|
9851
10297
|
const def = await resolveDefaultBranch2(repo);
|
|
9852
10298
|
return orch.createThread({
|
|
@@ -9856,15 +10302,16 @@ async function startOrchestration(opts) {
|
|
|
9856
10302
|
repoPath: repo
|
|
9857
10303
|
});
|
|
9858
10304
|
});
|
|
9859
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
10305
|
+
const { updateThread: upd } = await import("./thread-store-JRSL4HQY.js");
|
|
9860
10306
|
const updated = upd(thread.id, {
|
|
9861
10307
|
sourceType: "orchestration",
|
|
9862
10308
|
sourceRef: goal
|
|
9863
10309
|
});
|
|
10310
|
+
const ready = markEphemeralAutomation(updated.id, opts);
|
|
9864
10311
|
if (goal) {
|
|
9865
|
-
return orch.send(
|
|
10312
|
+
return orch.send(ready.id, goal);
|
|
9866
10313
|
}
|
|
9867
|
-
return
|
|
10314
|
+
return ready;
|
|
9868
10315
|
}
|
|
9869
10316
|
|
|
9870
10317
|
export {
|
|
@@ -9996,6 +10443,8 @@ export {
|
|
|
9996
10443
|
initStackFromThread,
|
|
9997
10444
|
createPrStack,
|
|
9998
10445
|
stackAgentDefaultsFrom,
|
|
10446
|
+
ghPrCreateAssigneeArgs,
|
|
10447
|
+
createOrUpdatePr,
|
|
9999
10448
|
inspectGitWorktree,
|
|
10000
10449
|
initializeGitRepository,
|
|
10001
10450
|
captureTurnBaseline,
|
|
@@ -10028,6 +10477,8 @@ export {
|
|
|
10028
10477
|
moveQueuedItemToFront,
|
|
10029
10478
|
shiftQueuedItem,
|
|
10030
10479
|
resolveSendFollowUp,
|
|
10480
|
+
formatCursorGitDirective,
|
|
10481
|
+
formatEntireGitDirective,
|
|
10031
10482
|
packagedDetachedJobPath,
|
|
10032
10483
|
resolveDetachedJobScript,
|
|
10033
10484
|
formatDetachedJobInvoke,
|