@orion-agents/orion-code 0.3.14 → 0.3.17

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +286 -0
  2. package/README.md +6 -8
  3. package/README.zh-CN.md +4 -5
  4. package/dist/runtime/release-receipts.d.ts +15 -3
  5. package/dist/runtime/release-receipts.js +27 -1
  6. package/dist/services/session-storage.d.ts +9 -0
  7. package/dist/services/session-storage.js +27 -1
  8. package/dist/web/git-compare-service.d.ts +45 -0
  9. package/dist/web/git-compare-service.js +160 -0
  10. package/dist/web/git-diff-document.d.ts +83 -0
  11. package/dist/web/git-diff-document.js +214 -0
  12. package/dist/web/git-file-source.d.ts +25 -0
  13. package/dist/web/git-file-source.js +21 -0
  14. package/dist/web/git-history-service.d.ts +151 -0
  15. package/dist/web/git-history-service.js +610 -0
  16. package/dist/web/git-index-transaction.d.ts +45 -0
  17. package/dist/web/git-index-transaction.js +174 -0
  18. package/dist/web/git-patch-builder.d.ts +30 -0
  19. package/dist/web/git-patch-builder.js +134 -0
  20. package/dist/web/git-read-model-service.d.ts +338 -18
  21. package/dist/web/git-read-model-service.js +1029 -110
  22. package/dist/web/git-version-service.d.ts +71 -0
  23. package/dist/web/git-version-service.js +255 -0
  24. package/dist/web/native-directory-picker.d.ts +63 -0
  25. package/dist/web/native-directory-picker.js +169 -0
  26. package/dist/web/protocol.d.ts +51 -2
  27. package/dist/web/server.js +384 -8
  28. package/dist/web/workbench-controller.d.ts +126 -10
  29. package/dist/web/workbench-controller.js +383 -15
  30. package/dist/web/workspace-open-telemetry.d.ts +55 -0
  31. package/dist/web/workspace-open-telemetry.js +73 -0
  32. package/dist/web-client/assets/FilesPanel-BARQCmne.js +1 -0
  33. package/dist/web-client/assets/GitPanel-DjB9eSiJ.js +4 -0
  34. package/dist/web-client/assets/ReviewPanel-YhEGlp-G.js +5 -0
  35. package/dist/web-client/assets/{TerminalPanel-IkCttxgw.js → TerminalPanel-DnWh3Vp2.js} +1 -1
  36. package/dist/web-client/assets/index--hnGXXjj.css +1 -0
  37. package/dist/web-client/assets/index-Drja0_BT.js +20 -0
  38. package/dist/web-client/assets/useAutoNotice-DfQi4G1X.js +1 -0
  39. package/dist/web-client/favicon.svg +9 -0
  40. package/dist/web-client/index.html +3 -2
  41. package/npm-shrinkwrap.json +2 -2
  42. package/package.json +1 -1
  43. package/dist/web-client/assets/DiffViewer-BrHqudpK.js +0 -5
  44. package/dist/web-client/assets/FilesPanel-BcFY6L1a.js +0 -1
  45. package/dist/web-client/assets/GitPanel-B6E5IEXm.js +0 -1
  46. package/dist/web-client/assets/ResourceSplitLayout-fPYE9JKJ.js +0 -1
  47. package/dist/web-client/assets/ReviewPanel-5ecTVmhT.js +0 -1
  48. package/dist/web-client/assets/index-DgVNIqmE.js +0 -20
  49. package/dist/web-client/assets/index-R6E589Fc.css +0 -1
@@ -1,10 +1,33 @@
1
+ import { type GitDiffDocumentV2 } from './git-diff-document';
2
+ import { type GitCommitDetailV1, type GitCommitFilesV1, type GitBlameResultV1, type GitGraphPageV1, type GitFileHistoryPageV1, type GitHistoryPageV1, type GitHistoryQueryV1, type GitRefsV1 } from './git-history-service';
3
+ import { type GitCompareModeV1, type GitCompareResultV1 } from './git-compare-service';
4
+ import { type GitBlobResultV1, type GitConflictVersionsV1, type GitSubmoduleEntryV1 } from './git-version-service';
5
+ import { type GitWorktreeSourceV1, type WebGitFileSourceV1 } from './git-file-source';
6
+ export type { GitWorktreeSourceV1, WebGitFileSourceV1 } from './git-file-source';
7
+ /**
8
+ * v0.3.17 S1 — the comparison source a file entry belongs to.
9
+ *
10
+ * A path with an index change *and* a further worktree change (`MM`) is two
11
+ * distinct selectable objects, so the source is part of the file identity.
12
+ * Declared in `./git-file-source` and re-exported here for existing importers.
13
+ */
1
14
  export interface WebGitFileV1 {
2
15
  readonly fileId: string;
3
16
  readonly path: string;
17
+ readonly source: GitWorktreeSourceV1;
4
18
  readonly indexStatus: string;
5
19
  readonly worktreeStatus: string;
6
20
  readonly renamedFrom?: string;
7
21
  }
22
+ /** v0.3.17 S1 — real totals per group, independent of the loaded page. */
23
+ export interface WebGitStatusCountsV1 {
24
+ readonly total: number;
25
+ readonly conflicted: number;
26
+ readonly staged: number;
27
+ readonly unstaged: number;
28
+ readonly untracked: number;
29
+ readonly loaded: number;
30
+ }
8
31
  export interface WebGitStatusV1 {
9
32
  readonly isRepository: boolean;
10
33
  readonly repositoryRevision: string;
@@ -21,6 +44,7 @@ export interface WebGitStatusV1 {
21
44
  readonly untracked: readonly WebGitFileV1[];
22
45
  readonly conflicted: readonly WebGitFileV1[];
23
46
  readonly totalFiles: number;
47
+ readonly counts: WebGitStatusCountsV1;
24
48
  readonly truncated: boolean;
25
49
  readonly nextCursor: string | null;
26
50
  }
@@ -39,12 +63,27 @@ export interface WebGitLogPageV1 {
39
63
  export interface WebGitDiffPageV1 {
40
64
  readonly fileId: string;
41
65
  readonly path: string;
66
+ /** Which comparison target this page was rendered against. */
67
+ readonly source: GitWorktreeSourceV1;
42
68
  readonly repositoryRevision: string;
43
69
  readonly binary: boolean;
44
70
  readonly lines: readonly string[];
45
71
  readonly nextCursor: string | null;
46
72
  readonly truncated: boolean;
47
73
  }
74
+ /** v0.3.17 S1 — a Git file token resolves to a source-scoped (source, path) pair. */
75
+ export interface ResolvedGitToken {
76
+ readonly source: GitWorktreeSourceV1;
77
+ readonly path: string;
78
+ }
79
+ /** v0.3.17 S1 — bounded status query accepted by `status()`. */
80
+ export interface GitStatusQueryV1 {
81
+ readonly cursor?: string;
82
+ readonly pageSize?: number;
83
+ /** Only a working-tree group can be filtered on; `commit` is not a status group. */
84
+ readonly group?: GitWorktreeSourceV1;
85
+ readonly query?: string;
86
+ }
48
87
  export interface WebGitPerformanceCountersV1 {
49
88
  readonly processCount: number;
50
89
  readonly bytesRead: number;
@@ -54,16 +93,22 @@ export interface WebGitPerformanceCountersV1 {
54
93
  export declare class GitReadModelServiceV1 {
55
94
  private readonly workspace;
56
95
  private readonly secret;
57
- private readonly pathById;
58
- private readonly idByPath;
96
+ /**
97
+ * v0.3.17 S1 — tokens are keyed by (source, path), not by path alone. A file that is
98
+ * both staged and modified in the worktree is two different selectable objects, so a
99
+ * path-only key silently conflated the two comparison sources.
100
+ */
101
+ private readonly targetById;
102
+ private readonly idByKey;
59
103
  private repositoryRoot?;
60
104
  private readonly performance;
61
- constructor(workspace: string);
105
+ /** Overridable so the timeout-recovery path can be exercised deterministically. */
106
+ private readonly commitTimeoutMs;
107
+ constructor(workspace: string, options?: {
108
+ readonly commitTimeoutMs?: number;
109
+ });
62
110
  performanceCounters(): WebGitPerformanceCountersV1;
63
- status(input?: {
64
- readonly cursor?: string;
65
- readonly pageSize?: number;
66
- }): Promise<WebGitStatusV1>;
111
+ status(input?: GitStatusQueryV1): Promise<WebGitStatusV1>;
67
112
  log(input?: {
68
113
  readonly cursor?: string;
69
114
  readonly pageSize?: number;
@@ -73,27 +118,302 @@ export declare class GitReadModelServiceV1 {
73
118
  readonly cursor?: string;
74
119
  readonly lineLimit?: number;
75
120
  readonly byteLimit?: number;
121
+ /** v0.3.17 S5 — `git diff --ignore-all-space`. Bound into the cursor so a page can
122
+ * never be continued under a different whitespace setting. */
123
+ readonly ignoreWhitespace?: boolean;
124
+ /** v0.3.17 S5 — `--word-diff=plain`. Also bound into the cursor: the rendered text is
125
+ * different, so a page must not be continued across a mode change. */
126
+ readonly wordDiff?: boolean;
76
127
  }): Promise<WebGitDiffPageV1>;
128
+ /**
129
+ * v0.3.17 S2 — the structured form of the same comparison. It reuses `diff()` verbatim,
130
+ * so the hardened read path, byte/line budget and pagination stay in one place; only the
131
+ * projection changes.
132
+ */
133
+ diffDocument(input: {
134
+ readonly fileId: string;
135
+ readonly cursor?: string;
136
+ readonly lineLimit?: number;
137
+ readonly byteLimit?: number;
138
+ readonly ignoreWhitespace?: boolean;
139
+ readonly wordDiff?: boolean;
140
+ }): Promise<GitDiffDocumentV2>;
141
+ /**
142
+ * v0.3.17 S4 — history reading.
143
+ *
144
+ * Delegated to a separate module (plan §8.2) that owns metadata about immutable objects,
145
+ * while the bounded diff stream stays here. None of these methods touch the working tree or
146
+ * the index — the S4 exit evidence is "history browsing without workspace writes".
147
+ */
148
+ private historyReaderInstance?;
149
+ private historyReader;
150
+ private compareReaderInstance?;
151
+ private compareReader;
152
+ /**
153
+ * v0.3.17 S5 — branch/version comparison. Read-only.
154
+ *
155
+ * The resolved OIDs are part of the result on purpose: the UI freezes the opened result
156
+ * against them, so a ref that moves afterwards produces a "there is an update" hint
157
+ * instead of silently comparing against a different tree.
158
+ */
159
+ compare(input: {
160
+ readonly baseRef: string;
161
+ readonly headRef: string;
162
+ readonly mode: GitCompareModeV1;
163
+ }): Promise<GitCompareResultV1>;
164
+ /** Resolves a pair of refs without computing a comparison (used to detect ref movement). */
165
+ resolveComparePair(baseRef: string, headRef: string): Promise<{
166
+ readonly baseOid: string;
167
+ readonly headOid: string;
168
+ }>;
169
+ /**
170
+ * v0.3.17 S5 — the diff one file shows between two arbitrary commits.
171
+ *
172
+ * Same bounded stream as every other diff; the only new thing is that the base is a
173
+ * caller-supplied resolved OID instead of a parent. The cursor margin binds the page to
174
+ * this exact base/head/path triple, so a different comparison cannot continue it.
175
+ */
176
+ compareFileDiffDocument(input: {
177
+ readonly baseOid: string;
178
+ readonly headOid: string;
179
+ readonly path: string;
180
+ readonly cursor?: string;
181
+ readonly lineLimit?: number;
182
+ readonly byteLimit?: number;
183
+ }): Promise<GitDiffDocumentV2>;
184
+ private versionReaderInstance?;
185
+ private versionReader;
186
+ /**
187
+ * v0.3.17 S5 — base / ours / theirs / worktree for a conflicted file.
188
+ *
189
+ * Read from index stages 1/2/3 rather than assembled from two diffs: a modify/delete
190
+ * conflict genuinely has no base, and pretending otherwise is what plan G6 forbids.
191
+ */
192
+ conflictVersions(path: string): Promise<GitConflictVersionsV1>;
193
+ /** Reads one file at a revision — including a file that no longer exists locally. */
194
+ fileBlob(input: {
195
+ readonly path: string;
196
+ readonly rev: string;
197
+ }): Promise<GitBlobResultV1>;
198
+ /** Recorded gitlink SHAs only; submodules are never traversed (plan G6). */
199
+ submodules(): Promise<readonly GitSubmoduleEntryV1[]>;
200
+ refs(): Promise<GitRefsV1>;
201
+ history(query: GitHistoryQueryV1): Promise<GitHistoryPageV1>;
202
+ commitDetail(oid: string, parentIndex?: number): Promise<GitCommitDetailV1>;
203
+ commitFiles(oid: string, parentIndex?: number): Promise<GitCommitFilesV1>;
204
+ graph(input?: {
205
+ readonly limit?: number;
206
+ }): Promise<GitGraphPageV1>;
207
+ blame(input: {
208
+ readonly path: string;
209
+ readonly rev?: string;
210
+ readonly limit?: number;
211
+ }): Promise<GitBlameResultV1>;
212
+ fileHistory(input: {
213
+ readonly path: string;
214
+ readonly rev?: string;
215
+ readonly limit?: number;
216
+ }): Promise<GitFileHistoryPageV1>;
217
+ /**
218
+ * v0.3.17 S4 — the diff a commit introduced to one file.
219
+ *
220
+ * Rebuilds the comparison from the commit's real base (first parent, a chosen parent, or the
221
+ * empty tree for a root commit) and reuses `streamDiffPage`, so the byte/line budget,
222
+ * pagination and `--no-ext-diff`/`--no-textconv` hardening are the same code the working-tree
223
+ * diff uses. There is no second diff implementation to keep in sync.
224
+ */
225
+ commitDiffDocument(input: {
226
+ readonly oid: string;
227
+ readonly path: string;
228
+ readonly parentIndex?: number;
229
+ readonly cursor?: string;
230
+ readonly lineLimit?: number;
231
+ readonly byteLimit?: number;
232
+ }): Promise<GitDiffDocumentV2>;
77
233
  private capture;
78
234
  private projectFile;
79
- private rememberPath;
235
+ private rememberTarget;
236
+ /**
237
+ * v0.3.17 S1 — the single place a Git file token becomes a path. Git mutations resolve
238
+ * tokens here instead of going through FileReadService, whose token space is unrelated.
239
+ */
240
+ resolveTarget(fileId: string): ResolvedGitToken;
241
+ /**
242
+ * v0.3.17 S1 — resolve Git file tokens for a mutation and enforce the source each
243
+ * action may write. This replaces FileReadService token lookup, whose token space is
244
+ * unrelated to Git and silently rejected every real Git list token.
245
+ */
246
+ resolveMutationPaths(action: 'stage' | 'unstage', fileIds: readonly string[]): readonly string[];
80
247
  /** v0.3.12 S3 — guarded stage: paths are host-resolved file ids only. */
81
- stagePaths(paths: readonly string[]): Promise<{
82
- readonly repositoryRevision: string;
83
- }>;
84
- unstagePaths(paths: readonly string[]): Promise<{
85
- readonly repositoryRevision: string;
86
- }>;
87
- commit(message: string): Promise<{
88
- readonly repositoryRevision: string;
89
- readonly commitSha: string;
90
- }>;
248
+ stagePaths(paths: readonly string[]): Promise<GitMutationResultV1>;
249
+ /**
250
+ * v0.3.17 S3 — prove the index entry for each path really equals what `git add` should
251
+ * have produced.
252
+ *
253
+ * Checking "the path is present in the index" is not enough: the path was usually already
254
+ * there, so a silent no-op would pass. `hash-object --path` applies exactly the filters and
255
+ * attributes git itself would, so comparing the two oids is a precise postcondition — and
256
+ * it is what turns a stat-cache no-op into a loud failure instead of a lost edit.
257
+ */
258
+ private assertIndexMatchesWorktree;
259
+ unstagePaths(paths: readonly string[]): Promise<GitMutationResultV1>;
260
+ /**
261
+ * v0.3.17 S3 — apply a hunk or line selection to the index only (plan §7.6/§7.8).
262
+ *
263
+ * The document is re-read on the Host, the patch is rebuilt from it, and `--check` runs
264
+ * before the write. The browser only ever sends ids, never patch text.
265
+ */
266
+ applySelection(input: {
267
+ readonly fileId: string;
268
+ readonly hunkIds?: readonly string[];
269
+ readonly lineIds?: readonly string[];
270
+ }): Promise<GitMutationResultV1>;
271
+ /**
272
+ * Applies a Host-rebuilt patch to the index only (plan §7.6). The patch never comes from
273
+ * the browser: it is rebuilt from the reviewed document, and `--check` runs first so a
274
+ * patch that cannot apply is rejected before anything is written into the private index.
275
+ */
276
+ applyIndexPatch(patch: string, options?: {
277
+ readonly reverse?: boolean;
278
+ }): Promise<GitMutationResultV1>;
279
+ private readTreeEmpty;
280
+ /** `ls-files --stage -z` parsed into path → blob oid, honouring a private index env. */
281
+ private indexEntries;
282
+ /** Resolves root, git dir and the real index path (worktree-aware). */
283
+ private resolveIndexPaths;
284
+ private mutationResult;
285
+ /**
286
+ * v0.3.17 S3 — what a commit would actually include.
287
+ *
288
+ * This is deliberately independent of the change-list filter: plan G3 requires the form to
289
+ * show the real index, not the currently filtered view, so the reader can never commit a
290
+ * subset they did not intend.
291
+ */
292
+ commitPreview(): Promise<GitCommitPreviewV1>;
293
+ /** Bounded `--cached --numstat` read; used only for the summary line of the form. */
294
+ private stagedNumstat;
295
+ /**
296
+ * v0.3.17 S3 — commit against a frozen expectation of HEAD and the index tree (plan §7.9).
297
+ *
298
+ * Differences from the previous implementation, all deliberate:
299
+ * - a **separate runner** that leaves the repository's own hooks and signing
300
+ * configuration in place, instead of the read hardening that disables hooks;
301
+ * - the message may contain real newlines (summary + body) and is rejected only for
302
+ * control characters that would corrupt a commit object;
303
+ * - the index and HEAD are captured before and re-read after, and any change that is not
304
+ * ours is reported rather than rolled back;
305
+ * - a timeout is not treated as "not committed": the outcome is queried by requestId.
306
+ */
307
+ commit(input: {
308
+ readonly summary: string;
309
+ readonly body?: string;
310
+ readonly expectedRepositoryRevision: string;
311
+ readonly requestId: string;
312
+ }): Promise<GitCommitOutcomeV1>;
313
+ /**
314
+ * A commit is confirmed by HEAD having moved to a *new* commit, never by exit code alone.
315
+ * This is what makes the timeout path safe: we ask Git what actually happened.
316
+ */
317
+ private recoverCommit;
318
+ /** Identity and hook configuration the commit will actually run under (plan §7.9). */
319
+ private describeCommitConfiguration;
91
320
  private mutate;
92
321
  private requireRepositoryRoot;
322
+ /**
323
+ * v0.3.17 S1 — a mutation reports the same state digest `status()` reports. Returning
324
+ * `rev-parse HEAD` was a different value space AND did not move on stage/unstage, so it
325
+ * could never express "the index changed".
326
+ *
327
+ * NOTE: this is post-write verification, not an atomic compare-and-swap. The real
328
+ * check-write window is S3 scope (plan §7.7); until then nothing may claim atomicity.
329
+ */
93
330
  private revisionAfterMutation;
331
+ /**
332
+ * v0.3.17 S3 — one exec path, three explicit profiles.
333
+ *
334
+ * `read` keeps every hardening from v0.3.12. `index` relaxes only what staging must
335
+ * resolve (user config for filters/CRLF) while keeping hooks disabled. `commit` is the
336
+ * deliberate exception from plan §7.9: it lets the repository's own hooks and signing
337
+ * configuration run, and gets its own bounded budget instead of the 5s read budget.
338
+ * The profiles are separate on purpose — enabling commit hooks must not relax reads.
339
+ *
340
+ * Implemented with `spawn` rather than `execFile` for two reasons found the hard way:
341
+ * 1. the async `execFile`/`exec` `input` option is silently ignored, so `git apply -`
342
+ * blocked forever waiting for stdin that never closed;
343
+ * 2. a timeout must kill the whole process group, otherwise a slow `pre-commit` hook
344
+ * survives as an orphan while we report failure.
345
+ */
94
346
  private runGit;
347
+ /**
348
+ * v0.3.17 S5 — the byte-level primitive behind `runGit`.
349
+ *
350
+ * Historical file content may not be valid UTF-8, so blob reads must not round-trip
351
+ * through a string. Everything else (hardening prefix, profile, byte budget, timeout,
352
+ * process-group kill) is shared, which is why this is the same body and not a copy.
353
+ */
354
+ private runGitBytes;
95
355
  private tryGit;
96
356
  private encodeCursor;
97
357
  private decodeCursor;
98
358
  }
359
+ /** v0.3.17 S3 — every index mutation answers with the state version it produced. */
360
+ export interface GitMutationResultV1 {
361
+ readonly repositoryRevision: string;
362
+ }
363
+ /**
364
+ * v0.3.17 S3 — the identity, signing and hook configuration a commit will actually run
365
+ * under. Shown in the form so a failure is explainable instead of mysterious (plan §7.9).
366
+ */
367
+ export interface GitCommitIdentityV1 {
368
+ readonly name: string | null;
369
+ readonly email: string | null;
370
+ readonly signingKey: string | null;
371
+ readonly signingEnabled: boolean;
372
+ readonly hooksDir: string | null;
373
+ readonly hooksPresent: boolean;
374
+ }
375
+ export interface GitCommitOutcomeV1 {
376
+ readonly status: 'committed';
377
+ readonly commitSha: string;
378
+ readonly repositoryRevision: string;
379
+ readonly durationMs: number;
380
+ readonly identity: GitCommitIdentityV1;
381
+ /** Set when the process reported failure but Git had in fact committed. */
382
+ readonly warning?: string;
383
+ }
384
+ /** One entry of the actual index that a commit would include. */
385
+ export interface GitIndexEntryV1 {
386
+ readonly path: string;
387
+ readonly source: WebGitFileSourceV1;
388
+ readonly status: string;
389
+ }
390
+ export interface GitCommitPreviewV1 {
391
+ readonly repositoryRevision: string;
392
+ readonly branch: string | null;
393
+ readonly detached: boolean;
394
+ readonly entries: readonly GitIndexEntryV1[];
395
+ readonly additions: number;
396
+ readonly deletions: number;
397
+ readonly filesChanged: number;
398
+ readonly identity: GitCommitIdentityV1;
399
+ readonly canCommit: boolean;
400
+ /** Why the form is disabled, when it is. */
401
+ readonly blockedReason: string | null;
402
+ }
403
+ /**
404
+ * v0.3.17 S3 — summary plus optional body.
405
+ *
406
+ * The previous validator rejected any newline, which made a real commit body impossible
407
+ * (plan G3 asks for exactly that fix). What must still be rejected are characters that would
408
+ * corrupt or truncate the commit object: NUL and other C0 controls, except the newlines and
409
+ * tabs a message legitimately contains.
410
+ */
411
+ export declare function normalizeCommitMessage(summary: string, body?: string): string;
412
+ /**
413
+ * v0.3.17 S4 — a repository-relative path coming from a history request.
414
+ *
415
+ * Validated, never escaped: anything that could be read as a revision expression, a pathspec
416
+ * magic prefix or an absolute path is refused outright rather than passed to argv.
417
+ */
418
+ export declare function assertRelativeGitPath(path: unknown): string;
99
419
  //# sourceMappingURL=git-read-model-service.d.ts.map