@gitkraken/compose-tools 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/git/diff-collector.js +5 -5
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/workflows/split.js +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/) and this
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.7.0] - 2026-07-30
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Export `parseUnifiedDiff`, so a consumer can turn a unified diff into the same `ComposeHunk[]` the composer scores. Needed by out-of-repo consumers (the commit-composer eval) that must index hunks exactly as `composeGroup` does.
|
|
14
|
+
|
|
9
15
|
## [0.6.0] - 2026-07-24
|
|
10
16
|
|
|
11
17
|
### Added
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import{GitError as e}from"../errors/git.js";import{ComposeWorkflowInputError as t}from"../errors/workflow.js";import{applyPatchToIndex as n,createBranch as r,currentBranch as i,diffTree as a,gitDir as o,listUntracked as s,log as c,mergeBase as l,mergeBaseIsAncestor as u,readTree as d,revParse as f,revParseVerify as p,stageAll as m,writeTree as h}from"./port-dispatch.js";import{
|
|
1
|
+
import{GitError as e}from"../errors/git.js";import{ComposeWorkflowInputError as t}from"../errors/workflow.js";import{applyPatchToIndex as n,createBranch as r,currentBranch as i,diffTree as a,gitDir as o,listUntracked as s,log as c,mergeBase as l,mergeBaseIsAncestor as u,readTree as d,revParse as f,revParseVerify as p,stageAll as m,writeTree as h}from"./port-dispatch.js";import{parseUnifiedDiff as g}from"./utils/hunk-parser.js";import{getAuthorAndCoAuthorsForCombinedDiffHunk as _}from"./utils/authorship.js";import{sha256 as v}from"./utils/crypto.js";import{withUntrackedInTempIndex as y}from"./utils/temp-index.js";import{randomUUID as b}from"node:crypto";import{copyFileSync as x,unlinkSync as S}from"node:fs";import{tmpdir as C}from"node:os";import{join as w}from"node:path";async function T(e,t){if(t.type===`workdir`){let n=!t.stagedOnly&&!t.noUntracked;return{...await E(e,{includeUnstaged:!t.stagedOnly,includeUntracked:n}),untrackedIncluded:n}}if(t.type===`commit-range`){if(t.includeWorkdir){let n=t.includeWorkdir.includeStaged??!0,r=t.includeWorkdir.includeUnstaged??!0,i=t.includeWorkdir.includeUntracked??!0,a=await L(e,t.branch,t.from,t.to,{includeStaged:n,includeUnstaged:r,includeUntracked:i});return{hunks:a.hunks,snapshot:a.snapshot,combinedDiff:a.combinedDiff,commitMessages:a.commits.map(e=>e.message),commitOrder:a.commits.map(e=>e.sha),branchName:t.branch,baseBranch:void 0,branchSha:a.snapshot.branchSha,mergeBaseSha:a.snapshot.baseSha,untrackedIncluded:i}}let n=await M(e,t.branch,t.from,t.to);return{hunks:n.hunks,snapshot:n.snapshot,combinedDiff:n.combinedDiff,commitMessages:n.commits.map(e=>e.message),commitOrder:n.commits.map(e=>e.sha),branchName:t.branch,baseBranch:void 0,branchSha:n.snapshot.branchSha,mergeBaseSha:n.snapshot.baseSha,untrackedIncluded:!1}}let n=t.mergeTarget??`main`,r=await j(e,t.name,n);return{hunks:r.hunks,snapshot:r.snapshot,combinedDiff:r.combinedDiff,commitMessages:r.commits.map(e=>e.message),commitOrder:r.commits.map(e=>e.sha),branchName:t.name,baseBranch:n,branchSha:r.snapshot.branchSha,mergeBaseSha:r.snapshot.baseSha,untrackedIncluded:!1}}async function E(e,t){let n=t.includeUnstaged||t.includeUntracked;return t.includeUntracked?k(e,n):D(e,n)}async function D(e,t){let n=await f(e,`HEAD`),r=await O(e,n,t);return{hunks:g(r),snapshot:V(r,n,void 0,void 0,await H(e,{includeUnstaged:t,includeUntracked:!1})),combinedDiff:r}}async function O(e,t,n){if(!n)return a(e,t,await h(e));let r=w(await o(e),`index`),i=w(C(),`compose-snapshot-idx-${b()}`);try{x(r,i);let n={GIT_INDEX_FILE:i};return await m(e,{trackedOnly:!0,indexEnv:n}),a(e,t,await h(e,{indexEnv:n}))}finally{try{S(i)}catch{}}}async function k(e,t){return y(e,async n=>{await A(e,n,t);let r=await h(e,{indexEnv:n}),i=await f(e,`HEAD`),o=await a(e,i,r);return{hunks:g(o),snapshot:V(o,i,void 0,void 0,await H(e,{includeUnstaged:t,includeUntracked:!0})),combinedDiff:o}})}async function A(e,t,n){n&&await m(e,{trackedOnly:!0,indexEnv:t}),await m(e,{indexEnv:t})}async function j(e,t,n){let r=await B(e,t);return P(e,await l(e,await B(e,n),r),await f(e,r))}async function M(e,t,n,r){await B(e,t);let i=await f(e,n),a=await f(e,r);return P(e,await N(e,i),a)}async function N(e,n){try{return await f(e,`${n}^`)}catch{throw new t(`Cannot recompose commit ${n.slice(0,8)} — it has no parent (root commit). Recomposing the root commit is not currently supported.`)}}async function P(n,r,i){if(!await u(n,r,i))throw new t(`Cannot collect range ${r.slice(0,8)}..${i.slice(0,8)}: '${r.slice(0,8)}' is not an ancestor of '${i.slice(0,8)}'.`);let o=await a(n,r,i),s=g(o),l=I(await c(n,{format:`%H%n%an%n%ae%n%aI%n%B%n---COMMIT-END---`,range:`${r}..${i}`,reverse:!0}));if(l.length===0)throw new e(`NO_CHANGES`,`No commits in range '${r.slice(0,8)}..${i.slice(0,8)}'.`);let d=await F(n,l);for(let e of s){let{author:t,coAuthors:n}=_(d,e);t!=null&&(e.author=t),n.length>0&&(e.coAuthors=n)}let p=V(o,await f(n,`HEAD`),i,r);return{hunks:s,commits:l.map(e=>({sha:e.sha,message:e.message})),snapshot:p,combinedDiff:o}}async function F(e,t){let n=[];for(let r of t){let t;try{t=await a(e,`${r.sha}^`,r.sha)}catch{continue}let i=g(t,0);for(let e of i)e.author={name:r.authorName,email:r.authorEmail,date:r.authorDate};n.push(...i)}return n}function I(e){let t=[],n=e.split(`---COMMIT-END---`).filter(e=>e.trim());for(let e of n){let n=e.replace(/^\n+/,``).split(`
|
|
2
2
|
`);if(n.length<5)continue;let r=n[0],i=n[1],a=n[2],o=n[3],s=n.slice(4).join(`
|
|
3
|
-
`).trimEnd(),c=o?new Date(o):void 0,l=c&&!Number.isNaN(c.getTime())?c:void 0;t.push({sha:r,authorName:i,authorEmail:a,authorDate:l,message:s})}return t}async function L(e,n,r,o,s){let l=await f(e,await B(e,n)),d=await f(e,r),p=await f(e,o),m=await f(e,`HEAD`);if(p!==l)throw new t(`commit-range with includeWorkdir requires 'to' to equal branch tip. Branch '${n}' tip is ${l}; got 'to'=${p}.`);if(m!==p)throw new t(`commit-range with includeWorkdir requires HEAD to equal 'to'. HEAD=${m}, 'to'=${p}.`);if(await i(e)==null)throw new t(`commit-range with includeWorkdir requires HEAD to be on a branch (non-detached). Check out the branch holding the range before composing.`);let h=await N(e,d),{finalTreeSha:
|
|
3
|
+
`).trimEnd(),c=o?new Date(o):void 0,l=c&&!Number.isNaN(c.getTime())?c:void 0;t.push({sha:r,authorName:i,authorEmail:a,authorDate:l,message:s})}return t}async function L(e,n,r,o,s){let l=await f(e,await B(e,n)),d=await f(e,r),p=await f(e,o),m=await f(e,`HEAD`);if(p!==l)throw new t(`commit-range with includeWorkdir requires 'to' to equal branch tip. Branch '${n}' tip is ${l}; got 'to'=${p}.`);if(m!==p)throw new t(`commit-range with includeWorkdir requires HEAD to equal 'to'. HEAD=${m}, 'to'=${p}.`);if(await i(e)==null)throw new t(`commit-range with includeWorkdir requires HEAD to be on a branch (non-detached). Check out the branch holding the range before composing.`);let h=await N(e,d),{finalTreeSha:v}=await R(e,m,s),y=await a(e,h,v);if(!await u(e,h,p))throw new t(`Cannot collect range ${h.slice(0,8)}..${p.slice(0,8)}: '${h.slice(0,8)}' is not an ancestor of '${p.slice(0,8)}'.`);let b=g(y),x=I(await c(e,{format:`%H%n%an%n%ae%n%aI%n%B%n---COMMIT-END---`,range:`${h}..${p}`,reverse:!0})),S=await F(e,x);for(let e of b){let{author:t,coAuthors:n}=_(S,e);t!=null&&(e.author=t),n.length>0&&(e.coAuthors=n)}let C=V(y,m,p,h,await H(e,s));return{hunks:b,commits:x.map(e=>({sha:e.sha,message:e.message})),snapshot:C,combinedDiff:y}}async function R(e,t,r){let i=w(C(),`compose-workdir-${b()}`),c={GIT_INDEX_FILE:i};try{if(await d(e,t,{indexEnv:c}),r.includeStaged){let r=await a(e,t,await h(e));r.trim()&&await n(e,r,{indexEnv:c})}if(r.includeUnstaged){let t=await h(e),r=w(C(),`compose-workdir-u-${b()}`),i={GIT_INDEX_FILE:r};try{x(w(await o(e),`index`),r),await m(e,{trackedOnly:!0,indexEnv:i});let s=await a(e,t,await h(e,{indexEnv:i}));s.trim()&&await n(e,s,{indexEnv:c})}finally{try{S(r)}catch{}}}if(r.includeUntracked){let t=await s(e);t.length>0&&(await m(e,{intentToAdd:!0,paths:t,indexEnv:c}),await m(e,{paths:t,indexEnv:c}))}return{finalTreeSha:await h(e,{indexEnv:c})}}finally{try{S(i)}catch{}}}async function z(e,t,n){let r=await B(e,t),i=await l(e,await B(e,n),r),o=await f(e,r),s=(await c(e,{format:`%H`,range:`${i}..${r}`,reverse:!0})).trim().split(`
|
|
4
4
|
`).filter(Boolean),u=[];for(let t of s){let[n,r,i]=await Promise.all([c(e,{format:`%B`,sha:t}).then(e=>e.trim()),a(e,`${t}^`,t),a(e,`${t}^`,t,{binary:!1,nameOnly:!0})]),o=i.trim().split(`
|
|
5
|
-
`).filter(Boolean);u.push({sha:t,message:n,diff:r,filesChanged:o})}return{commits:u,mergeBaseSha:i,branchSha:o}}async function B(t,n){if(await p(t,`refs/heads/${n}`)||await p(t,n))return n;if(await p(t,`origin/${n}`))return await r(t,n,`origin/${n}`),n;throw new e(`BRANCH_NOT_FOUND`,`Branch '${n}' not found locally or on origin. Run 'git fetch' if the branch exists on the remote.`)}function V(e,t,n,r,i){return{diffHash:
|
|
6
|
-
`).filter(Boolean);if(t.length>0){let n=[];for(let r of t)try{let t=await e.exec([`hash-object`,`--`,r]);n.push(`${r}:${t.trim()}`)}catch{}r.untracked=
|
|
7
|
-
`))}else r.untracked=
|
|
5
|
+
`).filter(Boolean);u.push({sha:t,message:n,diff:r,filesChanged:o})}return{commits:u,mergeBaseSha:i,branchSha:o}}async function B(t,n){if(await p(t,`refs/heads/${n}`)||await p(t,n))return n;if(await p(t,`origin/${n}`))return await r(t,n,`origin/${n}`),n;throw new e(`BRANCH_NOT_FOUND`,`Branch '${n}' not found locally or on origin. Run 'git fetch' if the branch exists on the remote.`)}function V(e,t,n,r,i){return{diffHash:v(e),headSha:t,branchSha:n,baseSha:r,sourceHashes:i}}async function H(e,t){if(!e.exec)return;let n=t.includeStaged??!0,r={};if(n)try{r.staged=v(await e.exec([`diff`,`--cached`,`--binary`,`HEAD`]))}catch{}if(t.includeUnstaged)try{r.unstaged=v(await e.exec([`diff`,`--binary`]))}catch{}if(t.includeUntracked)try{let t=(await e.exec([`ls-files`,`--others`,`--exclude-standard`])).trim().split(`
|
|
6
|
+
`).filter(Boolean);if(t.length>0){let n=[];for(let r of t)try{let t=await e.exec([`hash-object`,`--`,r]);n.push(`${r}:${t.trim()}`)}catch{}r.untracked=v(n.join(`
|
|
7
|
+
`))}else r.untracked=v(``)}catch{}return Object.keys(r).length>0?r:void 0}export{j as collectBranchDiffs,P as collectCombinedDiffRange,M as collectCommitRangeDiffs,L as collectCommitRangeWithWorkdir,z as collectCommitsForSplit,T as collectFromSource,H as collectSourceHashes,R as collectWorkdirPortionForRange,E as collectWorkingDiffs};
|
package/dist/index.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { ComposeContext, ComposeSource, ComposeTarget, OverrideSafetyFailures }
|
|
|
18
18
|
import { StashConflict } from "./git/types.js";
|
|
19
19
|
import { ComposeBranchPlan } from "./git/apply-target.js";
|
|
20
20
|
import { InteriorRefViolation, detectInteriorRefs } from "./git/safety-range.js";
|
|
21
|
+
import { parseUnifiedDiff } from "./git/utils/hunk-parser.js";
|
|
21
22
|
import { analyze } from "./tasks/analyze/analyze.js";
|
|
22
23
|
import { ComposeGroupInput, ComposeGroupOutput } from "./tasks/compose-group/types.js";
|
|
23
24
|
import { composeGroup } from "./tasks/compose-group/compose-group.js";
|
|
@@ -32,4 +33,4 @@ import { RefinePlanInput, RefinePlanResult, RefineProgressEvent, refinePlan } fr
|
|
|
32
33
|
import { SplitInput, SplitPlan, SplitProgressEvent, SplitResult, split } from "./workflows/split.js";
|
|
33
34
|
import { UndoComposeInput, ValidateUndoComposeInput, listUndoIds, undoCompose, validateUndoCompose } from "./workflows/undo.js";
|
|
34
35
|
import { UndoForceOptions } from "@gitkraken/shared-tools";
|
|
35
|
-
export { AIError, type AIErrorCode, type AfterModelCallInfo, type AnalysisResult, type AnalyzeInput, type AnalyzeOutput, type ApplyComposePlanInput, type ApplyComposePlanResult, type ApplyPatchOptions, type BeforeModelCallInfo, type BeforePromptInfo, type BranchGroup, type BranchOrdering, type BranchPartition, type CheckoutOptions, type CleanOptions, type CommitDetail, type CommitSuggestion, type CommitTreeOptions, type ComposeApplyPlan, type ComposeBranchPlan, type ComposeContext, type ComposeDepth, type ComposeDiffStats, type ComposeGitOps, type ComposeGitPort, ComposeGitPortMissingOpError, type ComposeGroupInput, type ComposeGroupOutput, type ComposeHunk, type ComposeInput, type ComposePlan, type ComposePlanInput, type ComposePlanResult, type ComposeProgressEvent, type ComposeResult, type ComposeSession, type ComposeSource, type ComposeStrategy, type ComposeTarget, type ComposeTaskName, ComposeWorkflowError, type ComposeWorkflowErrorCode, ComposeWorkflowInputError, type Concern, type ConcernDependency, type ConventionDescriptor, DEFAULT_INPUT_TOKEN_BUDGET, type DeleteBranchOptions, DiffTooLargeError, type DiffTreeOptions, type ForEachRefOptions, type GitCommitIdentity, GitError, type GitErrorCode, type GroupInput, type GroupOutput, type GroupingResult, type GroupingStrategy, type HunkAnnotation, type HunkOrderingConstraint, type IndexScopedOptions, type InteriorRefViolation, type LogOptions, type OnAfterModelCall, type OnBeforeModelCall, type OnBeforePrompt, type OpOptions, type OrderInput, type OrderOutput, type OrderingResult, type OverrideSafetyFailures, type PartitionInput, type PartitionOutput, type PartitionResult, type PartitionStrategy, type PhaseDetail, type ProgressEvent, type PromptOverride, type QuickComposeInput, type QuickComposeOutput, type QuickComposeResult, REDACTED_HUNK_CONTENT, type RedactHunkContent, type RefinePlanInput, type RefinePlanResult, type RefineProgressEvent, type SigningConfig, type SplitInput, type SplitPlan, type SplitProgressEvent, type SplitResult, type StageAllOptions, type StashConflict, type StashPushOptions, TaskInputError, type TokenUsage, type UndoComposeInput, type UndoForceOptions, type UpdateRefOptions, type ValidateUndoComposeInput, analyze, applyComposePlan, compose, composeGroup, composePlan, defaultPhaseMessages, detectInteriorRefs, estimatedCharactersPerToken, group, isNoiseHunk, listUndoIds, order, partition, quickCompose, refinePlan, split, undoCompose, validateUndoCompose, withDefaultNoiseRedaction };
|
|
36
|
+
export { AIError, type AIErrorCode, type AfterModelCallInfo, type AnalysisResult, type AnalyzeInput, type AnalyzeOutput, type ApplyComposePlanInput, type ApplyComposePlanResult, type ApplyPatchOptions, type BeforeModelCallInfo, type BeforePromptInfo, type BranchGroup, type BranchOrdering, type BranchPartition, type CheckoutOptions, type CleanOptions, type CommitDetail, type CommitSuggestion, type CommitTreeOptions, type ComposeApplyPlan, type ComposeBranchPlan, type ComposeContext, type ComposeDepth, type ComposeDiffStats, type ComposeGitOps, type ComposeGitPort, ComposeGitPortMissingOpError, type ComposeGroupInput, type ComposeGroupOutput, type ComposeHunk, type ComposeInput, type ComposePlan, type ComposePlanInput, type ComposePlanResult, type ComposeProgressEvent, type ComposeResult, type ComposeSession, type ComposeSource, type ComposeStrategy, type ComposeTarget, type ComposeTaskName, ComposeWorkflowError, type ComposeWorkflowErrorCode, ComposeWorkflowInputError, type Concern, type ConcernDependency, type ConventionDescriptor, DEFAULT_INPUT_TOKEN_BUDGET, type DeleteBranchOptions, DiffTooLargeError, type DiffTreeOptions, type ForEachRefOptions, type GitCommitIdentity, GitError, type GitErrorCode, type GroupInput, type GroupOutput, type GroupingResult, type GroupingStrategy, type HunkAnnotation, type HunkOrderingConstraint, type IndexScopedOptions, type InteriorRefViolation, type LogOptions, type OnAfterModelCall, type OnBeforeModelCall, type OnBeforePrompt, type OpOptions, type OrderInput, type OrderOutput, type OrderingResult, type OverrideSafetyFailures, type PartitionInput, type PartitionOutput, type PartitionResult, type PartitionStrategy, type PhaseDetail, type ProgressEvent, type PromptOverride, type QuickComposeInput, type QuickComposeOutput, type QuickComposeResult, REDACTED_HUNK_CONTENT, type RedactHunkContent, type RefinePlanInput, type RefinePlanResult, type RefineProgressEvent, type SigningConfig, type SplitInput, type SplitPlan, type SplitProgressEvent, type SplitResult, type StageAllOptions, type StashConflict, type StashPushOptions, TaskInputError, type TokenUsage, type UndoComposeInput, type UndoForceOptions, type UpdateRefOptions, type ValidateUndoComposeInput, analyze, applyComposePlan, compose, composeGroup, composePlan, defaultPhaseMessages, detectInteriorRefs, estimatedCharactersPerToken, group, isNoiseHunk, listUndoIds, order, parseUnifiedDiff, partition, quickCompose, refinePlan, split, undoCompose, validateUndoCompose, withDefaultNoiseRedaction };
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{AIError as e}from"./errors/ai.js";import{GitError as t}from"./errors/git.js";import{DiffTooLargeError as n,TaskInputError as r}from"./errors/task.js";import{ComposeWorkflowError as i,ComposeWorkflowInputError as a}from"./errors/workflow.js";import{ComposeGitPortMissingOpError as o}from"./ports/git.js";import{detectInteriorRefs as s}from"./git/safety-range.js";import{
|
|
1
|
+
import{AIError as e}from"./errors/ai.js";import{GitError as t}from"./errors/git.js";import{DiffTooLargeError as n,TaskInputError as r}from"./errors/task.js";import{ComposeWorkflowError as i,ComposeWorkflowInputError as a}from"./errors/workflow.js";import{ComposeGitPortMissingOpError as o}from"./ports/git.js";import{detectInteriorRefs as s}from"./git/safety-range.js";import{parseUnifiedDiff as c}from"./git/utils/hunk-parser.js";import{estimatedCharactersPerToken as l}from"./tasks/ai-loop.js";import{REDACTED_HUNK_CONTENT as u}from"./tasks/utils/redact.js";import{DEFAULT_INPUT_TOKEN_BUDGET as d}from"./tasks/utils/budget.js";import{analyze as f}from"./tasks/analyze/analyze.js";import{composeGroup as p}from"./tasks/compose-group/compose-group.js";import{group as m}from"./tasks/group/group.js";import{order as h}from"./tasks/order/order.js";import{partition as g}from"./tasks/partition/partition.js";import{quickCompose as _}from"./tasks/quick-compose/quick-compose.js";import{isNoiseHunk as v,withDefaultNoiseRedaction as y}from"./tasks/utils/noise.js";import{applyComposePlan as b,compose as x,composePlan as S,defaultPhaseMessages as C}from"./workflows/compose.js";import{refinePlan as w}from"./workflows/refine.js";import{split as T}from"./workflows/split.js";import{listUndoIds as E,undoCompose as D,validateUndoCompose as O}from"./workflows/undo.js";export{e as AIError,o as ComposeGitPortMissingOpError,i as ComposeWorkflowError,a as ComposeWorkflowInputError,d as DEFAULT_INPUT_TOKEN_BUDGET,n as DiffTooLargeError,t as GitError,u as REDACTED_HUNK_CONTENT,r as TaskInputError,f as analyze,b as applyComposePlan,x as compose,p as composeGroup,S as composePlan,C as defaultPhaseMessages,s as detectInteriorRefs,l as estimatedCharactersPerToken,m as group,v as isNoiseHunk,E as listUndoIds,h as order,c as parseUnifiedDiff,g as partition,_ as quickCompose,w as refinePlan,T as split,D as undoCompose,O as validateUndoCompose,y as withDefaultNoiseRedaction};
|
package/dist/workflows/split.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{GitError as e}from"../errors/git.js";import{forEachRef as t}from"../git/port-dispatch.js";import{addUsage as
|
|
2
|
-
`)),P=j.map(e=>({id:e.sha,message:e.message,explanation:``,hunkIndices:[]})),F;try{F=await
|
|
1
|
+
import{GitError as e}from"../errors/git.js";import{forEachRef as t}from"../git/port-dispatch.js";import{parseUnifiedDiff as n}from"../git/utils/hunk-parser.js";import{addUsage as r,emptyUsage as i}from"../ai/types.js";import{analyze as a}from"../tasks/analyze/analyze.js";import{partition as o}from"../tasks/partition/partition.js";import{createStackedBranches as s}from"../git/apply-branches.js";import{collectCommitsForSplit as c}from"../git/diff-collector.js";import{requireExec as l}from"../git/require-exec.js";import{rethrowAsWorkflowError as u}from"../utils/cancellation.js";import{defaultPhaseMessages as d}from"./compose.js";import{UndoStore as f,capturePreOperationState as p,generateUndoId as m}from"@gitkraken/shared-tools";async function h(t){let{git:f,model:m,branchName:h,baseBranch:v=`main`,instructions:y,maxRetries:b,maxTokens:x,onProgress:S,onBeforeApply:C,cancellation:w,onBeforeModelCall:T,onAfterModelCall:E,onBeforePrompt:D}=t,O=i(),k=[];S?.({phase:`collecting`,...d.collecting});let A=Date.now(),{commits:j,branchSha:M}=await c(f,h,v);if(k.push({name:`collecting`,durationMs:Date.now()-A,attempts:1}),j.length===0)throw new e(`NO_CHANGES`,`No commits found between '${v}' and '${h}'`);if(j.length<2)throw new e(`NO_CHANGES`,`Too few commits to split. A branch needs at least 2 commits.`);let N=n(j.map(e=>e.diff).join(`
|
|
2
|
+
`)),P=j.map(e=>({id:e.sha,message:e.message,explanation:``,hunkIndices:[]})),F;try{F=await a({hunks:N,commitMessages:j.map(e=>e.message),commitOrder:j.map(e=>e.sha),branchName:h,baseBranch:v,instructions:y,redactHunkContent:t.redactHunkContent,model:m,maxRetries:b,maxTokens:x,onProgress:e=>S?.({phase:`analyzing`,...d.analyzing,event:e}),cancellation:w,onBeforeModelCall:T,onAfterModelCall:E,onBeforePrompt:D})}catch(e){u(e,w)}F.usage&&r(O,F.usage),k.push({name:`analyzing`,durationMs:F.durationMs,attempts:F.attempts,usage:F.usage,callIds:F.callIds});let I=j.map(e=>e.sha),L=await g(f),R;try{R=await o({commits:P,orderedCommitIds:I,sourceBranchName:h,baseBranch:v,instructions:y,existingBranchNames:L,model:m,session:F.session,maxRetries:b,maxTokens:x,onProgress:e=>S?.({phase:`partitioning`,...d.partitioning,event:e}),cancellation:w,onBeforeModelCall:T,onAfterModelCall:E,onBeforePrompt:D})}catch(e){u(e,w)}R.usage&&r(O,R.usage),k.push({name:`partitioning`,durationMs:R.durationMs,attempts:R.attempts,usage:R.usage,callIds:R.callIds});let z={type:`branch`,hunks:N,commitMessages:j.map(e=>e.message),branchName:h,baseBranch:v},B={analysis:F.result,partitioning:R.result,commits:j};if(R.result.partitions.length<=1||C&&!await C(B))return{plan:B,partitions:R.result.partitions,session:R.session,usage:O,phases:k,source:z};let V=await p(l(f,`capturing pre-operation state`));S?.({phase:`applying`,...d.applying});let H=Date.now();await s({git:f,partitions:R.result.partitions,originalBranchName:h,originalBranchSha:M}),k.push({name:`applying`,durationMs:Date.now()-H,attempts:1});let U=await _(f,V,R.result.partitions,h,M);return{plan:B,partitions:R.result.partitions,session:R.session,usage:O,phases:k,source:z,undoId:U}}async function g(e){let n=(await t(e,{format:`%(refname:short)`,prefix:`refs/heads/`})).trim().split(`
|
|
3
3
|
`).filter(Boolean);return new Set(n)}async function _(e,t,n,r,i){let a=m(),o=n.map(e=>({kind:`branch`,name:e.branchName,sha:e.commitIds[e.commitIds.length-1]})),s={version:1,id:a,createdAt:new Date().toISOString(),description:`split: ${n.length} branches from '${r}'`,previousHead:{sha:t.headSha,branch:t.headBranch},workdirClean:t.workdirClean,workdirBackupSha:t.workdirBackupSha,createdRefs:o,deletedRefs:[{kind:`branch`,name:r,sha:i}],movedRefs:[]};return await new f(l(e,`undo manifest persistence`)).save(s),a}export{h as split};
|
package/package.json
CHANGED