@xbzbing/dsh-git-panel 0.1.1 → 0.3.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.
@@ -19,7 +19,14 @@ export declare function parseGraphLog(stdout: string): GraphCommit[];
19
19
  export declare function parseRefs(decoration: string): GitRef[];
20
20
  /** Parse `git for-each-ref` local/remote branch lines: `name\0shortHash\0track`. */
21
21
  export declare function parseBranches(stdout: string): GitBranch[];
22
- /** Parse `git show --name-status -z` file lines into stats. */
22
+ /** Parse `git for-each-ref` tag lines: `name\0shortHash` per line. */
23
+ export declare function parseTags(stdout: string): GitBranch[];
24
+ /**
25
+ * Parse `git show --name-status -z` into stats with an explicit state machine:
26
+ * read a status token, then consume exactly the paths it owns (2 for R/C, 1
27
+ * otherwise). A malformed token stops the scan rather than silently shifting
28
+ * every later field, so one bad entry can't corrupt the whole list.
29
+ */
23
30
  export declare function parseNameStatus(stdout: string): GitFileStat[];
24
31
  /** Sum `git diff --numstat` output: { insertions, deletions }. Binary rows ("-") skipped. */
25
32
  export declare function sumNumstat(stdout: string): {
@@ -3,6 +3,8 @@
3
3
  * The client half (src/client/rpc.ts) reuses these types directly, so the
4
4
  * wire contract has a single definition and cannot drift.
5
5
  */
6
+ /** Diff layout: `unified` = single inline column, `split` = side-by-side. */
7
+ export type DiffViewMode = 'unified' | 'split';
6
8
  /** Wire request: the browser sends only session identity, never a path. */
7
9
  export interface GitSnapshotRequest {
8
10
  readonly sessionId: string;
@@ -15,9 +17,6 @@ export type GitSnapshotResult = {
15
17
  readonly error: GitFailure;
16
18
  };
17
19
  export type GitFailure = {
18
- readonly code: 'session-not-found';
19
- readonly sessionId: string;
20
- } | {
21
20
  readonly code: 'cwd-unavailable';
22
21
  readonly sessionId: string;
23
22
  } | {
@@ -29,6 +28,8 @@ export type GitFailure = {
29
28
  readonly detail: string;
30
29
  } | {
31
30
  readonly code: 'timeout';
31
+ } | {
32
+ readonly code: 'cancelled';
32
33
  };
33
34
  /** Immutable snapshot of one repository's status at `checkedAt`. */
34
35
  export interface GitSnapshot {
@@ -49,12 +50,16 @@ export interface GitSnapshot {
49
50
  readonly behind: number;
50
51
  readonly lastCommit: GitCommit | null;
51
52
  readonly changes: readonly GitChange[];
53
+ /** Working-tree statistics for the changes-page header (single source). */
54
+ readonly stats: WorktreeStats;
52
55
  /** True when the change list was capped at maxChanges. */
53
56
  readonly truncated: boolean;
54
57
  /** Polling interval the client should use after this snapshot (0 = off). */
55
58
  readonly refreshIntervalMs: number;
56
59
  /** Whether the input-bar git marker pill should render (user preference). */
57
60
  readonly showInputPill: boolean;
61
+ /** Default diff layout the views open with (user preference). */
62
+ readonly defaultDiffView: DiffViewMode;
58
63
  /** Epoch millis of the snapshot. */
59
64
  readonly checkedAt: number;
60
65
  }
@@ -114,7 +119,7 @@ export type GitAction = {
114
119
  } | {
115
120
  readonly kind: 'fetch';
116
121
  };
117
- export type GitErrorCode = 'session-not-found' | 'cwd-unavailable' | 'not-a-git-repo' | 'git-unavailable' | 'invalid-path' | 'invalid-name' | 'git-error' | 'timeout' | 'empty-message' | 'local-changes-block';
122
+ export type GitErrorCode = 'cwd-unavailable' | 'not-a-git-repo' | 'git-unavailable' | 'invalid-path' | 'invalid-name' | 'git-error' | 'timeout' | 'cancelled' | 'empty-message' | 'local-changes-block';
118
123
  export type GitActionResult = {
119
124
  readonly ok: true;
120
125
  readonly snapshot: GitSnapshot;
@@ -153,6 +158,19 @@ export type GitQuery = {
153
158
  readonly base: 'commit';
154
159
  readonly commit: string;
155
160
  readonly context?: number;
161
+ } | {
162
+ readonly kind: 'file-lines';
163
+ readonly path: string;
164
+ readonly base: 'worktree' | 'staged';
165
+ readonly start: number;
166
+ readonly end: number;
167
+ } | {
168
+ readonly kind: 'file-lines';
169
+ readonly path: string;
170
+ readonly base: 'commit';
171
+ readonly commit: string;
172
+ readonly start: number;
173
+ readonly end: number;
156
174
  } | {
157
175
  readonly kind: 'image-diff';
158
176
  readonly path: string;
@@ -162,6 +180,12 @@ export type GitQuery = {
162
180
  readonly path: string;
163
181
  readonly base: 'commit';
164
182
  readonly commit: string;
183
+ } | {
184
+ readonly kind: 'dir-list';
185
+ readonly path: string;
186
+ } | {
187
+ readonly kind: 'file-content';
188
+ readonly path: string;
165
189
  } | {
166
190
  readonly kind: 'show';
167
191
  readonly ref: string;
@@ -176,6 +200,15 @@ export type GitQuery = {
176
200
  } | {
177
201
  readonly kind: 'worktree-stats';
178
202
  };
203
+ /** One entry in a `dir-list` result. */
204
+ export interface DirEntry {
205
+ readonly name: string;
206
+ readonly dir: boolean;
207
+ /** File byte size; absent for directories. */
208
+ readonly size?: number;
209
+ /** True when Git excludes an untracked item; absent outside a repository. */
210
+ readonly ignored?: boolean;
211
+ }
179
212
  /** One commit's changed-file line (from --name-status). */
180
213
  export interface GitFileStat {
181
214
  readonly path: string;
@@ -211,6 +244,12 @@ export type GitQueryResult = {
211
244
  readonly kind: 'diff';
212
245
  readonly path: string;
213
246
  readonly text: string;
247
+ } | {
248
+ readonly kind: 'file-lines';
249
+ readonly path: string;
250
+ readonly start: number;
251
+ readonly lines: readonly string[];
252
+ readonly eof: boolean;
214
253
  } | {
215
254
  /**
216
255
  * Old/new images for a binary image diff, as data URLs. The sides mirror
@@ -252,6 +291,23 @@ export type GitQueryResult = {
252
291
  } | {
253
292
  readonly kind: 'worktree-stats';
254
293
  readonly stats: WorktreeStats;
294
+ } | {
295
+ readonly kind: 'dir-list';
296
+ readonly path: string;
297
+ readonly entries: readonly DirEntry[];
298
+ readonly truncated: boolean;
299
+ } | {
300
+ readonly kind: 'file-content';
301
+ readonly path: string;
302
+ readonly variant: 'text' | 'image' | 'binary';
303
+ /** text variant: the file's full UTF-8 content. */
304
+ readonly content?: string;
305
+ /** text variant: total line count. */
306
+ readonly lines?: number;
307
+ /** image variant: a `data:<mime>;base64,…` URL. */
308
+ readonly dataUrl?: string;
309
+ /** The file exceeded the byte cap, so no content is returned. */
310
+ readonly tooLarge?: true;
255
311
  };
256
312
  export type GitQueryResponse = {
257
313
  readonly ok: true;
@@ -0,0 +1,10 @@
1
+ /** A repository-relative path is safe when it stays inside the work tree. */
2
+ export declare function isSafePath(path: string): boolean;
3
+ /**
4
+ * A ref (branch / tag / commit-ish) is safe as a bare argv element: no leading
5
+ * `-` (would be parsed as a git option — the `--output=` file-write vector),
6
+ * no whitespace/control chars, no glob or rev-range metacharacters.
7
+ */
8
+ export declare function isSafeRev(input: string): boolean;
9
+ /** A branch name for `git checkout`: the ref rules plus no leading slash. */
10
+ export declare function isSafeBranchName(name: string): boolean;
@@ -21,9 +21,10 @@ export declare function parseRepository(repository: unknown): {
21
21
  repo: string;
22
22
  } | undefined;
23
23
  /**
24
- * Compare dotted numeric versions with basic prerelease handling; returns 1
25
- * when a > b, -1 when a < b, 0 when equal. A release outranks a prerelease
26
- * sharing the same core (e.g. 0.2.0 > 0.2.0-beta.1).
24
+ * Compare dotted versions with prerelease handling; returns 1 when a > b, -1
25
+ * when a < b, 0 when equal. A release outranks a prerelease sharing the same
26
+ * core (0.2.0 > 0.2.0-beta.1); prerelease identifiers compare dot-segment by
27
+ * segment, numeric parts numerically (beta.2 > beta.1, 0.2.0-rc.10 > rc.2).
27
28
  */
28
29
  export declare function compareVersions(a: string, b: string): number;
29
30
  /** Local-only view: current version + repository URL, no network access. */
@@ -32,7 +33,8 @@ export declare function readVersionInfo(options?: {
32
33
  }): Promise<VersionInfo>;
33
34
  /**
34
35
  * Query the GitHub releases API for the latest tag and compare it to the
35
- * bundled version. Failures are reported through `error` instead of throwing.
36
+ * bundled version. Failures are reported through `error` instead of throwing;
37
+ * a 5s timeout bounds the call and a 10-minute memo bounds the request rate.
36
38
  */
37
39
  export declare function checkLatestVersion(options?: {
38
40
  manifestPath?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xbzbing/dsh-git-panel",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "DeepSeek Harness (dsh) plugin: an IDE-style Git panel in the Web GUI — branch/history overview, uncommitted changes with commit & amend, diff stats, and a zsh-style branch marker in the input bar.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -44,8 +44,7 @@
44
44
  "test:unit": "node build.mjs && node --test --test-force-exit test/unit/*.test.mjs",
45
45
  "test:e2e": "node build.mjs && node test/e2e/setup.mjs && node test/e2e/run.mjs && node test/e2e/run2.mjs",
46
46
  "test": "npm run test:unit && npm run test:e2e",
47
- "check": "npm run typecheck && npm run test",
48
- "prepare": "node build.mjs"
47
+ "check": "npm run typecheck && npm run test && git diff --exit-code -- lib/"
49
48
  },
50
49
  "dsh": {
51
50
  "bundle": {
@@ -56,7 +55,8 @@
56
55
  "inject": [
57
56
  "@deepseek-ai/dsh-client-connection",
58
57
  "@deepseek-ai/dsh-client-locale",
59
- "@deepseek-ai/dsh-client-ui-conversation"
58
+ "@deepseek-ai/dsh-client-ui-conversation",
59
+ "@deepseek-ai/dsh-client-ui-primitives"
60
60
  ]
61
61
  }
62
62
  },
@@ -76,9 +76,6 @@
76
76
  "@deepseek-ai/dsh-typert-protocol": ">=0.1.2-rc.1",
77
77
  "@deepseek-ai/schemastery": ">=3.18.4"
78
78
  },
79
- "dependencies": {
80
- "highlight.js": "11.11.1"
81
- },
82
79
  "devDependencies": {
83
80
  "@types/node": "22.10.5",
84
81
  "@types/react": "18.3.18",