@cuongtran001/kanna 1.2.0 → 1.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/dist/client/assets/{arc-BLk1CZKB.js → arc-DXtN3EWJ.js} +1 -1
- package/dist/client/assets/{architectureDiagram-3BPJPVTR-B01ZQYte.js → architectureDiagram-3BPJPVTR-CIGqW1z-.js} +1 -1
- package/dist/client/assets/{blockDiagram-GPEHLZMM-diL6a3cq.js → blockDiagram-GPEHLZMM-BafNS_H6.js} +1 -1
- package/dist/client/assets/{c4Diagram-AAUBKEIU-BY1verL8.js → c4Diagram-AAUBKEIU-YdAgRSis.js} +1 -1
- package/dist/client/assets/channel-BEYTrUAm.js +1 -0
- package/dist/client/assets/{chunk-2J33WTMH-psdZuajw.js → chunk-2J33WTMH-eiP5y5G-.js} +1 -1
- package/dist/client/assets/{chunk-4BX2VUAB-CrwQVBc5.js → chunk-4BX2VUAB-CvLGzPMF.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-9-aj4jKO.js → chunk-55IACEB6-Y-S9Fb8A.js} +1 -1
- package/dist/client/assets/{chunk-727SXJPM-1FNK9_nB.js → chunk-727SXJPM-6sJH1RI9.js} +1 -1
- package/dist/client/assets/{chunk-AQP2D5EJ-DFhvd_Ek.js → chunk-AQP2D5EJ-hV1r_IXO.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-B7MLrDa7.js → chunk-FMBD7UC4-CC3L28S5.js} +1 -1
- package/dist/client/assets/{chunk-ND2GUHAM-D4Df05QE.js → chunk-ND2GUHAM-BZ3czhdH.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-Iq17Dznm.js → chunk-QZHKN3VN-Bjyd6Yr-.js} +1 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-CvnF5Ud6.js +1 -0
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-CvnF5Ud6.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-BmaZhtXy.js → cose-bilkent-S5V4N54A-CfxdDghE.js} +1 -1
- package/dist/client/assets/{dagre-BM42HDAG-BCmpfnfP.js → dagre-BM42HDAG-B8CddsbB.js} +1 -1
- package/dist/client/assets/{diagram-2AECGRRQ-BIEcKowS.js → diagram-2AECGRRQ-F0yS0fVB.js} +1 -1
- package/dist/client/assets/{diagram-5GNKFQAL-CRBABBfv.js → diagram-5GNKFQAL-cW0i0qlh.js} +1 -1
- package/dist/client/assets/{diagram-KO2AKTUF-BRxUk16N.js → diagram-KO2AKTUF-BzAKMeJT.js} +1 -1
- package/dist/client/assets/{diagram-LMA3HP47-DPBs4xl1.js → diagram-LMA3HP47-qdC4XqIl.js} +1 -1
- package/dist/client/assets/{diagram-OG6HWLK6-BE9rgVv8.js → diagram-OG6HWLK6-CGcpi6Dh.js} +1 -1
- package/dist/client/assets/{erDiagram-TEJ5UH35-D3vgA1xJ.js → erDiagram-TEJ5UH35-CxNTDicM.js} +1 -1
- package/dist/client/assets/{flowDiagram-I6XJVG4X-Cgu-8XXC.js → flowDiagram-I6XJVG4X-qkGa5TqY.js} +1 -1
- package/dist/client/assets/{ganttDiagram-6RSMTGT7-CgjXVyTR.js → ganttDiagram-6RSMTGT7-D9mVPoQi.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-PVQCEYII-zD5D8B-i.js → gitGraphDiagram-PVQCEYII-DA0grAXe.js} +1 -1
- package/dist/client/assets/{index-DBTdhMbJ.js → index-BqUY1Bm4.js} +1 -1
- package/dist/client/assets/index-CLsOWXff.css +32 -0
- package/dist/client/assets/{index-zQLLeAfl.js → index-TU1k6ov6.js} +253 -243
- package/dist/client/assets/{infoDiagram-5YYISTIA-BaFHqT4u.js → infoDiagram-5YYISTIA-CGljtLs3.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-YF4QCWOH-2yAC1br2.js → ishikawaDiagram-YF4QCWOH-CtC0xrmG.js} +1 -1
- package/dist/client/assets/{journeyDiagram-JHISSGLW-DacQ-ND5.js → journeyDiagram-JHISSGLW-URLnVZeN.js} +1 -1
- package/dist/client/assets/{kanban-definition-UN3LZRKU-Qlbwm3z4.js → kanban-definition-UN3LZRKU-C2Q6aqQh.js} +1 -1
- package/dist/client/assets/{linear-DeafqpgO.js → linear-ByKHtsIx.js} +1 -1
- package/dist/client/assets/{mermaid.core-KYiCPJDj.js → mermaid.core-Dl_f2KLc.js} +4 -4
- package/dist/client/assets/{mindmap-definition-RKZ34NQL-B1V-T6d3.js → mindmap-definition-RKZ34NQL-CaJ9IDLI.js} +1 -1
- package/dist/client/assets/{pieDiagram-4H26LBE5-DOF9OFRu.js → pieDiagram-4H26LBE5-mmYaf2Oa.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-W4KKPZXB-lH1mB7ko.js → quadrantDiagram-W4KKPZXB-B_PO6OCC.js} +1 -1
- package/dist/client/assets/{requirementDiagram-4Y6WPE33-BaTsJ_sS.js → requirementDiagram-4Y6WPE33-M4huwJt1.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-5OEKKPKP-Pfxib5iI.js → sankeyDiagram-5OEKKPKP-B0hb1sWh.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-3UESZ5HK-BQMEKkBC.js → sequenceDiagram-3UESZ5HK-BAqSptnA.js} +1 -1
- package/dist/client/assets/{stateDiagram-AJRCARHV-CuldNnzp.js → stateDiagram-AJRCARHV-DTNkvPi5.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-CVN3oGTF.js +1 -0
- package/dist/client/assets/{timeline-definition-PNZ67QCA-DP7u0YAg.js → timeline-definition-PNZ67QCA-MgAjHz8Q.js} +1 -1
- package/dist/client/assets/{vennDiagram-CIIHVFJN-QlrjpNeQ.js → vennDiagram-CIIHVFJN-DmKoO51W.js} +1 -1
- package/dist/client/assets/{wardley-L42UT6IY-BqdJ_sAM.js → wardley-L42UT6IY-CWcyHnYs.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-YWT4CUSO-Wi3kaQ5X.js → wardleyDiagram-YWT4CUSO-BGIGmFP9.js} +1 -1
- package/dist/client/assets/{xychartDiagram-2RQKCTM6-D-KXMyCG.js → xychartDiagram-2RQKCTM6-D20YIvEl.js} +1 -1
- package/dist/client/index.html +2 -2
- package/package.json +1 -1
- package/src/server/agent-coordinator-types.ts +158 -0
- package/src/server/agent-coordinator.ts +919 -0
- package/src/server/agent-deps-builders.ts +425 -0
- package/src/server/agent.oauth-rotation.test.ts +101 -0
- package/src/server/agent.test.ts +24 -8
- package/src/server/agent.ts +35 -4963
- package/src/server/auto-continue/read-model.test.ts +2 -2
- package/src/server/auto-continue/read-model.ts +4 -1
- package/src/server/claude-autocontinue-commands.test.ts +494 -0
- package/src/server/claude-autocontinue-commands.ts +256 -0
- package/src/server/claude-cancel-handler.test.ts +472 -0
- package/src/server/claude-cancel-handler.ts +241 -0
- package/src/server/claude-chat-management.test.ts +395 -0
- package/src/server/claude-chat-management.ts +251 -0
- package/src/server/claude-harness-stream.test.ts +273 -0
- package/src/server/claude-harness-stream.ts +158 -0
- package/src/server/claude-loop-orch-commands.test.ts +579 -0
- package/src/server/claude-loop-orch-commands.ts +466 -0
- package/src/server/claude-message-normalizer.test.ts +213 -0
- package/src/server/claude-message-normalizer.ts +436 -0
- package/src/server/claude-prompt-helpers.test.ts +248 -0
- package/src/server/claude-prompt-helpers.ts +139 -0
- package/src/server/claude-sdk-queue.test.ts +169 -0
- package/src/server/claude-sdk-queue.ts +82 -0
- package/src/server/claude-send-command.test.ts +414 -0
- package/src/server/claude-send-command.ts +420 -0
- package/src/server/claude-session-config-helpers.test.ts +279 -0
- package/src/server/claude-session-config-helpers.ts +151 -0
- package/src/server/claude-session-config.test.ts +250 -0
- package/src/server/claude-session-config.ts +159 -0
- package/src/server/claude-session-error-handler.test.ts +498 -0
- package/src/server/claude-session-error-handler.ts +361 -0
- package/src/server/claude-session-lifecycle.test.ts +669 -0
- package/src/server/claude-session-lifecycle.ts +283 -0
- package/src/server/claude-session-rebuild.test.ts +224 -0
- package/src/server/claude-session-rebuild.ts +101 -0
- package/src/server/claude-session-runner.test.ts +523 -0
- package/src/server/claude-session-runner.ts +521 -0
- package/src/server/claude-session-spawner.test.ts +401 -0
- package/src/server/claude-session-spawner.ts +401 -0
- package/src/server/claude-session-start.test.ts +205 -0
- package/src/server/claude-session-start.ts +277 -0
- package/src/server/claude-session-state-queries.test.ts +344 -0
- package/src/server/claude-session-state-queries.ts +160 -0
- package/src/server/claude-session-state.ts +104 -0
- package/src/server/claude-slash-commands.test.ts +277 -0
- package/src/server/claude-slash-commands.ts +234 -0
- package/src/server/claude-spawn-helpers.test.ts +221 -0
- package/src/server/claude-spawn-helpers.ts +179 -0
- package/src/server/claude-steer-log.test.ts +243 -0
- package/src/server/claude-steer-log.ts +58 -0
- package/src/server/claude-subagent-tool-response.test.ts +213 -0
- package/src/server/claude-subagent-tool-response.ts +165 -0
- package/src/server/claude-subagent-wiring.test.ts +263 -0
- package/src/server/claude-subagent-wiring.ts +324 -0
- package/src/server/claude-tool-respond.test.ts +321 -0
- package/src/server/claude-tool-respond.ts +142 -0
- package/src/server/claude-turn-runner.test.ts +310 -0
- package/src/server/claude-turn-runner.ts +228 -0
- package/src/server/claude-turn-starter.test.ts +266 -0
- package/src/server/claude-turn-starter.ts +566 -0
- package/src/server/claude-usage-math.test.ts +169 -0
- package/src/server/claude-usage-math.ts +132 -0
- package/src/server/diff-store-branch-ops.adapter.test.ts +332 -0
- package/src/server/diff-store-branch-ops.adapter.ts +602 -0
- package/src/server/diff-store-commit-ops.adapter.test.ts +358 -0
- package/src/server/diff-store-commit-ops.adapter.ts +258 -0
- package/src/server/diff-store-errors.ts +85 -0
- package/src/server/diff-store-file-ops.adapter.ts +212 -0
- package/src/server/diff-store-git-branch.adapter.ts +686 -0
- package/src/server/diff-store-io.adapter.ts +27 -0
- package/src/server/diff-store-parse.test.ts +212 -0
- package/src/server/diff-store-parse.ts +122 -0
- package/src/server/diff-store-state.ts +82 -0
- package/src/server/diff-store.ts +76 -1854
- package/src/server/event-store-apply.test.ts +280 -0
- package/src/server/event-store-apply.ts +132 -0
- package/src/server/event-store-chat-lifecycle.test.ts +408 -0
- package/src/server/event-store-chat-lifecycle.ts +441 -0
- package/src/server/event-store-entity-write.ts +356 -0
- package/src/server/event-store-helpers.test.ts +230 -0
- package/src/server/event-store-helpers.ts +235 -0
- package/src/server/event-store-init.ts +276 -0
- package/src/server/event-store-messages.adapter.test.ts +365 -0
- package/src/server/event-store-messages.adapter.ts +213 -0
- package/src/server/event-store-orch-subscription.ts +124 -0
- package/src/server/event-store-orch.test.ts +462 -0
- package/src/server/event-store-orch.ts +312 -0
- package/src/server/event-store-peripheral-events.adapter.test.ts +254 -0
- package/src/server/event-store-peripheral-events.adapter.ts +105 -0
- package/src/server/event-store-snapshot.test.ts +597 -0
- package/src/server/event-store-snapshot.ts +658 -0
- package/src/server/event-store-subagent.test.ts +408 -0
- package/src/server/event-store-subagent.ts +198 -0
- package/src/server/event-store-tool-requests.test.ts +210 -0
- package/src/server/event-store-tool-requests.ts +131 -0
- package/src/server/event-store-transcript-write.adapter.ts +285 -0
- package/src/server/event-store-write-ops.test.ts +554 -0
- package/src/server/event-store-write-ops.ts +529 -0
- package/src/server/event-store.test.ts +35 -0
- package/src/server/event-store.ts +251 -2284
- package/src/server/events.ts +3 -0
- package/src/server/harness-types.ts +15 -1
- package/src/server/oauth-errors.ts +19 -0
- package/src/server/read-models.ts +26 -1
- package/src/server/subagent-orchestrator.ts +3 -0
- package/src/server/ws-router-agent-ctrl.test.ts +187 -0
- package/src/server/ws-router-agent-ctrl.ts +137 -0
- package/src/server/ws-router-broadcast.ts +488 -0
- package/src/server/ws-router-chat.test.ts +461 -0
- package/src/server/ws-router-chat.ts +279 -0
- package/src/server/ws-router-defaults.test.ts +283 -0
- package/src/server/ws-router-defaults.ts +434 -0
- package/src/server/ws-router-diff.test.ts +167 -0
- package/src/server/ws-router-diff.ts +250 -0
- package/src/server/ws-router-envelope.ts +329 -0
- package/src/server/ws-router-misc.test.ts +422 -0
- package/src/server/ws-router-misc.ts +265 -0
- package/src/server/ws-router-orch.test.ts +190 -0
- package/src/server/ws-router-orch.ts +93 -0
- package/src/server/ws-router-project.test.ts +403 -0
- package/src/server/ws-router-project.ts +256 -0
- package/src/server/ws-router-push.test.ts +193 -0
- package/src/server/ws-router-push.ts +120 -0
- package/src/server/ws-router-settings.test.ts +173 -0
- package/src/server/ws-router-settings.ts +416 -0
- package/src/server/ws-router-skills.test.ts +194 -0
- package/src/server/ws-router-skills.ts +204 -0
- package/src/server/ws-router-utils.ts +224 -0
- package/src/server/ws-router.ts +339 -2254
- package/src/shared/app-settings-types.ts +365 -0
- package/src/shared/core-types.ts +27 -0
- package/src/shared/git-diff-types.ts +165 -0
- package/src/shared/loop-progress.test.ts +106 -0
- package/src/shared/loop-progress.ts +88 -0
- package/src/shared/mcp-types.ts +105 -0
- package/src/shared/provider-model-types.ts +437 -0
- package/src/shared/subagent-types.ts +198 -0
- package/src/shared/tool-call-types.ts +314 -0
- package/src/shared/transcript-types.ts +270 -0
- package/src/shared/types.ts +27 -1668
- package/dist/client/assets/channel-BMkhjiLI.js +0 -1
- package/dist/client/assets/classDiagram-4FO5ZUOK-C5Kg1XOD.js +0 -1
- package/dist/client/assets/classDiagram-v2-Q7XG4LA2-C5Kg1XOD.js +0 -1
- package/dist/client/assets/index-H6C-f2Vp.css +0 -32
- package/dist/client/assets/stateDiagram-v2-BHNVJYJU-Ca2U11af.js +0 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import {
|
|
3
|
+
formatGitFailure,
|
|
4
|
+
getDiffFile,
|
|
5
|
+
makeTempDir,
|
|
6
|
+
readTextFileOrThrow,
|
|
7
|
+
rmPathRecursive,
|
|
8
|
+
runGit,
|
|
9
|
+
statOrNull,
|
|
10
|
+
writeTextFile,
|
|
11
|
+
} from "./diff-store-io.adapter"
|
|
12
|
+
import {
|
|
13
|
+
countTextLines,
|
|
14
|
+
getContentDigest,
|
|
15
|
+
parseNumstatValue,
|
|
16
|
+
parseStatusPaths,
|
|
17
|
+
} from "./diff-store-parse"
|
|
18
|
+
import type { DirtyPathEntry } from "./diff-store-parse"
|
|
19
|
+
import { inferProjectFileContentType } from "./uploads"
|
|
20
|
+
import type { ChatDiffFile } from "../shared/types"
|
|
21
|
+
|
|
22
|
+
export type { DirtyPathEntry }
|
|
23
|
+
|
|
24
|
+
export async function listDirtyPaths(repoRoot: string): Promise<DirtyPathEntry[]> {
|
|
25
|
+
const status = await runGit(["status", "--short", "--untracked-files=all"], repoRoot)
|
|
26
|
+
if (status.exitCode !== 0) {
|
|
27
|
+
throw new Error(status.stderr.trim() || "Failed to read git status")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const paths = parseStatusPaths(status.stdout)
|
|
31
|
+
return paths
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export async function readWorktreeFile(repoRoot: string, relativePath: string): Promise<string | null> {
|
|
35
|
+
const absolutePath = path.join(repoRoot, relativePath)
|
|
36
|
+
const fileInfo = await statOrNull(absolutePath)
|
|
37
|
+
if (!fileInfo?.isFile()) {
|
|
38
|
+
return null
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return await readTextFileOrThrow(absolutePath)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function readBaseFile(repoRoot: string, baseCommit: string | null, relativePath: string): Promise<string | null> {
|
|
45
|
+
if (!baseCommit) {
|
|
46
|
+
return null
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const result = await runGit(["show", `${baseCommit}:${relativePath}`], repoRoot)
|
|
50
|
+
if (result.exitCode !== 0) {
|
|
51
|
+
return null
|
|
52
|
+
}
|
|
53
|
+
return result.stdout
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function createPatch(beforePathLabel: string, afterPathLabel: string, beforeText: string | null, afterText: string | null): Promise<string> {
|
|
57
|
+
const tempDir = await makeTempDir("kanna-diff-")
|
|
58
|
+
const beforePath = path.join(tempDir, "before")
|
|
59
|
+
const afterPath = path.join(tempDir, "after")
|
|
60
|
+
|
|
61
|
+
try {
|
|
62
|
+
await writeTextFile(beforePath, beforeText ?? "")
|
|
63
|
+
await writeTextFile(afterPath, afterText ?? "")
|
|
64
|
+
|
|
65
|
+
const result = await runGit(
|
|
66
|
+
[
|
|
67
|
+
"diff",
|
|
68
|
+
"--no-index",
|
|
69
|
+
"--no-ext-diff",
|
|
70
|
+
"--text",
|
|
71
|
+
"--unified=3",
|
|
72
|
+
"--src-prefix=a/",
|
|
73
|
+
"--dst-prefix=b/",
|
|
74
|
+
"before",
|
|
75
|
+
"after",
|
|
76
|
+
],
|
|
77
|
+
tempDir
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if (result.exitCode !== 0 && result.exitCode !== 1) {
|
|
81
|
+
throw new Error(result.stderr.trim() || `Failed to build patch for ${afterPathLabel}`)
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return result.stdout
|
|
85
|
+
.replace("diff --git a/before b/after", `diff --git a/${beforePathLabel} b/${afterPathLabel}`)
|
|
86
|
+
.replace("--- a/before", `--- a/${beforePathLabel}`)
|
|
87
|
+
.replace("+++ b/after", `+++ b/${afterPathLabel}`)
|
|
88
|
+
} finally {
|
|
89
|
+
await rmPathRecursive(tempDir)
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export async function getTrackedDiffStats(repoRoot: string, baseCommit: string | null): Promise<Map<string, { additions: number; deletions: number }>> {
|
|
94
|
+
const statsByPath = new Map<string, { additions: number; deletions: number }>()
|
|
95
|
+
if (!baseCommit) {
|
|
96
|
+
return statsByPath
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const result = await runGit(["diff", "--numstat", "-z", "-M", baseCommit], repoRoot)
|
|
100
|
+
if (result.exitCode !== 0) {
|
|
101
|
+
throw new Error(result.stderr.trim() || "Failed to read git diff stats")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const NULL_BYTE = "\u0000"
|
|
105
|
+
const tokens = result.stdout.split(NULL_BYTE)
|
|
106
|
+
for (let index = 0; index < tokens.length;) {
|
|
107
|
+
const header = tokens[index++] ?? ""
|
|
108
|
+
if (!header) continue
|
|
109
|
+
|
|
110
|
+
const [additionsValue, deletionsValue, pathValue = ""] = header.split("\t")
|
|
111
|
+
if (typeof additionsValue !== "string" || typeof deletionsValue !== "string") continue
|
|
112
|
+
|
|
113
|
+
if (pathValue) {
|
|
114
|
+
statsByPath.set(pathValue, {
|
|
115
|
+
additions: parseNumstatValue(additionsValue),
|
|
116
|
+
deletions: parseNumstatValue(deletionsValue),
|
|
117
|
+
})
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
index += 1
|
|
122
|
+
const nextPath = tokens[index++] ?? ""
|
|
123
|
+
if (!nextPath) continue
|
|
124
|
+
statsByPath.set(nextPath, {
|
|
125
|
+
additions: parseNumstatValue(additionsValue),
|
|
126
|
+
deletions: parseNumstatValue(deletionsValue),
|
|
127
|
+
})
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
return statsByPath
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export async function computeCurrentFiles(repoRoot: string, baseCommit: string | null): Promise<ChatDiffFile[]> {
|
|
134
|
+
const currentDirtyPaths = await listDirtyPaths(repoRoot)
|
|
135
|
+
const trackedStatsByPath = await getTrackedDiffStats(repoRoot, baseCommit)
|
|
136
|
+
const files: ChatDiffFile[] = []
|
|
137
|
+
|
|
138
|
+
for (const entry of currentDirtyPaths) {
|
|
139
|
+
const relativePath = entry.path
|
|
140
|
+
const beforePath = entry.previousPath ?? relativePath
|
|
141
|
+
const beforeText = await readBaseFile(repoRoot, baseCommit, beforePath)
|
|
142
|
+
const afterText = await readWorktreeFile(repoRoot, relativePath)
|
|
143
|
+
const absolutePath = path.join(repoRoot, relativePath)
|
|
144
|
+
const fileInfo = await statOrNull(absolutePath)
|
|
145
|
+
const file = fileInfo?.isFile() ? getDiffFile(absolutePath) : null
|
|
146
|
+
const mimeType = file ? inferProjectFileContentType(relativePath, file.type) : undefined
|
|
147
|
+
const size = fileInfo?.isFile() ? fileInfo.size : undefined
|
|
148
|
+
|
|
149
|
+
if (beforeText === afterText && entry.changeType !== "renamed") {
|
|
150
|
+
continue
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const trackedStats = trackedStatsByPath.get(relativePath)
|
|
154
|
+
const additions = trackedStats?.additions ?? countTextLines(afterText)
|
|
155
|
+
const deletions = trackedStats?.deletions ?? 0
|
|
156
|
+
files.push({
|
|
157
|
+
path: relativePath,
|
|
158
|
+
changeType: entry.changeType,
|
|
159
|
+
isUntracked: entry.isUntracked,
|
|
160
|
+
additions,
|
|
161
|
+
deletions,
|
|
162
|
+
patchDigest: getContentDigest({
|
|
163
|
+
changeType: entry.changeType,
|
|
164
|
+
beforePath,
|
|
165
|
+
afterPath: relativePath,
|
|
166
|
+
beforeText,
|
|
167
|
+
afterText,
|
|
168
|
+
}),
|
|
169
|
+
mimeType,
|
|
170
|
+
size,
|
|
171
|
+
})
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return files
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export async function findDirtyPath(repoRoot: string, relativePath: string): Promise<DirtyPathEntry | undefined> {
|
|
178
|
+
const dirtyPaths = await listDirtyPaths(repoRoot)
|
|
179
|
+
return dirtyPaths.find((entry) => entry.path === relativePath)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function discardAddedPath(repoRoot: string, repoHasHead: boolean, relativePath: string): Promise<void> {
|
|
183
|
+
if (repoHasHead) {
|
|
184
|
+
const resetResult = await runGit(["reset", "--quiet", "HEAD", "--", relativePath], repoRoot)
|
|
185
|
+
if (resetResult.exitCode !== 0) {
|
|
186
|
+
throw new Error(formatGitFailure(resetResult) || "Failed to unstage added file")
|
|
187
|
+
}
|
|
188
|
+
} else {
|
|
189
|
+
const rmCachedResult = await runGit(["rm", "--cached", "--force", "--", relativePath], repoRoot)
|
|
190
|
+
if (rmCachedResult.exitCode !== 0) {
|
|
191
|
+
throw new Error(formatGitFailure(rmCachedResult) || "Failed to unstage added file")
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export async function discardRenamedPath(repoRoot: string, entry: DirtyPathEntry): Promise<void> {
|
|
197
|
+
if (!entry.previousPath) {
|
|
198
|
+
throw new Error(`Missing previous path for renamed file: ${entry.path}`)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const resetResult = await runGit(["reset", "--quiet", "HEAD", "--", entry.path], repoRoot)
|
|
202
|
+
if (resetResult.exitCode !== 0) {
|
|
203
|
+
throw new Error(formatGitFailure(resetResult) || "Failed to unstage renamed file")
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const restoreResult = await runGit(["restore", "--staged", "--worktree", "--source=HEAD", "--", entry.previousPath], repoRoot)
|
|
207
|
+
if (restoreResult.exitCode !== 0) {
|
|
208
|
+
throw new Error(formatGitFailure(restoreResult) || "Failed to restore renamed file")
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
await rmPathRecursive(path.join(repoRoot, entry.path))
|
|
212
|
+
}
|