@gitkraken/conflict-tools 0.0.1-beta.7 → 0.0.1-beta.8

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.
@@ -1,5 +1,5 @@
1
1
  function e(e,n,r){let i=e.split(`
2
- `),a=new Map;for(let e of r)a.set(e.markerIndex,e);let o=[],s=0;for(let e=0;e<n.length;e++){let r=n[e];if(!r)continue;let c=a.get(e);if(!c)continue;r.startLine>s&&o.push(i.slice(s,r.startLine).join(`
2
+ `),a=new Map;for(let e of r)a.set(e.markerIndex,e);let o=[],s=0;for(let e=0;e<n.length;e++){let r=n[e];if(!r)continue;let c=a.get(e);if(!c)throw Error(`Missing resolved chunk for markerIndex ${e}. Every conflict marker must have a corresponding chunk.`);r.startLine>s&&o.push(i.slice(s,r.startLine).join(`
3
3
  `));let l=t(c,r);l!==``&&o.push(l),s=r.endLine+1}return s<i.length&&o.push(i.slice(s).join(`
4
4
  `)),o.join(`
5
5
  `)}function t(e,t){switch(e.strategy){case`ours`:return t.ours;case`theirs`:return t.theirs;case`merged`:{let i=e.content.split(`
@@ -1 +1 @@
1
- import{applyChunks as e}from"./chunk-apply.js";function t(t,i,a){let o=i;a.fileStrategy&&a.fileStrategy!==`deleted`&&(o=t.markers.map((e,t)=>({markerIndex:t,strategy:a.fileStrategy})));let s=a.description!==void 0&&a.description.trim().length>0?a.description:r(o),c;c=a.fileStrategy===`deleted`?`deleted`:a.fileStrategy?a.fileStrategy===`ours`?`take-ours`:`take-theirs`:n(o);let l=a.fileStrategy===`deleted`?``:e(t.rawContent,t.markers,o);return{filePath:t.filePath,content:l,strategy:c,confidence:a.confidence,description:s,chunks:o,...a.metrics?{metrics:a.metrics}:{}}}function n(e){if(e.length===0)return`skipped`;let t=new Set(e.map(e=>e.strategy));if(t.size===1){if(t.has(`ours`))return`take-ours`;if(t.has(`theirs`))return`take-theirs`}return`ai`}function r(e){if(e.length===0)return`No markers resolved.`;let t=new Set(e.map(e=>e.strategy));if(t.size===1){if(t.has(`ours`))return`All markers resolved by taking ours.`;if(t.has(`theirs`))return`All markers resolved by taking theirs.`}return`Resolved ${e.length} marker(s) with mixed strategies.`}export{t as createResolution};
1
+ import{applyChunks as e}from"./chunk-apply.js";function t(t,i,a){let o=i;a.fileStrategy&&a.fileStrategy!==`deleted`&&(o=t.markers.map((e,t)=>({markerIndex:t,strategy:a.fileStrategy})));let s=a.description!==void 0&&a.description.trim().length>0?a.description:r(o),c;c=a.fileStrategy===`deleted`?`deleted`:a.fileStrategy?a.fileStrategy===`ours`?`take-ours`:`take-theirs`:n(o);let l=a.fileStrategy===`deleted`||o.length===0?``:e(t.rawContent,t.markers,o);return{filePath:t.filePath,content:l,strategy:c,confidence:a.confidence,description:s,chunks:o,...a.metrics?{metrics:a.metrics}:{}}}function n(e){if(e.length===0)return`skipped`;let t=new Set(e.map(e=>e.strategy));if(t.size===1){if(t.has(`ours`))return`take-ours`;if(t.has(`theirs`))return`take-theirs`}return`ai`}function r(e){if(e.length===0)return`No markers resolved.`;let t=new Set(e.map(e=>e.strategy));if(t.size===1){if(t.has(`ours`))return`All markers resolved by taking ours.`;if(t.has(`theirs`))return`All markers resolved by taking theirs.`}return`Resolved ${e.length} marker(s) with mixed strategies.`}export{t as createResolution};
@@ -1 +1 @@
1
- import{AIError as e}from"../errors/ai.js";import{applyChunks as t}from"../resolution/chunk-apply.js";import{parseModelResponse as n}from"./parse-response.js";import{buildPrompt as r}from"./prompt.js";import{createResolverTools as i}from"./tools.js";import{validateChunks as a}from"./validate.js";async function o(o,c,l){let u=l.config?.maxSteps??15,d=l.config?.temperature??0,{definitions:f,execute:p}=i(l.git),{system:m,userMessage:h}=r(o,c,{maxSteps:u}),g=[{role:`user`,content:h}],_=l.signal?{signal:l.signal}:void 0,v=0,y=0,b=[];for(;v<u;){v++;let e=await l.model.generate({system:m,messages:[...g],tools:f,temperature:d,signal:l.signal});if(e.usage&&(b.push(e.usage),l.onProgress?.({type:`resolver:step-usage`,filePath:o.filePath,stepNumber:v,usage:e.usage})),e.toolCalls&&e.toolCalls.length>0){g.push({role:`assistant`,content:e.text,toolCalls:e.toolCalls});for(let t of e.toolCalls){let e=typeof t.args.reason==`string`?t.args.reason:void 0;l.onProgress?.({type:`resolver:tool-call`,filePath:o.filePath,tool:t.name,args:t.args,stepNumber:v,reason:e}),y++;let n=await p(t,_);g.push({role:`tool`,toolCallId:n.toolCallId,toolName:t.name,content:n.content})}continue}let r=e.text??``;if(!r.trim()){g.push({role:`assistant`,content:``}),g.push({role:`user`,content:`Your response was empty. Please respond with a valid JSON object containing "confidence" (0-1), "description" (1-2 sentences), and either "strategy" ("ours", "theirs", or "deleted") for a file-level decision, or "chunks" (array of { markerIndex, strategy, content? }).`});continue}let i;try{i=n(r,o.markers.length)}catch(e){let t=e instanceof Error?e.message:String(e);g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`Failed to parse your response: ${t}. Please respond with a valid JSON object containing "confidence" (0-1), "description" (1-2 sentences), and either "strategy" ("ours", "theirs", or "deleted") for a file-level decision, or "chunks" (array of { markerIndex, strategy, content? }).`});continue}if(i.strategy===`deleted`&&o.type!==`delete-modify`){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`Strategy "deleted" is only valid for delete-modify conflicts. This is a text conflict — respond with "chunks" or a file-level "ours"/"theirs" strategy.`});continue}if(i.strategy)return{chunks:i.chunks,strategy:i.strategy,confidence:i.confidence,description:i.description,metrics:s(b,v,y)};if(o.markers.length===0&&!i.strategy){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`Delete-modify conflicts require a file-level strategy field ("ours", "theirs", or "deleted"). Please respond with a JSON object containing "strategy".`});continue}let c=a(i.chunks,o);if(!c.valid){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`Validation failed: ${c.feedback}\nPlease fix the issues and respond with a corrected JSON object. Make sure every marker index appears exactly once, or use a top-level "strategy" field.`});continue}if(l.verifier&&o.type===`text`){let e=t(o.rawContent,o.markers,i.chunks),n=await l.verifier.verify(o.filePath,e);if(!n.valid){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`Verification failed: ${n.feedback??`Content did not pass verification.`}\nPlease fix and respond with corrected JSON.`});continue}}return{chunks:i.chunks,confidence:i.confidence,description:i.description,metrics:s(b,v,y)}}throw new e(`VALIDATION_EXHAUSTED`,`Resolver exhausted ${u} steps without producing a valid resolution for ${o.filePath}.`)}function s(e,t,n){let r={inputTokens:0,outputTokens:0};for(let t of e)r.inputTokens+=t.inputTokens,r.outputTokens+=t.outputTokens,t.cacheReadTokens&&(r.cacheReadTokens=(r.cacheReadTokens??0)+t.cacheReadTokens),t.cacheWriteTokens&&(r.cacheWriteTokens=(r.cacheWriteTokens??0)+t.cacheWriteTokens),t.reasoningTokens&&(r.reasoningTokens=(r.reasoningTokens??0)+t.reasoningTokens),t.cost&&(r.cost=(r.cost??0)+t.cost);return{...r,stepCount:t,toolCallCount:n}}export{o as runResolverLoop};
1
+ import{AIError as e}from"../errors/ai.js";import{applyChunks as t}from"../resolution/chunk-apply.js";import{parseModelResponse as n}from"./parse-response.js";import{buildPrompt as r}from"./prompt.js";import{createResolverTools as i}from"./tools.js";import{validateChunks as a}from"./validate.js";async function o(o,c,l){let u=l.config?.maxSteps??15,d=l.config?.temperature??0,{definitions:f,execute:p}=i(l.git),{system:m,userMessage:h}=r(o,c,{maxSteps:u}),g=[{role:`user`,content:h}],_=l.signal?{signal:l.signal}:void 0,v=0,y=0,b=[];for(;v<u;){v++;let e=await l.model.generate({system:m,messages:[...g],tools:f,temperature:d,signal:l.signal});if(e.usage&&(b.push(e.usage),l.onProgress?.({type:`resolver:step-usage`,filePath:o.filePath,stepNumber:v,usage:e.usage})),e.toolCalls&&e.toolCalls.length>0){g.push({role:`assistant`,content:e.text,toolCalls:e.toolCalls});for(let t of e.toolCalls){let e=typeof t.args.reason==`string`?t.args.reason:void 0;l.onProgress?.({type:`resolver:tool-call`,filePath:o.filePath,tool:t.name,args:t.args,stepNumber:v,reason:e}),y++;let n=await p(t,_);g.push({role:`tool`,toolCallId:n.toolCallId,toolName:t.name,content:n.content})}continue}let r=e.text??``;if(!r.trim()){g.push({role:`assistant`,content:``}),g.push({role:`user`,content:`[Step ${v}/${u}] Your response was empty. Please respond with a valid JSON object containing "confidence" (0-1), "description" (1-2 sentences), and either "strategy" ("ours", "theirs", or "deleted") for a file-level decision, or "chunks" (array of { markerIndex, strategy, content? }).`});continue}let i;try{i=n(r,o.markers.length)}catch(e){let t=e instanceof Error?e.message:String(e);g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`[Step ${v}/${u}] Failed to parse your response: ${t}. Please respond with a valid JSON object containing "confidence" (0-1), "description" (1-2 sentences), and either "strategy" ("ours", "theirs", or "deleted") for a file-level decision, or "chunks" (array of { markerIndex, strategy, content? }).`});continue}if(i.strategy===`deleted`&&o.type!==`delete-modify`){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`[Step ${v}/${u}] Strategy "deleted" is only valid for delete-modify conflicts. This is a text conflict — respond with "chunks" or a file-level "ours"/"theirs" strategy.`});continue}if(i.strategy)return{chunks:i.chunks,strategy:i.strategy,confidence:i.confidence,description:i.description,metrics:s(b,v,y)};if(o.markers.length===0&&!i.strategy){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`[Step ${v}/${u}] Delete-modify conflicts require a file-level strategy field ("ours", "theirs", or "deleted"). Please respond with a JSON object containing "strategy".`});continue}let c=a(i.chunks,o);if(!c.valid){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`[Step ${v}/${u}] Validation failed: ${c.feedback}\nPlease fix the issues and respond with a corrected JSON object. Make sure every marker index appears exactly once, or use a top-level "strategy" field.`});continue}if(l.verifier&&o.type===`text`){let e=t(o.rawContent,o.markers,i.chunks),n=await l.verifier.verify(o.filePath,e);if(!n.valid){g.push({role:`assistant`,content:r}),g.push({role:`user`,content:`[Step ${v}/${u}] Verification failed: ${n.feedback??`Content did not pass verification.`}\nPlease fix and respond with corrected JSON.`});continue}}return{chunks:i.chunks,confidence:i.confidence,description:i.description,metrics:s(b,v,y)}}throw new e(`VALIDATION_EXHAUSTED`,`Resolver exhausted ${u} steps without producing a valid resolution for ${o.filePath}.`)}function s(e,t,n){let r={inputTokens:0,outputTokens:0};for(let t of e)r.inputTokens+=t.inputTokens,r.outputTokens+=t.outputTokens,t.cacheReadTokens&&(r.cacheReadTokens=(r.cacheReadTokens??0)+t.cacheReadTokens),t.cacheWriteTokens&&(r.cacheWriteTokens=(r.cacheWriteTokens??0)+t.cacheWriteTokens),t.reasoningTokens&&(r.reasoningTokens=(r.reasoningTokens??0)+t.reasoningTokens),t.cost&&(r.cost=(r.cost??0)+t.cost);return{...r,stepCount:t,toolCallCount:n}}export{o as runResolverLoop};
@@ -1 +1 @@
1
- function e(e,n){let r=t(e);if(r===null)throw Error(`No valid JSON object found in model response.`);let i;try{i=JSON.parse(r)}catch{throw Error(`Failed to parse JSON from model response.`)}if(typeof i!=`object`||!i||Array.isArray(i))throw Error(`Model response must be a JSON object.`);let a=i,o=a.confidence;if(typeof o!=`number`||!Number.isFinite(o)||o<0||o>1)throw Error(`Field "confidence" must be a number in [0, 1].`);let s=a.description;if(typeof s!=`string`||s.trim().length===0)throw Error(`Field "description" must be a non-empty string.`);if(a.strategy!==void 0){let e=a.strategy;if(e!==`ours`&&e!==`theirs`&&e!==`deleted`)throw Error(`Field "strategy" must be "ours", "theirs", or "deleted".`);return{confidence:o,description:s.trim(),chunks:[],strategy:e}}let c=a.chunks;if(!Array.isArray(c))throw Error(`Field "chunks" must be an array. Each chunk needs { markerIndex, strategy, content? }.`);let l=[];for(let e of c){if(typeof e!=`object`||!e)throw Error(`Each chunk must be an object.`);let t=e,r=t.markerIndex,i=t.strategy;if(typeof r!=`number`||!Number.isInteger(r))throw Error(`Each chunk must have an integer markerIndex.`);if(r<0||r>=n)throw Error(`markerIndex ${r} is out of range. Valid range: 0..${n-1}.`);if(i===`ours`||i===`theirs`)l.push({markerIndex:r,strategy:i});else if(i===`merged`){let e=t.content;if(typeof e!=`string`)throw Error(`Chunk at markerIndex ${r} with strategy "merged" must have a string "content".`);l.push({markerIndex:r,strategy:i,content:e})}else throw Error(`Unknown strategy "${String(i)}" at markerIndex ${r}. Valid strategies: "ours", "theirs", "merged".`)}return{confidence:o,description:s.trim(),chunks:l}}function t(e){let t=e.trim(),n=/```(?:json)?\s*\n([\s\S]*?)\n\s*```/.exec(t);if(n){let e=n[1];if(e!==void 0)return e.trim()}let r=/\{[\s\S]*\}/.exec(t);return r?r[0]:null}export{e as parseModelResponse};
1
+ function e(e,n){let r=t(e);if(r===null)throw Error(`No valid JSON object found in model response.`);let i;try{i=JSON.parse(r)}catch{throw Error(`Failed to parse JSON from model response.`)}if(typeof i!=`object`||!i||Array.isArray(i))throw Error(`Model response must be a JSON object.`);let a=i,o=a.confidence;if(typeof o!=`number`||!Number.isFinite(o)||o<0||o>1)throw Error(`Field "confidence" must be a number in [0, 1].`);let s=a.description;if(typeof s!=`string`||s.trim().length===0)throw Error(`Field "description" must be a non-empty string.`);if(a.strategy!==void 0){let e=a.strategy;if(e!==`ours`&&e!==`theirs`&&e!==`deleted`)throw Error(`Field "strategy" must be "ours", "theirs", or "deleted".`);return{confidence:o,description:s.trim(),chunks:[],strategy:e}}let c=a.chunks;if(!Array.isArray(c))throw Error(`Field "chunks" must be an array. Each chunk needs { markerIndex, strategy, content? }.`);let l=[];for(let e of c){if(typeof e!=`object`||!e)throw Error(`Each chunk must be an object.`);let t=e,r=t.markerIndex,i=t.strategy;if(typeof r!=`number`||!Number.isInteger(r))throw Error(`Each chunk must have an integer markerIndex.`);if(n===0)throw Error(`This conflict has no markers (delete-modify). Use a file-level "strategy" field ("ours", "theirs", or "deleted") instead of "chunks" with markerIndex.`);if(r<0||r>=n)throw Error(`markerIndex ${r} is out of range. Valid range: 0..${n-1}.`);if(i===`ours`||i===`theirs`)l.push({markerIndex:r,strategy:i});else if(i===`merged`){let e=t.content;if(typeof e!=`string`)throw Error(`Chunk at markerIndex ${r} with strategy "merged" must have a string "content".`);l.push({markerIndex:r,strategy:i,content:e})}else throw Error(`Unknown strategy "${String(i)}" at markerIndex ${r}. Valid strategies: "ours", "theirs", "merged".`)}return{confidence:o,description:s.trim(),chunks:l}}function t(e){let t=e.trim(),n=/```(?:json)?\s*\n([\s\S]*?)\n\s*```/.exec(t);if(n){let e=n[1];if(e!==void 0)return e.trim()}let r=/\{[\s\S]*\}/.exec(t);return r?r[0]:null}export{e as parseModelResponse};
@@ -4,8 +4,6 @@ You will receive a file with conflict markers. Each marker has an "ours" side (c
4
4
 
5
5
  When provided, the "Three-way diffs" section shows what each side changed relative to the common ancestor. Prefer resolving from this data and the conflict markers. Use the tools (show_file_at_ref, grep, blame, diff, log, show) only when the provided context is insufficient.
6
6
 
7
- You have access to tools to inspect the repository: show_file_at_ref, grep, blame, diff, log, show. Use them to understand the intent behind each change before resolving.
8
-
9
7
  You have a budget of ${t??15} tool-calling steps. If you have used more than half your budget without resolving, stop investigating and produce your best resolution now.
10
8
 
11
9
  Tool outputs are capped to keep context manageable. Prefer narrow queries: pass startLine/endLine when you need specific regions of a file, use path scope on grep/log, and use specific patterns over broad ones. If a tool response includes a 'capped' header, the underlying data is larger — re-run with a narrower range or filter to see other regions.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gitkraken/conflict-tools",
3
- "version": "0.0.1-beta.7",
3
+ "version": "0.0.1-beta.8",
4
4
  "description": "AI-powered git conflict resolution.",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Axosoft, LLC dba GitKraken",