@gitkraken/compose-tools 0.2.0 → 0.3.1
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 +47 -0
- package/README.md +38 -17
- package/dist/git/apply-target.d.ts +5 -9
- package/dist/git/apply-target.js +1 -1
- package/dist/git/commit-chain.d.ts +36 -48
- package/dist/git/commit-chain.js +7 -7
- package/dist/git/diff-collector.d.ts +40 -17
- package/dist/git/diff-collector.js +6 -7
- package/dist/git/index.d.ts +2 -2
- package/dist/git/index.js +1 -1
- package/dist/git/port-dispatch.d.ts +4 -2
- package/dist/git/port-dispatch.js +4 -3
- package/dist/git/reparent.d.ts +39 -0
- package/dist/git/reparent.js +5 -0
- package/dist/git/safety-range.d.ts +33 -0
- package/dist/git/safety-range.js +5 -0
- package/dist/git/types.d.ts +10 -14
- package/dist/git/utils/authorship.d.ts +22 -0
- package/dist/git/utils/authorship.js +1 -0
- package/dist/git/utils/hunk-parser.d.ts +1 -1
- package/dist/git/utils/hunk-parser.js +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +1 -1
- package/dist/ports/git.d.ts +22 -1
- package/dist/tasks/analyze/analyze.js +1 -1
- package/dist/tasks/analyze/prompt.d.ts +2 -0
- package/dist/tasks/analyze/prompt.js +5 -5
- package/dist/tasks/analyze/types.d.ts +3 -0
- package/dist/tasks/compose-group/compose-group.js +1 -1
- package/dist/tasks/compose-group/prompt.d.ts +2 -0
- package/dist/tasks/compose-group/prompt.js +29 -29
- package/dist/tasks/compose-group/types.d.ts +3 -0
- package/dist/tasks/group/group.js +1 -1
- package/dist/tasks/group/prompt.d.ts +2 -0
- package/dist/tasks/group/prompt.js +22 -22
- package/dist/tasks/group/types.d.ts +3 -0
- package/dist/tasks/quick-compose/prompt.d.ts +2 -0
- package/dist/tasks/quick-compose/prompt.js +11 -11
- package/dist/tasks/quick-compose/quick-compose.js +1 -1
- package/dist/tasks/quick-compose/types.d.ts +3 -0
- package/dist/tasks/types.d.ts +10 -9
- package/dist/tasks/utils/redact.d.ts +14 -0
- package/dist/tasks/utils/redact.js +1 -0
- package/dist/workflows/compose.d.ts +25 -14
- package/dist/workflows/compose.js +3 -2
- package/dist/workflows/split.d.ts +3 -0
- package/dist/workflows/split.js +2 -2
- package/dist/workflows/types.d.ts +41 -18
- package/package.json +2 -2
package/dist/git/index.d.ts
CHANGED
|
@@ -2,6 +2,6 @@ import { ApplyBranchEntry, ApplyBranchStructureParams, applyBranchStructure, cre
|
|
|
2
2
|
import { SafetySnapshot } from "./types.js";
|
|
3
3
|
import { BranchCommitInfo, BranchDiffResult, CollectionResult, SplitCollectionResult, WorkingDiffOptions, WorkingDiffResult, collectBranchDiffs, collectCommitsForSplit, collectFromSource, collectWorkingDiffs } from "./diff-collector.js";
|
|
4
4
|
import { ApplyToTargetParams, ApplyToTargetResult, ComposeBranchPlan, applyToTarget } from "./apply-target.js";
|
|
5
|
-
import { ApplyCommitChainParams,
|
|
5
|
+
import { ApplyCommitChainParams, BuildCommitChainParams, BuildCommitChainResult, applyCommitChain, buildCommitChain } from "./commit-chain.js";
|
|
6
6
|
import { verifyMultiBranchDiff, verifyResultingDiff, verifySnapshot } from "./safety.js";
|
|
7
|
-
export { type ApplyBranchEntry, type ApplyBranchStructureParams, type ApplyCommitChainParams, type
|
|
7
|
+
export { type ApplyBranchEntry, type ApplyBranchStructureParams, type ApplyCommitChainParams, type ApplyToTargetParams, type ApplyToTargetResult, type BranchCommitInfo, type BranchDiffResult, type BuildCommitChainParams, type BuildCommitChainResult, type CollectionResult, type ComposeBranchPlan, type SafetySnapshot, type SplitCollectionResult, type WorkingDiffOptions, type WorkingDiffResult, applyBranchStructure, applyCommitChain, applyToTarget, buildCommitChain, collectBranchDiffs, collectCommitsForSplit, collectFromSource, collectWorkingDiffs, createStackedBranches, verifyMultiBranchDiff, verifyResultingDiff, verifySnapshot };
|
package/dist/git/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{applyBranchStructure as e,createStackedBranches as t}from"./apply-branches.js";import{applyCommitChain as n,
|
|
1
|
+
import{applyBranchStructure as e,createStackedBranches as t}from"./apply-branches.js";import{applyCommitChain as n,buildCommitChain as r}from"./commit-chain.js";import{collectBranchDiffs as i,collectCommitsForSplit as a,collectFromSource as o,collectWorkingDiffs as s}from"./diff-collector.js";import{verifyMultiBranchDiff as c,verifyResultingDiff as l,verifySnapshot as u}from"./safety.js";import{applyToTarget as d}from"./apply-target.js";export{e as applyBranchStructure,n as applyCommitChain,d as applyToTarget,r as buildCommitChain,i as collectBranchDiffs,a as collectCommitsForSplit,o as collectFromSource,s as collectWorkingDiffs,t as createStackedBranches,c as verifyMultiBranchDiff,l as verifyResultingDiff,u as verifySnapshot};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ApplyPatchOptions, ApplyPatchToWorkdirOptions, CheckoutOptions, CleanOptions, CommitTreeOptions, ComposeGitPort, DeleteBranchOptions, DiffTreeOptions, ForEachRefOptions, IndexScopedOptions, LogOptions, OpOptions, StageAllOptions, StashPopOptions, StashPushOptions, UpdateRefOptions } from "../ports/git.js";
|
|
1
|
+
import { ApplyPatchOptions, ApplyPatchToWorkdirOptions, CheckoutOptions, CleanOptions, CommitTreeOptions, ComposeGitPort, DeleteBranchOptions, DiffTreeOptions, ForEachRefOptions, IndexScopedOptions, LogOptions, OpOptions, RevListChildrenEntry, RevListChildrenOptions, StageAllOptions, StashPopOptions, StashPushOptions, UpdateRefOptions } from "../ports/git.js";
|
|
2
2
|
|
|
3
3
|
//#region src/git/port-dispatch.d.ts
|
|
4
4
|
declare function revParse(git: ComposeGitPort, ref: string, opts?: OpOptions): Promise<string>;
|
|
@@ -6,9 +6,11 @@ declare function revParseVerify(git: ComposeGitPort, ref: string, opts?: OpOptio
|
|
|
6
6
|
declare function gitDir(git: ComposeGitPort, opts?: OpOptions): Promise<string>;
|
|
7
7
|
declare function currentBranch(git: ComposeGitPort, opts?: OpOptions): Promise<string | null>;
|
|
8
8
|
declare function mergeBase(git: ComposeGitPort, a: string, b: string, opts?: OpOptions): Promise<string>;
|
|
9
|
+
declare function mergeBaseIsAncestor(git: ComposeGitPort, ancestor: string, descendant: string, opts?: OpOptions): Promise<boolean>;
|
|
9
10
|
declare function diffTree(git: ComposeGitPort, from: string, to: string, opts?: DiffTreeOptions): Promise<string>;
|
|
10
11
|
declare function log(git: ComposeGitPort, opts: LogOptions): Promise<string>;
|
|
11
12
|
declare function forEachRef(git: ComposeGitPort, opts: ForEachRefOptions): Promise<string>;
|
|
13
|
+
declare function revListChildren(git: ComposeGitPort, opts: RevListChildrenOptions): Promise<RevListChildrenEntry[]>;
|
|
12
14
|
declare function writeTree(git: ComposeGitPort, opts?: IndexScopedOptions): Promise<string>;
|
|
13
15
|
declare function readTree(git: ComposeGitPort, sha: string, opts?: IndexScopedOptions): Promise<void>;
|
|
14
16
|
declare function stageAll(git: ComposeGitPort, opts?: StageAllOptions): Promise<void>;
|
|
@@ -37,4 +39,4 @@ declare function stashDrop(git: ComposeGitPort, stashRef: string, opts?: OpOptio
|
|
|
37
39
|
declare function cherryPick(git: ComposeGitPort, sha: string, opts?: OpOptions): Promise<void>;
|
|
38
40
|
declare function cherryPickAbort(git: ComposeGitPort, opts?: OpOptions): Promise<void>;
|
|
39
41
|
//#endregion
|
|
40
|
-
export { applyPatchToIndex, applyPatchToWorkdir, checkout, cherryPick, cherryPickAbort, cleanWorkdir, commitTree, createBranch, currentBranch, deleteBranch, diffTree, discardWorkdirChanges, forEachRef, getConfig, gitDir, listUntracked, localeNeutralEnv, log, mergeBase, mergeTree, readTree, reset, revParse, revParseVerify, showFile, stageAll, stashDrop, stashPop, stashPush, statusPorcelain, updateRef, writeTree };
|
|
42
|
+
export { applyPatchToIndex, applyPatchToWorkdir, checkout, cherryPick, cherryPickAbort, cleanWorkdir, commitTree, createBranch, currentBranch, deleteBranch, diffTree, discardWorkdirChanges, forEachRef, getConfig, gitDir, listUntracked, localeNeutralEnv, log, mergeBase, mergeBaseIsAncestor, mergeTree, readTree, reset, revListChildren, revParse, revParseVerify, showFile, stageAll, stashDrop, stashPop, stashPush, statusPorcelain, updateRef, writeTree };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import{ComposeGitPortMissingOpError as e}from"../ports/git.js";function t(t,n){throw new e(t,n)}async function n(e,n,r){return e.revParse?e.revParse(n,r):e.exec?(await e.exec([`rev-parse`,n])).trim():t(`revParse`)}async function r(e,n,r){if(e.revParseVerify)return e.revParseVerify(n,r);if(e.exec)try{return(await e.exec([`rev-parse`,`--verify`,n])).trim()}catch{return null}return t(`revParseVerify`)}async function i(e,n){return e.gitDir?e.gitDir(n):e.exec?(await e.exec([`rev-parse`,`--absolute-git-dir`])).trim():t(`gitDir`)}async function a(e,n){if(e.currentBranch)return e.currentBranch(n);if(e.exec)try{return(await e.exec([`symbolic-ref`,`--short`,`HEAD`])).trim()||null}catch{return null}return t(`currentBranch`)}async function o(e,n,r,i){return e.mergeBase?e.mergeBase(n,r,i):e.exec?(await e.exec([`merge-base`,n,r])).trim():t(`mergeBase`)}async function s(e,n,r,i){if(e.diffTree)return e.diffTree(n,r,i);if(e.exec){let t=[`diff`];return i?.binary!==!1&&t.push(`--binary`),i?.nameOnly&&t.push(`--name-only`),t.push(n,r),e.exec(t)}return t(`diffTree`)}async function
|
|
2
|
-
`).
|
|
3
|
-
`)
|
|
1
|
+
import{ComposeGitPortMissingOpError as e}from"../ports/git.js";function t(t,n){throw new e(t,n)}async function n(e,n,r){return e.revParse?e.revParse(n,r):e.exec?(await e.exec([`rev-parse`,n])).trim():t(`revParse`)}async function r(e,n,r){if(e.revParseVerify)return e.revParseVerify(n,r);if(e.exec)try{return(await e.exec([`rev-parse`,`--verify`,n])).trim()}catch{return null}return t(`revParseVerify`)}async function i(e,n){return e.gitDir?e.gitDir(n):e.exec?(await e.exec([`rev-parse`,`--absolute-git-dir`])).trim():t(`gitDir`)}async function a(e,n){if(e.currentBranch)return e.currentBranch(n);if(e.exec)try{return(await e.exec([`symbolic-ref`,`--short`,`HEAD`])).trim()||null}catch{return null}return t(`currentBranch`)}async function o(e,n,r,i){return e.mergeBase?e.mergeBase(n,r,i):e.exec?(await e.exec([`merge-base`,n,r])).trim():t(`mergeBase`)}async function s(e,n,r,i){if(e.mergeBaseIsAncestor)return e.mergeBaseIsAncestor(n,r,i);if(e.exec)try{return await e.exec([`merge-base`,`--is-ancestor`,n,r]),!0}catch{return!1}return t(`mergeBaseIsAncestor`)}async function c(e,n,r,i){if(e.diffTree)return e.diffTree(n,r,i);if(e.exec){let t=[`diff`];return i?.binary!==!1&&t.push(`--binary`),i?.nameOnly&&t.push(`--name-only`),t.push(n,r),e.exec(t)}return t(`diffTree`)}async function l(e,n){if(e.log)return e.log(n);if(e.exec){let t=[`log`,`--format=${n.format}`];if(n.noMerges&&t.push(`--no-merges`),n.reverse&&t.push(`--reverse`),n.topoOrder&&t.push(`--topo-order`),n.limit!=null&&t.push(`-n`,String(n.limit)),n.author&&t.push(`--author=${n.author}`),n.sha)t.push(`-1`,n.sha);else if(n.range)for(let e of n.range.split(/\s+/))e&&t.push(e);return e.exec(t)}return t(`log`)}async function u(e,n){if(e.forEachRef)return e.forEachRef(n);if(e.exec){let t=[`for-each-ref`,`--format=${n.format}`];return n.sort&&t.push(`--sort=${n.sort}`),n.pointsAt&&t.push(`--points-at=${n.pointsAt}`),n.prefix&&t.push(n.prefix),n.limit!=null&&t.push(`--count=${n.limit}`),e.exec(t)}return t(`forEachRef`)}async function d(e,n){if(e.revListChildren)return e.revListChildren(n);if(e.exec){let t=[`rev-list`,`--children`];return n.reverse&&t.push(`--reverse`),t.push(n.range),f(await e.exec(t))}return t(`revListChildren`)}function f(e){let t=[];for(let n of e.split(`
|
|
2
|
+
`)){let e=n.trim();if(!e)continue;let r=e.split(/\s+/);t.push({sha:r[0],children:r.slice(1)})}return t}async function p(e,n){return e.writeTree?e.writeTree(n):e.exec?(await e.exec([`write-tree`],{env:n?.indexEnv})).trim():t(`writeTree`)}async function m(e,n,r){if(e.readTree)return e.readTree(n,r);if(e.exec){await e.exec([`read-tree`,n],{env:r?.indexEnv});return}return t(`readTree`)}async function h(e,n){if(e.stageAll)return e.stageAll(n);if(e.exec){let t=[`add`];n?.intentToAdd?t.push(`-N`):n?.trackedOnly?t.push(`-u`):n?.paths||t.push(`-A`),n?.paths&&t.push(`--`,...n.paths),await e.exec(t,{env:n?.indexEnv});return}return t(`stageAll`)}async function g(e,n){return e.statusPorcelain?e.statusPorcelain(n):e.exec?e.exec([`status`,`--porcelain`]):t(`statusPorcelain`)}async function _(e,n){return e.listUntracked?e.listUntracked(n):e.exec?(await e.exec([`ls-files`,`--others`,`--exclude-standard`])).trim().split(`
|
|
3
|
+
`).filter(Boolean):t(`listUntracked`)}async function v(e,n,r,i){return e.showFile?e.showFile(n,r,i):e.exec?e.exec([`show`,`${n}:${r}`]):t(`showFile`)}async function y(e,n,r){if(e.getConfig)return e.getConfig(n,r);if(e.exec)try{return(await e.exec([`config`,n])).trim()||null}catch{return null}return t(`getConfig`)}async function b(e,n,r,i,a){if(e.commitTree)return e.commitTree(n,r,i,a);if(e.exec){let t=[`commit-tree`,n];for(let e of r)t.push(`-p`,e);t.push(`-m`,i),a?.signing?.enabled&&t.push(a.signing.signingKey?`-S${a.signing.signingKey}`:`-S`);let o={};return a?.author&&(o.GIT_AUTHOR_NAME=a.author.name,o.GIT_AUTHOR_EMAIL=a.author.email,o.GIT_COMMITTER_NAME=a.author.name,o.GIT_COMMITTER_EMAIL=a.author.email,a.author.date&&(o.GIT_AUTHOR_DATE=a.author.date.toISOString())),a?.signing?.gpgProgram&&(o.GIT_GPG_PROGRAM=a.signing.gpgProgram),(await e.exec(t,{env:Object.keys(o).length?o:void 0})).trim()}return t(`commitTree`)}async function x(e,n,r){if(e.applyPatchToIndex)return e.applyPatchToIndex(n,r);if(e.exec){let t=[`apply`,`--cached`];r?.allowBinaryReplacement!==!1&&t.push(`--allow-binary-replacement`),await e.exec(t,{env:r?.indexEnv,stdin:n});return}return t(`applyPatchToIndex`)}async function S(e,n,r){if(e.applyPatchToWorkdir)return e.applyPatchToWorkdir(n,r);if(e.exec){let t=[`apply`];r?.allowBinaryReplacement!==!1&&t.push(`--allow-binary-replacement`),await e.exec(t,{stdin:n});return}return t(`applyPatchToWorkdir`)}async function C(e,n,r,i){return e.mergeTree?e.mergeTree(n,r,i):e.exec?(await e.exec([`merge-tree`,`--write-tree`,n,r])).trim().split(`
|
|
4
|
+
`)[0]:t(`mergeTree`)}async function w(e,n,r,i){if(e.createBranch)return e.createBranch(n,r,i);if(e.exec){await e.exec([`branch`,n,r]);return}return t(`createBranch`)}async function T(e,n,r){if(e.deleteBranch)return e.deleteBranch(n,r);if(e.exec){await e.exec([`branch`,r?.force?`-D`:`-d`,n]);return}return t(`deleteBranch`)}async function E(e,n,r,i){if(e.updateRef)return e.updateRef(n,r,i);if(e.exec){if(i?.remove){await e.exec([`update-ref`,`-d`,n]);return}let t=[`update-ref`,n,r];i?.previousSha&&t.push(i.previousSha),await e.exec(t);return}return t(`updateRef`)}async function D(e,n,r){if(e.checkout)return e.checkout(n,r);if(e.exec){let t=[`checkout`];r?.createBranch&&t.push(`-b`),r?.detach&&t.push(`--detach`),t.push(n),r?.createBranch&&r?.startPoint&&t.push(r.startPoint),await e.exec(t);return}return t(`checkout`)}async function O(e,n,r,i){if(e.reset)return e.reset(n,r,i);if(e.exec){await e.exec([`reset`,`--${r}`,n]);return}return t(`reset`)}async function k(e,n){if(e.cleanWorkdir)return e.cleanWorkdir(n);if(e.exec){let t=`-`;n?.force!==!1&&(t+=`f`),n?.directories!==!1&&(t+=`d`),t===`-`&&(t=`-fd`),await e.exec([`clean`,t]);return}return t(`cleanWorkdir`)}async function A(e,n,r){if(e.discardWorkdirChanges)return e.discardWorkdirChanges(n,r);if(e.exec){let t=[`checkout`,`--`,...n?.length?n:[`.`]];await e.exec(t);return}return t(`discardWorkdirChanges`)}async function j(e,n){if(e.stashPush)return e.stashPush(n);if(e.exec){let t=[`stash`,`push`];n?.includeUntracked&&t.push(`--include-untracked`),n?.message&&t.push(`-m`,n.message),await e.exec(t);return}return t(`stashPush`)}const M={LANG:`C`,LC_ALL:`C`};async function N(e,n){if(e.stashPop)return e.stashPop(n);if(e.exec){let t=[`stash`,`pop`];n?.withIndex&&t.push(`--index`),n?.ref&&t.push(n.ref),await e.exec(t,{env:M});return}return t(`stashPop`)}async function P(e,n,r){if(e.stashDrop)return e.stashDrop(n,r);if(e.exec){await e.exec([`stash`,`drop`,n]);return}return t(`stashDrop`)}async function F(e,n,r){if(e.cherryPick)return e.cherryPick(n,r);if(e.exec){await e.exec([`cherry-pick`,n]);return}return t(`cherryPick`)}async function I(e,n){if(e.cherryPickAbort)return e.cherryPickAbort(n);if(e.exec){await e.exec([`cherry-pick`,`--abort`]);return}return t(`cherryPickAbort`)}export{x as applyPatchToIndex,S as applyPatchToWorkdir,D as checkout,F as cherryPick,I as cherryPickAbort,k as cleanWorkdir,b as commitTree,w as createBranch,a as currentBranch,T as deleteBranch,c as diffTree,A as discardWorkdirChanges,u as forEachRef,y as getConfig,i as gitDir,_ as listUntracked,M as localeNeutralEnv,l as log,o as mergeBase,s as mergeBaseIsAncestor,C as mergeTree,m as readTree,O as reset,d as revListChildren,n as revParse,r as revParseVerify,v as showFile,h as stageAll,P as stashDrop,N as stashPop,j as stashPush,g as statusPorcelain,E as updateRef,p as writeTree};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { ComposeGitPort, SigningConfig } from "../ports/git.js";
|
|
2
|
+
|
|
3
|
+
//#region src/git/reparent.d.ts
|
|
4
|
+
interface ReparentedRef {
|
|
5
|
+
refname: string;
|
|
6
|
+
oldSha: string;
|
|
7
|
+
newSha: string;
|
|
8
|
+
}
|
|
9
|
+
interface ReparentDescendantsParams {
|
|
10
|
+
git: ComposeGitPort;
|
|
11
|
+
/** The old tip of the rewritten range — descendants of this SHA get re-parented. */
|
|
12
|
+
oldToSha: string;
|
|
13
|
+
/** The new last commit of the recomposed chain. */
|
|
14
|
+
newTopSha: string;
|
|
15
|
+
/**
|
|
16
|
+
* The source branch's short name (e.g. `main`). When provided, the result
|
|
17
|
+
* includes `sourceBranchNewSha` if the source branch's tip was a strict
|
|
18
|
+
* descendant of `oldToSha` and got re-parented by this function. When
|
|
19
|
+
* undefined, the caller must move the source branch manually.
|
|
20
|
+
*/
|
|
21
|
+
sourceBranchName?: string;
|
|
22
|
+
signing?: SigningConfig;
|
|
23
|
+
}
|
|
24
|
+
interface ReparentDescendantsResult {
|
|
25
|
+
reparentedRefs: ReparentedRef[];
|
|
26
|
+
/**
|
|
27
|
+
* Set when the source branch's tip was a strict descendant of `oldToSha` and got re-parented
|
|
28
|
+
* here. Undefined otherwise — the caller handles the source branch (move to `newTopSha` when
|
|
29
|
+
* it pointed at `oldToSha`, or leave at an interior commit per user allowance).
|
|
30
|
+
*/
|
|
31
|
+
sourceBranchNewSha?: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Re-parent every ref whose tip is a strict descendant of `oldToSha` onto `newTopSha`.
|
|
35
|
+
* Refs at `oldToSha` itself are excluded — the caller moves those to the new tip directly.
|
|
36
|
+
*/
|
|
37
|
+
declare function reparentDescendants(params: ReparentDescendantsParams): Promise<ReparentDescendantsResult>;
|
|
38
|
+
//#endregion
|
|
39
|
+
export { ReparentDescendantsParams, ReparentDescendantsResult, ReparentedRef, reparentDescendants };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{GitError as e}from"../errors/git.js";import{commitTree as t,forEachRef as n,log as r,mergeBaseIsAncestor as i,updateRef as a}from"./port-dispatch.js";async function o(n){let{git:r,oldToSha:i,newTopSha:o,sourceBranchName:u,signing:d}=n,f=await s(r,i);if(f.length===0)return{reparentedRefs:[]};let p=await c(r,i,f.map(e=>e.sha)),m=new Map;m.set(i,o);for(let e of p){if(m.has(e))continue;let n=await l(r,e),i=n.parents.map(e=>m.get(e)??e),a=await t(r,n.tree,i,n.message,{author:n.author,signing:d});m.set(e,a)}let h=u?`refs/heads/${u}`:void 0,g,_=[];for(let t of f){let n=m.get(t.sha);if(n==null)throw new e(`OPERATION_FAILED`,`Internal error during descendant re-parenting: ref ${t.refname} at ${t.sha.slice(0,8)} did not appear in the downstream walk.`);await a(r,t.refname,n),_.push({refname:t.refname,oldSha:t.sha,newSha:n}),h!=null&&t.refname===h&&(g=n)}return{reparentedRefs:_,sourceBranchNewSha:g}}async function s(e,t){let r=await n(e,{format:`%(refname) %(objectname)`}),a=[];for(let n of r.split(`
|
|
2
|
+
`)){let r=n.trim();if(!r)continue;let o=r.indexOf(` `);if(o<0)continue;let s=r.slice(0,o),c=r.slice(o+1).trim();!s.startsWith(`refs/heads/`)&&!s.startsWith(`refs/tags/`)||c!==t&&await i(e,t,c)&&a.push({refname:s,sha:c})}return a}async function c(e,t,n){return(await r(e,{format:`%H`,range:`${n.join(` `)} ^${t}`,reverse:!0,topoOrder:!0})).trim().split(`
|
|
3
|
+
`).filter(Boolean)}async function l(t,n){let i=(await r(t,{format:`%T%n%P%n%an%n%ae%n%aI%n%B`,sha:n})).split(`
|
|
4
|
+
`);if(i.length<5)throw new e(`OPERATION_FAILED`,`Unable to read commit info for ${n.slice(0,8)}`);let a=i[0].trim(),o=i[1].trim(),s=o?o.split(/\s+/):[],c=i[2],l=i[3],u=i[4],d=i.slice(5).join(`
|
|
5
|
+
`).trimEnd(),f=u?new Date(u):void 0;return{tree:a,parents:s,author:{name:c,email:l,date:f&&!Number.isNaN(f.getTime())?f:void 0},message:d}}export{o as reparentDescendants};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { ComposeGitPort } from "../ports/git.js";
|
|
2
|
+
import { ComposeSource, ComposeTarget } from "../workflows/types.js";
|
|
3
|
+
|
|
4
|
+
//#region src/git/safety-range.d.ts
|
|
5
|
+
interface InteriorForkViolation {
|
|
6
|
+
kind: 'interior-fork';
|
|
7
|
+
sha: string;
|
|
8
|
+
/** Children of the offending commit. When > 1, the commit is forked. */
|
|
9
|
+
children: string[];
|
|
10
|
+
reason: 'multiple-children' | 'child-outside-range';
|
|
11
|
+
}
|
|
12
|
+
interface InteriorRefViolation {
|
|
13
|
+
kind: 'interior-ref';
|
|
14
|
+
refname: string;
|
|
15
|
+
sha: string;
|
|
16
|
+
}
|
|
17
|
+
type RewriteSafetyViolation = InteriorForkViolation | InteriorRefViolation;
|
|
18
|
+
interface ValidateRewriteRangeSafetyParams {
|
|
19
|
+
git: ComposeGitPort;
|
|
20
|
+
source: ComposeSource;
|
|
21
|
+
target: ComposeTarget;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run the interior-fork and interior-ref checks against the source range.
|
|
25
|
+
* Throws `ComposeWorkflowInputError` with all violations listed when either
|
|
26
|
+
* check fails; returns silently on success.
|
|
27
|
+
*
|
|
28
|
+
* No-op when the target doesn't rewrite history (`head`, `branch` with
|
|
29
|
+
* `preserveOriginal: true`, `auto` with `preserveOriginal: true`).
|
|
30
|
+
*/
|
|
31
|
+
declare function validateRewriteRangeSafety(params: ValidateRewriteRangeSafetyParams): Promise<void>;
|
|
32
|
+
//#endregion
|
|
33
|
+
export { InteriorForkViolation, InteriorRefViolation, RewriteSafetyViolation, ValidateRewriteRangeSafetyParams, validateRewriteRangeSafety };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{ComposeWorkflowInputError as e}from"../errors/workflow.js";import{currentBranch as t,forEachRef as n,log as r,mergeBase as i,mergeBaseIsAncestor as a,revListChildren as o,revParse as s}from"./port-dispatch.js";async function c(t){let{git:n,source:r,target:i}=t;if(!l(r,i))return;let o=await u(n,r);if(o==null)return;let{sourceBranchName:s,parentOfFromSha:c,toSha:m}=o;if(!await a(n,c,m))return;let h=[],g=await d(n,c,m);h.push(...g);let _=await f(n,c,m,s);if(h.push(..._),h.length>0)throw new e(p(h))}function l(e,t){return t.type===`rewrite-range`?!0:(t.type===`branch`||t.type===`auto`)&&e.type===`branch`?!t.preserveOriginal:!1}async function u(t,n){if(n.type===`workdir`)return null;if(n.type===`branch`){let e=n.mergeTarget??`main`,r=await s(t,n.name),a=await i(t,await s(t,e),r);return{sourceBranchName:n.name,parentOfFromSha:a,toSha:r}}let r=await s(t,n.from),a=await s(t,n.to),o;try{o=await s(t,`${r}^`)}catch{throw new e(`Cannot rewrite commit ${r.slice(0,8)} — it has no parent (root commit). Rewriting the root commit is not currently supported.`)}return{sourceBranchName:n.branch,parentOfFromSha:o,toSha:a}}async function d(e,t,n){let i=await r(e,{format:`%H`,range:`${t}..${n}`}),a=new Set(i.trim().split(`
|
|
2
|
+
`).filter(Boolean)),s=await o(e,{range:`${t}..${n}`}),c=[];for(let e of s){if(e.sha===n||!a.has(e.sha))continue;if(e.children.length!==1){c.push({kind:`interior-fork`,sha:e.sha,children:e.children,reason:`multiple-children`});continue}let t=e.children[0];a.has(t)||c.push({kind:`interior-fork`,sha:e.sha,children:e.children,reason:`child-outside-range`})}return c}async function f(e,i,a,o){let c=await r(e,{format:`%H`,range:`${i}..${a}`}),l=new Set(c.trim().split(`
|
|
3
|
+
`).filter(Boolean));l.delete(a);let u=await n(e,{format:`%(refname) %(objectname)`}),d=`refs/heads/${o}`,f=[];for(let e of u.split(`
|
|
4
|
+
`)){let t=e.trim();if(!t)continue;let n=t.indexOf(` `);if(n<0)continue;let r=t.slice(0,n),i=t.slice(n+1).trim();r!==d&&(!r.startsWith(`refs/heads/`)&&!r.startsWith(`refs/tags/`)||l.has(i)&&f.push({kind:`interior-ref`,refname:r,sha:i}))}if(await t(e)==null){let t=await s(e,`HEAD`);l.has(t)&&f.push({kind:`interior-ref`,refname:`HEAD (detached)`,sha:t})}return f}function p(e){let t=[`Cannot safely rewrite the source range — applying the rewrite would orphan refs or lose history outside the range.`,``],n=e.filter(e=>e.kind===`interior-fork`),r=e.filter(e=>e.kind===`interior-ref`);if(n.length>0){t.push(`Interior fork(s) detected — every commit in the rewritten range (except the tip) must have exactly one child within the range:`);for(let e of n){let n=e.children.length>0?e.children.map(e=>e.slice(0,8)).join(`, `):`(none)`,r=e.reason===`multiple-children`?`has ${e.children.length} children`:`has a child that is outside the rewritten range`;t.push(` - ${e.sha.slice(0,8)}: ${r} (${n})`)}t.push(``)}if(r.length>0){t.push(`Refs pointing at interior commits — these would be orphaned by the rewrite:`);for(let e of r)t.push(` - ${e.refname} → ${e.sha.slice(0,8)}`);t.push(``),t.push(`To proceed: delete the offending refs (or move them outside the range), or check out a stable ref if HEAD is detached at an interior commit, then re-run.`)}return t.join(`
|
|
5
|
+
`)}export{c as validateRewriteRangeSafety};
|
package/dist/git/types.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { RefMovement, RefSnapshot } from "@gitkraken/shared-tools";
|
|
2
|
+
|
|
1
3
|
//#region src/git/types.d.ts
|
|
2
4
|
/**
|
|
3
5
|
* Hash-based fingerprint of the diff at the start of an AI-driven compose pass.
|
|
@@ -23,21 +25,15 @@ interface SafetySnapshot {
|
|
|
23
25
|
untracked?: string;
|
|
24
26
|
};
|
|
25
27
|
}
|
|
26
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Git mutations performed during an apply phase, for undo manifest construction. Ref entries
|
|
30
|
+
* carry a `kind` (`'branch'` or `'tag'`) so undo can reconstruct the full refname and dispatch
|
|
31
|
+
* to the right plumbing.
|
|
32
|
+
*/
|
|
27
33
|
interface ApplyMutations {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}[];
|
|
32
|
-
deletedBranches: {
|
|
33
|
-
name: string;
|
|
34
|
-
sha: string;
|
|
35
|
-
}[];
|
|
36
|
-
movedBranches: {
|
|
37
|
-
name: string;
|
|
38
|
-
previousSha: string;
|
|
39
|
-
newSha: string;
|
|
40
|
-
}[];
|
|
34
|
+
createdRefs: RefSnapshot[];
|
|
35
|
+
deletedRefs: RefSnapshot[];
|
|
36
|
+
movedRefs: RefMovement[];
|
|
41
37
|
}
|
|
42
38
|
/** Reported when the apply path's stash pop hit conflicts. The apply itself succeeded. */
|
|
43
39
|
interface StashConflict {
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ComposeHunk } from "../../tasks/types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/git/utils/authorship.d.ts
|
|
4
|
+
declare function getHunkSimilarityValue(hunkA: ComposeHunk, hunkB: ComposeHunk): number;
|
|
5
|
+
type Identity = NonNullable<ComposeHunk['author']>;
|
|
6
|
+
/**
|
|
7
|
+
* Given a combined-diff hunk and the side-table of per-commit hunks, pick
|
|
8
|
+
* a primary author + co-authors by line-range overlap. Returns
|
|
9
|
+
* `{ author: undefined, coAuthors: [] }` when no per-commit hunk for the
|
|
10
|
+
* file matches — the caller treats that as "no opinion."
|
|
11
|
+
*
|
|
12
|
+
* Tie-breaking: when two authors have equal cumulative overlap, the first
|
|
13
|
+
* one to reach that score wins primary (iteration order over
|
|
14
|
+
* `perCommitHunks`). Both remain in the returned set — the tied author who
|
|
15
|
+
* didn't win primary surfaces as a co-author.
|
|
16
|
+
*/
|
|
17
|
+
declare function getAuthorAndCoAuthorsForCombinedDiffHunk(perCommitHunks: ComposeHunk[], combinedHunk: ComposeHunk): {
|
|
18
|
+
author: Identity | undefined;
|
|
19
|
+
coAuthors: Identity[];
|
|
20
|
+
};
|
|
21
|
+
//#endregion
|
|
22
|
+
export { getAuthorAndCoAuthorsForCombinedDiffHunk, getHunkSimilarityValue };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/;function t(t){let n=t.match(e);return n?{oldStart:Number.parseInt(n[1],10),oldCount:n[2]==null?1:Number.parseInt(n[2],10),newStart:Number.parseInt(n[3],10),newCount:n[4]==null?1:Number.parseInt(n[4],10)}:null}function n(e,t,n,r){let i=e+t,a=n+r;return Math.max(0,Math.min(i,a)-Math.max(e,n))}function r(e,r){let i=t(e.hunkHeader),a=t(r.hunkHeader);return i==null||a==null?0:n(i.oldStart,i.oldCount,a.oldStart,a.oldCount)+n(i.newStart,i.newCount,a.newStart,a.newCount)}function i(e){return`${e.name.toLowerCase()}\x00${e.email.toLowerCase()}`}function a(e,t){let n=e.filter(e=>e.author!=null&&e.fileName===t.fileName&&(t.isRename!==!0||e.isRename===t.isRename));if(n.length===0)return{author:void 0,coAuthors:[]};let a=new Map,o=new Map,s,c=0;for(let e of n){if(!e.author)continue;let n=i(e.author);o.set(n,e.author);for(let t of e.coAuthors??[])o.set(i(t),t);let l=r(e,t),u=(a.get(n)??0)+l;a.set(n,u),(s==null||u>c)&&(c=u,s=n)}if(s==null)return{author:void 0,coAuthors:[]};let l=o.get(s),u=[];for(let[e,t]of o)e!==s&&u.push(t);return{author:l,coAuthors:u}}export{a as getAuthorAndCoAuthorsForCombinedDiffHunk,r as getHunkSimilarityValue};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ComposeHunk } from "../../tasks/types.js";
|
|
2
2
|
|
|
3
3
|
//#region src/git/utils/hunk-parser.d.ts
|
|
4
|
-
declare function parseUnifiedDiff(diffText: string,
|
|
4
|
+
declare function parseUnifiedDiff(diffText: string, startIndex?: number): ComposeHunk[];
|
|
5
5
|
//#endregion
|
|
6
6
|
export { parseUnifiedDiff };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const e=/^diff --git /m,t=/^@@ /m;function n(e,t
|
|
1
|
+
const e=/^diff --git /m,t=/^@@ /m;function n(e,t=0){if(!e.trim())return[];let n=r(e),a=[],o=t;for(let e of n){let{diffHeader:t,fileName:n,originalFileName:r,isRename:s,isBinary:c,binaryPatchData:l,hunkSections:u}=i(e);if(c){a.push({index:o++,fileName:n,diffHeader:t,hunkHeader:``,content:`Binary file change`,additions:0,deletions:0,isRename:s,originalFileName:r,isBinary:!0,binaryPatchData:l});continue}if(u.length===0){a.push({index:o++,fileName:n,diffHeader:t,hunkHeader:s?`rename`:``,content:s?`Rename from ${r}\nRename to ${n}`:``,additions:0,deletions:0,isRename:s,originalFileName:r});continue}for(let e of u)a.push({index:o++,fileName:n,diffHeader:t,hunkHeader:e.header,content:e.content,additions:e.additions,deletions:e.deletions,isRename:!1,originalFileName:r})}return a}function r(t){let n=[],r=t.split(e);for(let e=1;e<r.length;e++)n.push(`diff --git ${r[e]}`);return n}function i(e){let n=e.indexOf(`
|
|
2
2
|
GIT binary patch
|
|
3
3
|
`);if(n!==-1){let t=e.slice(0,n).trimEnd(),r=e.slice(n+1),i=a(t),{isRename:s,originalFileName:c}=o(t);return{diffHeader:t,fileName:i,originalFileName:c,isRename:s,isBinary:!0,binaryPatchData:r,hunkSections:[]}}let r=e.search(t),i,c;r===-1?(i=e.trimEnd(),c=``):(i=e.slice(0,r).trimEnd(),c=e.slice(r));let l=a(i),{isRename:u,originalFileName:d}=o(i),f=c?s(c):[];return{diffHeader:i,fileName:l,originalFileName:d,isRename:u,isBinary:!1,hunkSections:f}}function a(e){let t=e.split(`
|
|
4
4
|
`);for(let e of t)if(e.startsWith(`+++ b/`))return e.slice(6);for(let e of t)if(e.startsWith(`rename to `))return e.slice(10);return t[0]?.match(/^diff --git a\/.+ b\/(.+)$/)?.[1]??`unknown`}function o(e){let t=e.split(`
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { ApplyPatchOptions, CheckoutOptions, CleanOptions, CommitTreeOptions, Co
|
|
|
7
7
|
import { BranchGroup, BranchOrdering, BranchPartition, CommitDetail, CommitSuggestion, ComposeHunk, ComposeTaskName, PromptOverride } from "./tasks/types.js";
|
|
8
8
|
import { ConventionDescriptor } from "./git/utils/conventions.js";
|
|
9
9
|
import { AfterModelCallInfo, BeforeModelCallInfo, BeforePromptInfo, OnAfterModelCall, OnBeforeModelCall, OnBeforePrompt, estimatedCharactersPerToken } from "./tasks/ai-loop.js";
|
|
10
|
+
import { REDACTED_HUNK_CONTENT, RedactHunkContent } from "./tasks/utils/redact.js";
|
|
10
11
|
import { AnalysisResult, AnalyzeInput, AnalyzeOutput, Concern, ConcernDependency, HunkAnnotation, HunkOrderingConstraint } from "./tasks/analyze/types.js";
|
|
11
12
|
import { GroupInput, GroupOutput, GroupingResult, GroupingStrategy } from "./tasks/group/types.js";
|
|
12
13
|
import { OrderInput, OrderOutput, OrderingResult } from "./tasks/order/types.js";
|
|
@@ -23,8 +24,8 @@ import { group } from "./tasks/group/group.js";
|
|
|
23
24
|
import { order } from "./tasks/order/order.js";
|
|
24
25
|
import { partition } from "./tasks/partition/partition.js";
|
|
25
26
|
import { quickCompose } from "./tasks/quick-compose/quick-compose.js";
|
|
26
|
-
import { ApplyComposePlanInput, ApplyComposePlanResult,
|
|
27
|
+
import { ApplyComposePlanInput, ApplyComposePlanResult, ComposeApplyPlan, ComposeDepth, ComposeInput, ComposePlan, ComposePlanInput, ComposePlanResult, ComposeProgressEvent, ComposeResult, ComposeStrategy, applyComposePlan, compose, composePlan, defaultPhaseMessages } from "./workflows/compose.js";
|
|
27
28
|
import { SplitInput, SplitPlan, SplitProgressEvent, SplitResult, split } from "./workflows/split.js";
|
|
28
29
|
import { UndoComposeInput, ValidateUndoComposeInput, listUndoIds, undoCompose, validateUndoCompose } from "./workflows/undo.js";
|
|
29
30
|
import { UndoForceOptions } from "@gitkraken/shared-tools";
|
|
30
|
-
export { AIError, type AIErrorCode, type AfterModelCallInfo, type AnalysisResult, type AnalyzeInput, type AnalyzeOutput, type ApplyComposePlanInput, type ApplyComposePlanResult, type ApplyPatchOptions, type
|
|
31
|
+
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 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, type DeleteBranchOptions, type DiffTreeOptions, type ForEachRefOptions, type GitCommitIdentity, GitError, type GitErrorCode, type GroupInput, type GroupOutput, type GroupingResult, type GroupingStrategy, type HunkAnnotation, type HunkOrderingConstraint, type IndexScopedOptions, type LogOptions, type OnAfterModelCall, type OnBeforeModelCall, type OnBeforePrompt, type OpOptions, type OrderInput, type OrderOutput, type OrderingResult, 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 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, estimatedCharactersPerToken, group, listUndoIds, order, partition, quickCompose, split, undoCompose, validateUndoCompose };
|
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{TaskInputError as n}from"./errors/task.js";import{ComposeWorkflowError as r,ComposeWorkflowInputError as i}from"./errors/workflow.js";import{ComposeGitPortMissingOpError as a}from"./ports/git.js";import{estimatedCharactersPerToken as o}from"./tasks/ai-loop.js";import{
|
|
1
|
+
import{AIError as e}from"./errors/ai.js";import{GitError as t}from"./errors/git.js";import{TaskInputError as n}from"./errors/task.js";import{ComposeWorkflowError as r,ComposeWorkflowInputError as i}from"./errors/workflow.js";import{ComposeGitPortMissingOpError as a}from"./ports/git.js";import{estimatedCharactersPerToken as o}from"./tasks/ai-loop.js";import{REDACTED_HUNK_CONTENT as s}from"./tasks/utils/redact.js";import{analyze as c}from"./tasks/analyze/analyze.js";import{composeGroup as l}from"./tasks/compose-group/compose-group.js";import{group as u}from"./tasks/group/group.js";import{order as d}from"./tasks/order/order.js";import{partition as f}from"./tasks/partition/partition.js";import{quickCompose as p}from"./tasks/quick-compose/quick-compose.js";import{applyComposePlan as m,compose as h,composePlan as g,defaultPhaseMessages as _}from"./workflows/compose.js";import{split as v}from"./workflows/split.js";import{listUndoIds as y,undoCompose as b,validateUndoCompose as x}from"./workflows/undo.js";export{e as AIError,a as ComposeGitPortMissingOpError,r as ComposeWorkflowError,i as ComposeWorkflowInputError,t as GitError,s as REDACTED_HUNK_CONTENT,n as TaskInputError,c as analyze,m as applyComposePlan,h as compose,l as composeGroup,g as composePlan,_ as defaultPhaseMessages,o as estimatedCharactersPerToken,u as group,y as listUndoIds,d as order,f as partition,p as quickCompose,v as split,b as undoCompose,x as validateUndoCompose};
|
package/dist/ports/git.d.ts
CHANGED
|
@@ -28,12 +28,19 @@ interface ComposeGitOps {
|
|
|
28
28
|
currentBranch?: (opts?: OpOptions) => Promise<string | null>;
|
|
29
29
|
/** Best common ancestor between two refs. Covers `merge-base a b`. */
|
|
30
30
|
mergeBase?: (a: string, b: string, opts?: OpOptions) => Promise<string>;
|
|
31
|
+
/** Check whether `ancestor` is an ancestor of `descendant`. Covers `merge-base --is-ancestor`. */
|
|
32
|
+
mergeBaseIsAncestor?: (ancestor: string, descendant: string, opts?: OpOptions) => Promise<boolean>;
|
|
31
33
|
/** Tree-to-tree unified diff. Covers `diff --binary from to` and `diff --name-only from to`. */
|
|
32
34
|
diffTree?: (from: string, to: string, opts?: DiffTreeOptions) => Promise<string>;
|
|
33
35
|
/** Commit log with custom format. Covers various `git log --format=... <range>` / `-1 <sha>` uses. */
|
|
34
36
|
log?: (opts: LogOptions) => Promise<string>;
|
|
35
37
|
/** Ref enumeration. Covers `for-each-ref`. */
|
|
36
38
|
forEachRef?: (opts: ForEachRefOptions) => Promise<string>;
|
|
39
|
+
/**
|
|
40
|
+
* List commits in a range alongside their immediate children. Covers `rev-list --children`.
|
|
41
|
+
* `children` includes every direct child, even those outside the queried range.
|
|
42
|
+
*/
|
|
43
|
+
revListChildren?: (opts: RevListChildrenOptions) => Promise<RevListChildrenEntry[]>;
|
|
37
44
|
/** Write the current (or temp) index to a tree object. Covers `write-tree`. */
|
|
38
45
|
writeTree?: (opts?: IndexScopedOptions) => Promise<string>;
|
|
39
46
|
/** Load a tree's contents into the current (or temp) index. Covers `read-tree <sha>`. */
|
|
@@ -112,12 +119,26 @@ interface LogOptions extends OpOptions {
|
|
|
112
119
|
noMerges?: boolean;
|
|
113
120
|
reverse?: boolean;
|
|
114
121
|
author?: string;
|
|
122
|
+
/** Force parents-before-children ordering. Maps to `--topo-order`. */
|
|
123
|
+
topoOrder?: boolean;
|
|
115
124
|
}
|
|
116
125
|
interface ForEachRefOptions extends OpOptions {
|
|
117
126
|
format: string;
|
|
118
127
|
prefix?: string;
|
|
119
128
|
sort?: string;
|
|
120
129
|
limit?: number;
|
|
130
|
+
/** When set, only returns refs pointing at the given commit SHA. Maps to `--points-at=<sha>`. */
|
|
131
|
+
pointsAt?: string;
|
|
132
|
+
}
|
|
133
|
+
interface RevListChildrenOptions extends OpOptions {
|
|
134
|
+
/** Commit range to query, e.g. `from..to`. */
|
|
135
|
+
range: string;
|
|
136
|
+
/** Reverse the output (oldest first). Maps to `--reverse`. */
|
|
137
|
+
reverse?: boolean;
|
|
138
|
+
}
|
|
139
|
+
interface RevListChildrenEntry {
|
|
140
|
+
sha: string;
|
|
141
|
+
children: string[];
|
|
121
142
|
}
|
|
122
143
|
/**
|
|
123
144
|
* Index-scoped options.
|
|
@@ -216,4 +237,4 @@ declare class ComposeGitPortMissingOpError extends Error {
|
|
|
216
237
|
constructor(op: string, hint?: string);
|
|
217
238
|
}
|
|
218
239
|
//#endregion
|
|
219
|
-
export { ApplyPatchOptions, ApplyPatchToWorkdirOptions, CheckoutOptions, CleanOptions, CommitTreeOptions, ComposeGitOps, ComposeGitPort, ComposeGitPortMissingOpError, DeleteBranchOptions, DiffTreeOptions, ForEachRefOptions, GitCommitIdentity, IndexScopedOptions, LogOptions, OpOptions, SigningConfig, StageAllOptions, StashPopOptions, StashPushOptions, UpdateRefOptions };
|
|
240
|
+
export { ApplyPatchOptions, ApplyPatchToWorkdirOptions, CheckoutOptions, CleanOptions, CommitTreeOptions, ComposeGitOps, ComposeGitPort, ComposeGitPortMissingOpError, DeleteBranchOptions, DiffTreeOptions, ForEachRefOptions, GitCommitIdentity, IndexScopedOptions, LogOptions, OpOptions, RevListChildrenEntry, RevListChildrenOptions, SigningConfig, StageAllOptions, StashPopOptions, StashPushOptions, UpdateRefOptions };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TaskInputError as e}from"../../errors/task.js";import{runAiLoop as t}from"../ai-loop.js";import{applyUserPromptOverride as n}from"../types.js";import{buildAnalyzeSystemPrompt as r,buildAnalyzeUserPrompt as i}from"./prompt.js";import{validateAnalyzeResponse as a}from"./validator.js";async function o(o){let s=o.hunks;if(!s||s.length===0)throw new e(`No hunks provided: supply 'hunks'`);if(o.session?.completedSteps.analyze)return{result:o.session.completedSteps.analyze,session:o.session,attempts:0,durationMs:0,callIds:[]};let c=n(i({hunks:s,commitMessages:o.commitMessages,commitOrder:o.commitOrder,branchName:o.branchName,baseBranch:o.baseBranch,issueUrl:o.issueUrl,pullRequestUrl:o.pullRequestUrl,instructions:o.instructions}),o.promptOverride),l=s.length,u=await t({model:o.model,systemPrompt:o.session?void 0:o.promptOverride?.system??r(),userPrompt:c,session:o.session,maxRetries:o.maxRetries,maxTokens:o.maxTokens,onProgress:o.onProgress,cancellation:o.cancellation,onBeforeModelCall:o.onBeforeModelCall,onAfterModelCall:o.onAfterModelCall,onBeforePrompt:o.onBeforePrompt,validate:e=>a(e,l),taskName:`analyze`}),d=o.session?.completedSteps??{},f={...u.session,completedSteps:{...d,analyze:u.result}};return{result:u.result,session:f,usage:u.usage,attempts:u.attempts,durationMs:u.durationMs,callIds:u.callIds}}export{o as analyze};
|
|
1
|
+
import{TaskInputError as e}from"../../errors/task.js";import{runAiLoop as t}from"../ai-loop.js";import{applyUserPromptOverride as n}from"../types.js";import{buildAnalyzeSystemPrompt as r,buildAnalyzeUserPrompt as i}from"./prompt.js";import{validateAnalyzeResponse as a}from"./validator.js";async function o(o){let s=o.hunks;if(!s||s.length===0)throw new e(`No hunks provided: supply 'hunks'`);if(o.session?.completedSteps.analyze)return{result:o.session.completedSteps.analyze,session:o.session,attempts:0,durationMs:0,callIds:[]};let c=n(i({hunks:s,commitMessages:o.commitMessages,commitOrder:o.commitOrder,branchName:o.branchName,baseBranch:o.baseBranch,issueUrl:o.issueUrl,pullRequestUrl:o.pullRequestUrl,instructions:o.instructions,redactHunkContent:o.redactHunkContent}),o.promptOverride),l=s.length,u=await t({model:o.model,systemPrompt:o.session?void 0:o.promptOverride?.system??r(),userPrompt:c,session:o.session,maxRetries:o.maxRetries,maxTokens:o.maxTokens,onProgress:o.onProgress,cancellation:o.cancellation,onBeforeModelCall:o.onBeforeModelCall,onAfterModelCall:o.onAfterModelCall,onBeforePrompt:o.onBeforePrompt,validate:e=>a(e,l),taskName:`analyze`}),d=o.session?.completedSteps??{},f={...u.session,completedSteps:{...d,analyze:u.result}};return{result:u.result,session:f,usage:u.usage,attempts:u.attempts,durationMs:u.durationMs,callIds:u.callIds}}export{o as analyze};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ComposeHunk } from "../types.js";
|
|
2
|
+
import { RedactHunkContent } from "../utils/redact.js";
|
|
2
3
|
|
|
3
4
|
//#region src/tasks/analyze/prompt.d.ts
|
|
4
5
|
declare function buildAnalyzeSystemPrompt(): string;
|
|
@@ -11,6 +12,7 @@ declare function buildAnalyzeUserPrompt(params: {
|
|
|
11
12
|
issueUrl?: string;
|
|
12
13
|
pullRequestUrl?: string;
|
|
13
14
|
instructions?: string;
|
|
15
|
+
redactHunkContent?: RedactHunkContent;
|
|
14
16
|
}): string;
|
|
15
17
|
//#endregion
|
|
16
18
|
export { buildAnalyzeSystemPrompt, buildAnalyzeUserPrompt };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{hunkContentForPrompt as e}from"../utils/redact.js";import{analysisResultSchema as t}from"./schema.js";import{z as n}from"zod";const r=JSON.stringify(n.toJSONSchema(t),null,2);function i(){return`You are an advanced AI code analysis assistant. Your task is to deeply analyze a set of code changes (provided as diff hunks) and produce a structured understanding of what the changes accomplish, what concerns they address, and how hunks relate to each other.
|
|
2
2
|
|
|
3
3
|
Your analysis must produce:
|
|
4
4
|
1. **Title** — a short, PR-style title for the changes (under 72 characters, imperative mood, e.g. "Add user authentication and session management"). This should capture the essence of what the changes accomplish.
|
|
@@ -25,10 +25,10 @@ Rules:
|
|
|
25
25
|
Output your analysis as JSON inside a <output> tag matching this schema:
|
|
26
26
|
|
|
27
27
|
\`\`\`json
|
|
28
|
-
${
|
|
28
|
+
${r}
|
|
29
29
|
\`\`\`
|
|
30
30
|
|
|
31
|
-
Return only the <output> tag and no other text.`}function
|
|
32
|
-
`)}\n</context>`),
|
|
31
|
+
Return only the <output> tag and no other text.`}function a(t){let{hunks:n,commitMessages:r,commitOrder:i,branchName:a,baseBranch:o,issueUrl:s,pullRequestUrl:c,instructions:l,redactHunkContent:u}=t,d=`Analyze the following code changes:\n\n<hunks>\n${JSON.stringify(n.map(t=>({index:t.index,fileName:t.fileName,hunkHeader:t.hunkHeader,content:e(t,u),...t.isBinary?{isBinary:!0}:{},...t.isRename?{isRename:!0}:{},...t.originalFileName?{originalFileName:t.originalFileName}:{}})))}\n</hunks>`,f=[];if(a&&f.push(`Branch: ${a}`),o&&f.push(`Base branch: ${o}`),s&&f.push(`Issue: ${s}`),c&&f.push(`Pull request: ${c}`),f.length>0&&(d+=`\n\n<context>\n${f.join(`
|
|
32
|
+
`)}\n</context>`),r?.length){let e=r.map((e,t)=>({index:t,sha:i?.[t],message:e}));d+=`\n\n<commit_messages>\n${JSON.stringify(e)}\n</commit_messages>`}return l&&(d+=`\n\nCarefully follow these additional instructions, but do not deviate from the output structure:\n${l}`),d+=`
|
|
33
33
|
|
|
34
|
-
Now analyze the changes and return your structured analysis. Return only the <output> tag and no other text.`,
|
|
34
|
+
Now analyze the changes and return your structured analysis. Return only the <output> tag and no other text.`,d}export{i as buildAnalyzeSystemPrompt,a as buildAnalyzeUserPrompt};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ProgressEvent, TokenUsage } from "../../ai/types.js";
|
|
2
2
|
import { ComposeHunk, PromptOverride } from "../types.js";
|
|
3
3
|
import { OnAfterModelCall, OnBeforeModelCall, OnBeforePrompt } from "../ai-loop.js";
|
|
4
|
+
import { RedactHunkContent } from "../utils/redact.js";
|
|
4
5
|
import { ComposeSession } from "../session.js";
|
|
5
6
|
import { AiModelPort } from "@gitkraken/shared-tools";
|
|
6
7
|
|
|
@@ -14,6 +15,8 @@ interface AnalyzeInput {
|
|
|
14
15
|
issueUrl?: string;
|
|
15
16
|
pullRequestUrl?: string;
|
|
16
17
|
instructions?: string;
|
|
18
|
+
/** See {@link RedactHunkContent}. */
|
|
19
|
+
redactHunkContent?: RedactHunkContent;
|
|
17
20
|
model: AiModelPort;
|
|
18
21
|
session?: ComposeSession;
|
|
19
22
|
maxRetries?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{TaskInputError as e}from"../../errors/task.js";import{runAiLoop as t}from"../ai-loop.js";import{applyUserPromptOverride as n}from"../types.js";import{validateGroupResponse as r}from"../group/validator.js";import{buildComposeGroupSystemPrompt as i,buildComposeGroupUserPrompt as a}from"./prompt.js";async function o(o){let s=o.hunks,c=o.mode??`branches`;if(!s||s.length===0)throw new e(`No hunks provided for compose-group`);if(o.session?.completedSteps.composeGroup)return{result:o.session.completedSteps.composeGroup,session:o.session,attempts:0,durationMs:0,callIds:[]};let l=o.promptOverride?.system??i(o.conventions,c,o.strategy,o.includeAnalysis,o.lightweight),u=n(a({hunks:s,commitMessages:o.commitMessages,commitOrder:o.commitOrder,branchName:o.branchName,baseBranch:o.baseBranch,issueUrl:o.issueUrl,pullRequestUrl:o.pullRequestUrl,instructions:o.instructions,condensed:o.condensed}),o.promptOverride),d=await t({model:o.model,systemPrompt:l,userPrompt:u,maxRetries:o.maxRetries,maxTokens:o.maxTokens,onProgress:o.onProgress,cancellation:o.cancellation,onBeforeModelCall:o.onBeforeModelCall,onAfterModelCall:o.onAfterModelCall,onBeforePrompt:o.onBeforePrompt,validate:e=>r(e,s.length,c,o.existingBranchNames),taskName:`compose-group`}),f=o.session?.completedSteps??{},p={...d.session,completedSteps:{...f,composeGroup:d.result}};return{result:d.result,session:p,usage:d.usage,attempts:d.attempts,durationMs:d.durationMs,callIds:d.callIds}}export{o as composeGroup};
|
|
1
|
+
import{TaskInputError as e}from"../../errors/task.js";import{runAiLoop as t}from"../ai-loop.js";import{applyUserPromptOverride as n}from"../types.js";import{validateGroupResponse as r}from"../group/validator.js";import{buildComposeGroupSystemPrompt as i,buildComposeGroupUserPrompt as a}from"./prompt.js";async function o(o){let s=o.hunks,c=o.mode??`branches`;if(!s||s.length===0)throw new e(`No hunks provided for compose-group`);if(o.session?.completedSteps.composeGroup)return{result:o.session.completedSteps.composeGroup,session:o.session,attempts:0,durationMs:0,callIds:[]};let l=o.promptOverride?.system??i(o.conventions,c,o.strategy,o.includeAnalysis,o.lightweight),u=n(a({hunks:s,commitMessages:o.commitMessages,commitOrder:o.commitOrder,branchName:o.branchName,baseBranch:o.baseBranch,issueUrl:o.issueUrl,pullRequestUrl:o.pullRequestUrl,instructions:o.instructions,condensed:o.condensed,redactHunkContent:o.redactHunkContent}),o.promptOverride),d=await t({model:o.model,systemPrompt:l,userPrompt:u,maxRetries:o.maxRetries,maxTokens:o.maxTokens,onProgress:o.onProgress,cancellation:o.cancellation,onBeforeModelCall:o.onBeforeModelCall,onAfterModelCall:o.onAfterModelCall,onBeforePrompt:o.onBeforePrompt,validate:e=>r(e,s.length,c,o.existingBranchNames),taskName:`compose-group`}),f=o.session?.completedSteps??{},p={...d.session,completedSteps:{...f,composeGroup:d.result}};return{result:d.result,session:p,usage:d.usage,attempts:d.attempts,durationMs:d.durationMs,callIds:d.callIds}}export{o as composeGroup};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ComposeHunk } from "../types.js";
|
|
2
2
|
import { ConventionDescriptor } from "../../git/utils/conventions.js";
|
|
3
|
+
import { RedactHunkContent } from "../utils/redact.js";
|
|
3
4
|
import { GroupingStrategy } from "../group/types.js";
|
|
4
5
|
|
|
5
6
|
//#region src/tasks/compose-group/prompt.d.ts
|
|
@@ -21,6 +22,7 @@ declare function buildComposeGroupUserPrompt(params: {
|
|
|
21
22
|
pullRequestUrl?: string;
|
|
22
23
|
instructions?: string;
|
|
23
24
|
condensed?: boolean;
|
|
25
|
+
redactHunkContent?: RedactHunkContent;
|
|
24
26
|
}): string;
|
|
25
27
|
//#endregion
|
|
26
28
|
export { buildComposeGroupSystemPrompt, buildComposeGroupUserPrompt };
|