@agentknight/sdk 0.9.43 → 0.9.44

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/LICENSE CHANGED
@@ -1,201 +1,201 @@
1
- Apache License
2
- Version 2.0, January 2004
3
- http://www.apache.org/licenses/
4
-
5
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
-
7
- 1. Definitions.
8
-
9
- "License" shall mean the terms and conditions for use, reproduction,
10
- and distribution as defined by Sections 1 through 9 of this document.
11
-
12
- "Licensor" shall mean the copyright owner or entity authorized by
13
- the copyright owner that is granting the License.
14
-
15
- "Legal Entity" shall mean the union of the acting entity and all
16
- other entities that control, are controlled by, or are under common
17
- control with that entity. For the purposes of this definition,
18
- "control" means (i) the power, direct or indirect, to cause the
19
- direction or management of such entity, whether by contract or
20
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
- outstanding shares, or (iii) beneficial ownership of such entity.
22
-
23
- "You" (or "Your") shall mean an individual or Legal Entity
24
- exercising permissions granted by this License.
25
-
26
- "Source" form shall mean the preferred form for making modifications,
27
- including but not limited to software source code, documentation
28
- source, and configuration files.
29
-
30
- "Object" form shall mean any form resulting from mechanical
31
- transformation or translation of a Source form, including but
32
- not limited to compiled object code, generated documentation,
33
- and conversions to other media types.
34
-
35
- "Work" shall mean the work of authorship, whether in Source or
36
- Object form, made available under the License, as indicated by a
37
- copyright notice that is included in or attached to the work
38
- (an example is provided in the Appendix below).
39
-
40
- "Derivative Works" shall mean any work, whether in Source or Object
41
- form, that is based on (or derived from) the Work and for which the
42
- editorial revisions, annotations, elaborations, or other modifications
43
- represent, as a whole, an original work of authorship. For the purposes
44
- of this License, Derivative Works shall not include works that remain
45
- separable from, or merely link (or bind by name) to the interfaces of,
46
- the Work and Derivative Works thereof.
47
-
48
- "Contribution" shall mean any work of authorship, including
49
- the original version of the Work and any modifications or additions
50
- to that Work or Derivative Works thereof, that is intentionally
51
- submitted to Licensor for inclusion in the Work by the copyright owner
52
- or by an individual or Legal Entity authorized to submit on behalf of
53
- the copyright owner. For the purposes of this definition, "submitted"
54
- means any form of electronic, verbal, or written communication sent
55
- to the Licensor or its representatives, including but not limited to
56
- communication on electronic mailing lists, source code control systems,
57
- and issue tracking systems that are managed by, or on behalf of, the
58
- Licensor for the purpose of discussing and improving the Work, but
59
- excluding communication that is conspicuously marked or otherwise
60
- designated in writing by the copyright owner as "Not a Contribution."
61
-
62
- "Contributor" shall mean Licensor and any individual or Legal Entity
63
- on behalf of whom a Contribution has been received by Licensor and
64
- subsequently incorporated within the Work.
65
-
66
- 2. Grant of Copyright License. Subject to the terms and conditions of
67
- this License, each Contributor hereby grants to You a perpetual,
68
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
- copyright license to reproduce, prepare Derivative Works of,
70
- publicly display, publicly perform, sublicense, and distribute the
71
- Work and such Derivative Works in Source or Object form.
72
-
73
- 3. Grant of Patent License. Subject to the terms and conditions of
74
- this License, each Contributor hereby grants to You a perpetual,
75
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
- (except as stated in this section) patent license to make, have made,
77
- use, offer to sell, sell, import, and otherwise transfer the Work,
78
- where such license applies only to those patent claims licensable
79
- by such Contributor that are necessarily infringed by their
80
- Contribution(s) alone or by combination of their Contribution(s)
81
- with the Work to which such Contribution(s) was submitted. If You
82
- institute patent litigation against any entity (including a
83
- cross-claim or counterclaim in a lawsuit) alleging that the Work
84
- or a Contribution incorporated within the Work constitutes direct
85
- or contributory patent infringement, then any patent licenses
86
- granted to You under this License for that Work shall terminate
87
- as of the date such litigation is filed.
88
-
89
- 4. Redistribution. You may reproduce and distribute copies of the
90
- Work or Derivative Works thereof in any medium, with or without
91
- modifications, and in Source or Object form, provided that You
92
- meet the following conditions:
93
-
94
- (a) You must give any other recipients of the Work or
95
- Derivative Works a copy of this License; and
96
-
97
- (b) You must cause any modified files to carry prominent notices
98
- stating that You changed the files; and
99
-
100
- (c) You must retain, in the Source form of any Derivative Works
101
- that You distribute, all copyright, patent, trademark, and
102
- attribution notices from the Source form of the Work,
103
- excluding those notices that do not pertain to any part of
104
- the Derivative Works; and
105
-
106
- (d) If the Work includes a "NOTICE" text file as part of its
107
- distribution, then any Derivative Works that You distribute must
108
- include a readable copy of the attribution notices contained
109
- within such NOTICE file, excluding those notices that do not
110
- pertain to any part of the Derivative Works, in at least one
111
- of the following places: within a NOTICE text file distributed
112
- as part of the Derivative Works; within the Source form or
113
- documentation, if provided along with the Derivative Works; or,
114
- within a display generated by the Derivative Works, if and
115
- wherever such third-party notices normally appear. The contents
116
- of the NOTICE file are for informational purposes only and
117
- do not modify the License. You may add Your own attribution
118
- notices within Derivative Works that You distribute, alongside
119
- or as an addendum to the NOTICE text from the Work, provided
120
- that such additional attribution notices cannot be construed
121
- as modifying the License.
122
-
123
- You may add Your own copyright statement to Your modifications and
124
- may provide additional or different license terms and conditions
125
- for use, reproduction, or distribution of Your modifications, or
126
- for any such Derivative Works as a whole, provided Your use,
127
- reproduction, and distribution of the Work otherwise complies with
128
- the conditions stated in this License.
129
-
130
- 5. Submission of Contributions. Unless You explicitly state otherwise,
131
- any Contribution intentionally submitted for inclusion in the Work
132
- by You to the Licensor shall be under the terms and conditions of
133
- this License, without any additional terms or conditions.
134
- Notwithstanding the above, nothing herein shall supersede or modify
135
- the terms of any separate license agreement you may have executed
136
- with Licensor regarding such Contributions.
137
-
138
- 6. Trademarks. This License does not grant permission to use the trade
139
- names, trademarks, service marks, or product names of the Licensor,
140
- except as required for reasonable and customary use in describing the
141
- origin of the Work and reproducing the content of the NOTICE file.
142
-
143
- 7. Disclaimer of Warranty. Unless required by applicable law or
144
- agreed to in writing, Licensor provides the Work (and each
145
- Contributor provides its Contributions) on an "AS IS" BASIS,
146
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
- implied, including, without limitation, any warranties or conditions
148
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
- PARTICULAR PURPOSE. You are solely responsible for determining the
150
- appropriateness of using or redistributing the Work and assume any
151
- risks associated with Your exercise of permissions under this License.
152
-
153
- 8. Limitation of Liability. In no event and under no legal theory,
154
- whether in tort (including negligence), contract, or otherwise,
155
- unless required by applicable law (such as deliberate and grossly
156
- negligent acts) or agreed to in writing, shall any Contributor be
157
- liable to You for damages, including any direct, indirect, special,
158
- incidental, or consequential damages of any character arising as a
159
- result of this License or out of the use or inability to use the
160
- Work (including but not limited to damages for loss of goodwill,
161
- work stoppage, computer failure or malfunction, or any and all
162
- other commercial damages or losses), even if such Contributor
163
- has been advised of the possibility of such damages.
164
-
165
- 9. Accepting Warranty or Additional Liability. While redistributing
166
- the Work or Derivative Works thereof, You may choose to offer,
167
- and charge a fee for, acceptance of support, warranty, indemnity,
168
- or other liability obligations and/or rights consistent with this
169
- License. However, in accepting such obligations, You may act only
170
- on Your own behalf and on Your sole responsibility, not on behalf
171
- of any other Contributor, and only if You agree to indemnify,
172
- defend, and hold each Contributor harmless for any liability
173
- incurred by, or claims asserted against, such Contributor by reason
174
- of your accepting any such warranty or additional liability.
175
-
176
- END OF TERMS AND CONDITIONS
177
-
178
- APPENDIX: How to apply the Apache License to your work.
179
-
180
- To apply the Apache License to your work, attach the following
181
- boilerplate notice, with the fields enclosed by brackets "[]"
182
- replaced with your own identifying information. (Don't include
183
- the brackets!) The text should be enclosed in the appropriate
184
- comment syntax for the file format. We also recommend that a
185
- file or class name and description of purpose be included on the
186
- same "printed page" as the copyright notice for easier
187
- identification within third-party archives.
188
-
189
- Copyright [yyyy] [name of copyright owner]
190
-
191
- Licensed under the Apache License, Version 2.0 (the "License");
192
- you may not use this file except in compliance with the License.
193
- You may obtain a copy of the License at
194
-
195
- http://www.apache.org/licenses/LICENSE-2.0
196
-
197
- Unless required by applicable law or agreed to in writing, software
198
- distributed under the License is distributed on an "AS IS" BASIS,
199
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
- See the License for the specific language governing permissions and
201
- limitations under the License.
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  latestPreviewItems
3
- } from "./chunk-DB3EAMYS.js";
3
+ } from "./chunk-AK3YVBEP.js";
4
4
  import {
5
5
  UnsupportedAgentOperationError
6
- } from "./chunk-ULM5KUJ7.js";
6
+ } from "./chunk-UNRPSTRM.js";
7
7
  import {
8
8
  ConversationItemSchema,
9
9
  PromptImageAttachmentSchema,
10
10
  SESSION_TIMELINE_PAGE_SIZE,
11
11
  SessionSummarySchema
12
- } from "./chunk-7QOBDG6R.js";
12
+ } from "./chunk-W6TZVD7W.js";
13
13
 
14
14
  // src/acp-adapter.ts
15
15
  import { spawn } from "node:child_process";
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  CODING_AGENT_IDS
3
- } from "./chunk-ULM5KUJ7.js";
3
+ } from "./chunk-UNRPSTRM.js";
4
4
  import {
5
5
  SECURE_MESSAGE_MAX_CIPHERTEXT_LENGTH
6
- } from "./chunk-7QOBDG6R.js";
6
+ } from "./chunk-W6TZVD7W.js";
7
7
 
8
8
  // src/agent-selection.ts
9
9
  import { z } from "zod";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  SessionAssistantPreviewSchema,
3
3
  SessionUserPreviewSchema
4
- } from "./chunk-7QOBDG6R.js";
4
+ } from "./chunk-W6TZVD7W.js";
5
5
 
6
6
  // src/assistant-preview.ts
7
7
  function isContentfulAssistant(item) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  isContentfulAssistant
3
- } from "./chunk-DB3EAMYS.js";
3
+ } from "./chunk-AK3YVBEP.js";
4
4
  import {
5
5
  SessionOperationError
6
- } from "./chunk-ULM5KUJ7.js";
6
+ } from "./chunk-UNRPSTRM.js";
7
7
  import {
8
8
  CONVERSATION_SOURCE_ID_LIMIT,
9
9
  SESSION_DIRECTORY_LIST_OPERATION,
@@ -23,7 +23,7 @@ import {
23
23
  WorkbenchInsightsSchema,
24
24
  WorkbenchQueueMutationResultSchema,
25
25
  WorkbenchQueueSnapshotSchema
26
- } from "./chunk-7QOBDG6R.js";
26
+ } from "./chunk-W6TZVD7W.js";
27
27
 
28
28
  // src/operation-diagnostics.ts
29
29
  import { AsyncLocalStorage } from "node:async_hooks";
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  AgentSessionRenameError,
3
3
  validateSessionName
4
- } from "./chunk-ULM5KUJ7.js";
4
+ } from "./chunk-UNRPSTRM.js";
5
5
  import {
6
6
  ConversationItemSchema,
7
7
  GroupChatInfoSchema,
8
8
  GroupChatParticipantSchema,
9
9
  SESSION_TIMELINE_PAGE_SIZE,
10
10
  SessionSummarySchema
11
- } from "./chunk-7QOBDG6R.js";
11
+ } from "./chunk-W6TZVD7W.js";
12
12
 
13
13
  // src/group-chat.ts
14
14
  import { createHash, randomUUID } from "node:crypto";
@@ -3,7 +3,7 @@ import {
3
3
  SessionCommunicationDataSchema,
4
4
  SessionNameSchema,
5
5
  WorkbenchOperationStatusSchema
6
- } from "./chunk-7QOBDG6R.js";
6
+ } from "./chunk-W6TZVD7W.js";
7
7
 
8
8
  // src/session-operations.ts
9
9
  import { createHash, randomUUID } from "node:crypto";
@@ -1872,6 +1872,7 @@ import { z as z19 } from "zod";
1872
1872
  var SESSION_GIT_DIFF_OPERATION = "session.git.diff";
1873
1873
  var SESSION_GIT_DIFF_VERSION = 1;
1874
1874
  var SESSION_GIT_DIFF_GZIP_VERSION = 2;
1875
+ var SESSION_GIT_DIFF_PARTIAL_VERSION = 3;
1875
1876
  var SESSION_GIT_DIFF_GZIP_MIN_BYTES = 2 * 1024;
1876
1877
  var SESSION_GIT_DIFF_MAX_FILES = 500;
1877
1878
  var SESSION_GIT_DIFF_MAX_PATCH_BYTES = 128 * 1024;
@@ -1910,6 +1911,22 @@ var SessionGitDiffResultDataSchema = z19.object({
1910
1911
  context.addIssue({ code: "custom", message: "Expected a text patch or an explicit binary change" });
1911
1912
  }
1912
1913
  });
1914
+ var SessionGitDiffFileErrorSchema = z19.object({
1915
+ code: z19.enum(["DIFF_BLOCKED", "DIFF_FILE_UNAVAILABLE"]),
1916
+ message: z19.string().min(1).max(512)
1917
+ }).strict();
1918
+ var SessionGitDiffPartialEntrySchema = SessionGitDiffEntrySchema.extend({
1919
+ // Error paths are display-only: they must never be used for file requests.
1920
+ path: z19.string().min(1).max(32768).refine((value) => !value.includes("\0")),
1921
+ error: SessionGitDiffFileErrorSchema.optional()
1922
+ }).superRefine((value, context) => {
1923
+ if (value.error === void 0 && !SessionGitDiffEntrySchema.shape.path.safeParse(value.path).success) {
1924
+ context.addIssue({ code: "custom", message: "A readable diff entry must have a safe path" });
1925
+ }
1926
+ });
1927
+ var SessionGitDiffPartialResultDataSchema = SessionGitDiffResultDataSchema.safeExtend({
1928
+ files: z19.array(SessionGitDiffPartialEntrySchema).max(SESSION_GIT_DIFF_MAX_FILES).optional()
1929
+ });
1913
1930
  var SessionGitDiffGzipResultDataSchema = z19.object({
1914
1931
  encoding: z19.literal("gzip"),
1915
1932
  byteLength: z19.number().int().min(1).max(SESSION_GIT_DIFF_MAX_RESPONSE_BYTES),
@@ -2571,8 +2588,9 @@ var AndroidProtocolSchemas = {
2571
2588
  ...ScheduleAndroidSchemas,
2572
2589
  SessionCommunication: SessionCommunicationSchema,
2573
2590
  SessionGitDiffData: SessionGitDiffDataSchema,
2574
- SessionGitDiffEntry: SessionGitDiffEntrySchema,
2575
- SessionGitDiffResultData: SessionGitDiffResultDataSchema,
2591
+ SessionGitDiffEntry: SessionGitDiffPartialEntrySchema,
2592
+ SessionGitDiffResultData: SessionGitDiffPartialResultDataSchema,
2593
+ SessionGitDiffFileError: SessionGitDiffFileErrorSchema,
2576
2594
  SessionGitDiffGzipResultData: SessionGitDiffGzipResultDataSchema,
2577
2595
  SessionRenameData: SessionRenameDataSchema,
2578
2596
  SessionRenameResultData: SessionRenameResultDataSchema,
@@ -2733,12 +2751,14 @@ export {
2733
2751
  SESSION_GIT_DIFF_OPERATION,
2734
2752
  SESSION_GIT_DIFF_VERSION,
2735
2753
  SESSION_GIT_DIFF_GZIP_VERSION,
2754
+ SESSION_GIT_DIFF_PARTIAL_VERSION,
2736
2755
  SESSION_GIT_DIFF_GZIP_MIN_BYTES,
2737
2756
  SESSION_GIT_DIFF_MAX_FILES,
2738
2757
  SESSION_GIT_DIFF_MAX_PATCH_BYTES,
2739
2758
  SESSION_GIT_DIFF_MAX_RESPONSE_BYTES,
2740
2759
  SessionGitDiffDataSchema,
2741
2760
  SessionGitDiffResultDataSchema,
2761
+ SessionGitDiffPartialResultDataSchema,
2742
2762
  SessionGitDiffGzipResultDataSchema,
2743
2763
  SESSION_RESOURCE_READ_OPERATION,
2744
2764
  SESSION_RESOURCE_READ_VERSION,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  IdSchema
3
- } from "./chunk-7QOBDG6R.js";
3
+ } from "./chunk-W6TZVD7W.js";
4
4
 
5
5
  // src/data-directory.ts
6
6
  import { randomUUID } from "node:crypto";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SessionOperationError
3
- } from "./chunk-ULM5KUJ7.js";
3
+ } from "./chunk-UNRPSTRM.js";
4
4
 
5
5
  // src/adapters/copilot/runtime/session-identity.ts
6
6
  function assertMainSessionId(sessionId) {
@@ -3,18 +3,18 @@ import {
3
3
  } from "./chunk-EIFNERXM.js";
4
4
  import {
5
5
  latestPreviewItems
6
- } from "./chunk-DB3EAMYS.js";
6
+ } from "./chunk-AK3YVBEP.js";
7
7
  import {
8
8
  UnsupportedAgentOperationError,
9
9
  validateSessionName
10
- } from "./chunk-ULM5KUJ7.js";
10
+ } from "./chunk-UNRPSTRM.js";
11
11
  import {
12
12
  ConversationItemSchema,
13
13
  InteractionRequestSchema,
14
14
  InteractionResponseSchema,
15
15
  SESSION_TIMELINE_PAGE_SIZE,
16
16
  SessionSummarySchema
17
- } from "./chunk-7QOBDG6R.js";
17
+ } from "./chunk-W6TZVD7W.js";
18
18
 
19
19
  // src/claude-adapter.ts
20
20
  import { randomUUID as randomUUID2 } from "node:crypto";
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  latestPreviewItems
3
- } from "./chunk-DB3EAMYS.js";
3
+ } from "./chunk-AK3YVBEP.js";
4
4
  import {
5
5
  UnsupportedAgentOperationError
6
- } from "./chunk-ULM5KUJ7.js";
6
+ } from "./chunk-UNRPSTRM.js";
7
7
  import {
8
8
  ConversationItemSchema,
9
9
  InteractionRequestSchema,
10
10
  SESSION_TIMELINE_PAGE_SIZE,
11
11
  SessionSummarySchema
12
- } from "./chunk-7QOBDG6R.js";
12
+ } from "./chunk-W6TZVD7W.js";
13
13
 
14
14
  // src/codex-adapter.ts
15
15
  import { randomUUID } from "node:crypto";
@@ -18,25 +18,25 @@ import {
18
18
  recordTimelineSyncDiagnostic,
19
19
  resolveGitProjectIdentity,
20
20
  sanitizeGitRemoteUrl
21
- } from "./chunk-CWJENQ3O.js";
21
+ } from "./chunk-EWXFUECA.js";
22
22
  import {
23
23
  assertMainSessionId,
24
24
  isResearchSessionId
25
- } from "./chunk-NYSZHHBS.js";
25
+ } from "./chunk-ZST7M4CD.js";
26
26
  import {
27
27
  GroupChatError,
28
28
  GroupChatMessageSchema,
29
29
  GroupChatRuntime
30
- } from "./chunk-C2VUD77E.js";
30
+ } from "./chunk-LRSHP7WN.js";
31
31
  import {
32
32
  isContentfulAssistant
33
- } from "./chunk-DB3EAMYS.js";
33
+ } from "./chunk-AK3YVBEP.js";
34
34
  import {
35
35
  AgentSessionRenameError,
36
36
  SessionOperationError,
37
37
  TimelinePageBudgetError,
38
38
  validateSessionName
39
- } from "./chunk-ULM5KUJ7.js";
39
+ } from "./chunk-UNRPSTRM.js";
40
40
  import {
41
41
  ConversationItemSchema,
42
42
  CopilotModelOptionSchema,
@@ -57,7 +57,7 @@ import {
57
57
  WorkbenchScheduleEntrySchema,
58
58
  WorkbenchScheduleProposalSchema,
59
59
  WorkbenchScheduleSnapshotSchema
60
- } from "./chunk-7QOBDG6R.js";
60
+ } from "./chunk-W6TZVD7W.js";
61
61
 
62
62
  // src/copilot-adapter.ts
63
63
  import { createHash as createHash4, randomUUID as randomUUID6 } from "node:crypto";
@@ -1,13 +1,13 @@
1
1
  import {
2
2
  AgentSelectionSchema,
3
3
  assertSelectionSnapshotFits
4
- } from "./chunk-YZ2GB3DD.js";
4
+ } from "./chunk-4UAMAGVT.js";
5
5
  import {
6
6
  isResearchSessionId
7
- } from "./chunk-NYSZHHBS.js";
7
+ } from "./chunk-ZST7M4CD.js";
8
8
  import {
9
9
  GroupChatError
10
- } from "./chunk-C2VUD77E.js";
10
+ } from "./chunk-LRSHP7WN.js";
11
11
  import {
12
12
  AgentModelListingError,
13
13
  AgentSessionRenameError,
@@ -16,11 +16,11 @@ import {
16
16
  UnsupportedAgentOperationError,
17
17
  captureWorkbenchAccess,
18
18
  validateSessionName
19
- } from "./chunk-ULM5KUJ7.js";
19
+ } from "./chunk-UNRPSTRM.js";
20
20
  import {
21
21
  InteractionResponseSchema,
22
22
  SessionSummarySchema
23
- } from "./chunk-7QOBDG6R.js";
23
+ } from "./chunk-W6TZVD7W.js";
24
24
 
25
25
  // src/managed-agent-adapter.ts
26
26
  import { createHash, randomUUID } from "node:crypto";
@@ -1,16 +1,16 @@
1
1
  import {
2
2
  latestPreviewItems
3
- } from "./chunk-DB3EAMYS.js";
3
+ } from "./chunk-AK3YVBEP.js";
4
4
  import {
5
5
  AgentSessionRenameError,
6
6
  UnsupportedAgentOperationError,
7
7
  validateSessionName
8
- } from "./chunk-ULM5KUJ7.js";
8
+ } from "./chunk-UNRPSTRM.js";
9
9
  import {
10
10
  InteractionRequestSchema,
11
11
  REASONING_EFFORTS,
12
12
  SESSION_TIMELINE_PAGE_SIZE
13
- } from "./chunk-7QOBDG6R.js";
13
+ } from "./chunk-W6TZVD7W.js";
14
14
 
15
15
  // src/pi-adapter.ts
16
16
  import { createHash as createHash2, randomUUID } from "node:crypto";
package/dist/index.js CHANGED
@@ -4,12 +4,12 @@ import {
4
4
  PeerChatRequestSchema,
5
5
  PeerChatResultSchema,
6
6
  validateDataDirectory
7
- } from "./chunks/chunk-M2QZ6EFR.js";
7
+ } from "./chunks/chunk-ZGO2OSQZ.js";
8
8
  import {
9
9
  AgentSelectionSchema,
10
10
  assertSelectionSnapshotFits,
11
11
  supportsAgentSelection
12
- } from "./chunks/chunk-YZ2GB3DD.js";
12
+ } from "./chunks/chunk-4UAMAGVT.js";
13
13
  import {
14
14
  ConversationNormalizer,
15
15
  LiveTimelineProjection,
@@ -31,11 +31,11 @@ import {
31
31
  resolveGitProjectIdentity,
32
32
  sessionRestoreFailure,
33
33
  validateOperationResponse
34
- } from "./chunks/chunk-CWJENQ3O.js";
34
+ } from "./chunks/chunk-EWXFUECA.js";
35
35
  import {
36
36
  GROUP_CHAT_MAX_TURNS,
37
37
  GroupChatError
38
- } from "./chunks/chunk-C2VUD77E.js";
38
+ } from "./chunks/chunk-LRSHP7WN.js";
39
39
  import {
40
40
  detectClaude,
41
41
  detectCopilot,
@@ -46,7 +46,7 @@ import {
46
46
  assistantPreview,
47
47
  isContentfulAssistant,
48
48
  userPreview
49
- } from "./chunks/chunk-DB3EAMYS.js";
49
+ } from "./chunks/chunk-AK3YVBEP.js";
50
50
  import {
51
51
  AgentModelListingError,
52
52
  AgentSessionRenameError,
@@ -57,7 +57,7 @@ import {
57
57
  UnsupportedAgentOperationError,
58
58
  captureResearchAccess,
59
59
  captureWorkbenchAccess
60
- } from "./chunks/chunk-ULM5KUJ7.js";
60
+ } from "./chunks/chunk-UNRPSTRM.js";
61
61
  import {
62
62
  A2aRelayRequestSchema,
63
63
  A2aRelayResponseSchema,
@@ -131,6 +131,7 @@ import {
131
131
  SESSION_GIT_DIFF_MAX_PATCH_BYTES,
132
132
  SESSION_GIT_DIFF_MAX_RESPONSE_BYTES,
133
133
  SESSION_GIT_DIFF_OPERATION,
134
+ SESSION_GIT_DIFF_PARTIAL_VERSION,
134
135
  SESSION_GIT_DIFF_VERSION,
135
136
  SESSION_IMAGE_API_PATH,
136
137
  SESSION_IMAGE_MAX_BYTES,
@@ -169,6 +170,7 @@ import {
169
170
  SessionFileReadV2ResultDataSchema,
170
171
  SessionGitDiffDataSchema,
171
172
  SessionGitDiffGzipResultDataSchema,
173
+ SessionGitDiffPartialResultDataSchema,
172
174
  SessionGitDiffResultDataSchema,
173
175
  SessionImageCommitResultSchema,
174
176
  SessionImageScopeSchema,
@@ -239,7 +241,7 @@ import {
239
241
  sessionCommunicationError,
240
242
  sessionCommunicationOperationCapability,
241
243
  workbenchCapability
242
- } from "./chunks/chunk-7QOBDG6R.js";
244
+ } from "./chunks/chunk-W6TZVD7W.js";
243
245
 
244
246
  // src/initialize.ts
245
247
  import { createHash as createHash16 } from "node:crypto";
@@ -277,7 +279,7 @@ async function createCodingAgentAdapter(config, onDiagnostic, owner) {
277
279
  switch (engine.kind) {
278
280
  case "managed": {
279
281
  if (owner === void 0) throw new Error("Managed coding agents require the PC owner identity");
280
- const { ManagedCodingAgentAdapter } = await import("./chunks/managed-agent-adapter-ZXTKIPJN.js");
282
+ const { ManagedCodingAgentAdapter } = await import("./chunks/managed-agent-adapter-HDLOSSHZ.js");
281
283
  return new ManagedCodingAgentAdapter({
282
284
  dataDirectory: config.dataDirectory,
283
285
  owner,
@@ -334,7 +336,7 @@ async function createCodingAgentAdapter(config, onDiagnostic, owner) {
334
336
  });
335
337
  }
336
338
  case "copilot": {
337
- const { GithubCopilotAdapter } = await import("./chunks/copilot-adapter-UP6KDSXH.js");
339
+ const { GithubCopilotAdapter } = await import("./chunks/copilot-adapter-Y5W4ZUFD.js");
338
340
  if (owner !== void 0) {
339
341
  return new GithubCopilotAdapter(void 0, void 0, void 0, {
340
342
  dataDirectory: config.dataDirectory,
@@ -354,13 +356,13 @@ async function createCodingAgentAdapter(config, onDiagnostic, owner) {
354
356
  }
355
357
  case "pi": {
356
358
  assertPiRuntimeSupported();
357
- const { PiCodingAgentAdapter } = await import("./chunks/pi-adapter-KXVZ5QP5.js");
359
+ const { PiCodingAgentAdapter } = await import("./chunks/pi-adapter-6EF6Z5CP.js");
358
360
  return new PiCodingAgentAdapter(
359
361
  engine.agentDirectory === void 0 ? {} : { agentDirectory: resolve(engine.agentDirectory) }
360
362
  );
361
363
  }
362
364
  case "codex": {
363
- const { CodexCodingAgentAdapter } = await import("./chunks/codex-adapter-VQTLTFNP.js");
365
+ const { CodexCodingAgentAdapter } = await import("./chunks/codex-adapter-MMQK47KY.js");
364
366
  return new CodexCodingAgentAdapter({
365
367
  dataDirectory: resolve(config.dataDirectory, "coding-agents"),
366
368
  ...engine.command === void 0 ? {} : { command: engine.command },
@@ -368,14 +370,14 @@ async function createCodingAgentAdapter(config, onDiagnostic, owner) {
368
370
  });
369
371
  }
370
372
  case "claude": {
371
- const { ClaudeCodingAgentAdapter } = await import("./chunks/claude-adapter-7VQ4QCNI.js");
373
+ const { ClaudeCodingAgentAdapter } = await import("./chunks/claude-adapter-A5EFNV5S.js");
372
374
  return new ClaudeCodingAgentAdapter({
373
375
  dataDirectory: resolve(config.dataDirectory, "coding-agents"),
374
376
  ...onDiagnostic === void 0 ? {} : { onDiagnostic }
375
377
  });
376
378
  }
377
379
  case "acp": {
378
- const { AcpCodingAgentAdapter } = await import("./chunks/acp-adapter-LJNYHSSY.js");
380
+ const { AcpCodingAgentAdapter } = await import("./chunks/acp-adapter-JKSOVQJ7.js");
379
381
  return new AcpCodingAgentAdapter({
380
382
  command: engine.command,
381
383
  args: engine.args,
@@ -2690,6 +2692,28 @@ var SessionGitDiffError = class extends Error {
2690
2692
  function fail3(code, message) {
2691
2693
  throw new SessionGitDiffError(code, message);
2692
2694
  }
2695
+ function fileError(error) {
2696
+ if (error instanceof SessionGitDiffError && error.code === "DIFF_BLOCKED") {
2697
+ return { code: "DIFF_BLOCKED", message: error.message };
2698
+ }
2699
+ if (error instanceof Error && "code" in error && typeof error.code === "string" && ["EACCES", "EPERM", "EBUSY", "ENAMETOOLONG", "EINVAL", "EIO", "ELOOP"].includes(error.code)) {
2700
+ return { code: "DIFF_FILE_UNAVAILABLE", message: `Cannot read this path (${error.code})` };
2701
+ }
2702
+ return void 0;
2703
+ }
2704
+ async function forFile(path, work, operation) {
2705
+ try {
2706
+ return await operation();
2707
+ } catch (error) {
2708
+ const failure = work.partial ? fileError(error) : void 0;
2709
+ if (failure === void 0) throw error;
2710
+ throw new SessionGitDiffError(
2711
+ failure.code === "DIFF_BLOCKED" ? "DIFF_FILE_BLOCKED" : failure.code,
2712
+ `${path}: ${failure.message}`,
2713
+ { cause: error }
2714
+ );
2715
+ }
2716
+ }
2693
2717
  function changed() {
2694
2718
  return fail3("DIFF_CHANGED", "The project diff changed; refresh the changed-file list");
2695
2719
  }
@@ -2725,12 +2749,30 @@ function environment() {
2725
2749
  function isExit(error, code) {
2726
2750
  return error instanceof Error && "code" in error && error.code === code && "stdout" in error && Buffer.isBuffer(error.stdout) && "stderr" in error && Buffer.isBuffer(error.stderr);
2727
2751
  }
2752
+ function hashFileError(error, path) {
2753
+ if (!isExit(error, 128)) return void 0;
2754
+ const diagnostic = decode(error.stderr).trim().split(/\r?\n/u).at(-1) ?? "";
2755
+ if (!diagnostic.startsWith(`fatal: could not open '${path}' for reading: `)) return void 0;
2756
+ return { code: "DIFF_FILE_UNAVAILABLE", message: "Cannot normalize this path for comparison" };
2757
+ }
2728
2758
  var Work = class {
2759
+ constructor(partial) {
2760
+ this.partial = partial;
2761
+ }
2762
+ partial;
2729
2763
  deadline = Date.now() + SESSION_GIT_DIFF_TIMEOUT_MS;
2730
2764
  env = environment();
2731
2765
  bytes = 0;
2766
+ linkFiles = /* @__PURE__ */ new Set();
2767
+ symlinks = true;
2732
2768
  #filterConfig = [];
2733
2769
  async disableExternalFilters(repository) {
2770
+ this.symlinks = decode(await this.git(repository, [
2771
+ "config",
2772
+ "--type=bool",
2773
+ "--get",
2774
+ "core.symlinks"
2775
+ ], { allowExitOne: true })).trim() !== "false";
2734
2776
  const names = records(await this.git(repository, [
2735
2777
  "config",
2736
2778
  "--includes",
@@ -2836,8 +2878,22 @@ async function inspect(root, path, work, kind = "file") {
2836
2878
  return void 0;
2837
2879
  }
2838
2880
  async function readCurrent(root, path, algorithm, work, keepBytes = false) {
2839
- const before = await inspect(root, path, work);
2881
+ const kind = work.partial ? "link" : "file";
2882
+ const before = await inspect(root, path, work, kind);
2840
2883
  if (before === void 0) return void 0;
2884
+ if (before.isSymbolicLink()) {
2885
+ const bytes = Buffer.from(await readlink(join5(root, ...path.split("/"))), "utf8");
2886
+ const latest = await inspect(root, path, work, "link");
2887
+ if (latest === void 0 || identity(latest) !== identity(before)) changed();
2888
+ const oid = createHash5(algorithm).update(`blob ${bytes.length}\0`).update(bytes).digest("hex");
2889
+ return {
2890
+ oid,
2891
+ rawOid: oid,
2892
+ identity: identity(before),
2893
+ mode: "120000",
2894
+ ...keepBytes ? { bytes } : {}
2895
+ };
2896
+ }
2841
2897
  if (before.size > BigInt(MAX_SCAN_BYTES - work.bytes) || keepBytes && before.size > BigInt(SESSION_GIT_DIFF_MAX_SOURCE_BYTES)) limit();
2842
2898
  work.bytes += Number(before.size);
2843
2899
  const handle = await open2(
@@ -2867,7 +2923,7 @@ async function readCurrent(root, path, algorithm, work, keepBytes = false) {
2867
2923
  oid: rawOid,
2868
2924
  rawOid,
2869
2925
  identity: identity(before),
2870
- mode: process.platform !== "win32" && (before.mode & 0o111n) !== 0n ? "100755" : "100644",
2926
+ mode: work.linkFiles.has(path) ? "120000" : process.platform !== "win32" && (before.mode & 0o111n) !== 0n ? "100755" : "100644",
2871
2927
  ...keepBytes ? { bytes: Buffer.concat(chunks) } : {}
2872
2928
  };
2873
2929
  } finally {
@@ -2903,7 +2959,6 @@ function scopedPath(context, path) {
2903
2959
  const prefix = context.prefix === "" ? "" : `${context.prefix}/`;
2904
2960
  if (!path.startsWith(prefix)) fail3("DIFF_BLOCKED", "Git returned a path outside the session");
2905
2961
  const scoped = path.slice(prefix.length);
2906
- if (!safePath(scoped)) fail3("DIFF_BLOCKED", "The project contains an unsupported path");
2907
2962
  return scoped;
2908
2963
  }
2909
2964
  function records(output2) {
@@ -2934,7 +2989,7 @@ async function changes(context, work) {
2934
2989
  return scoped2;
2935
2990
  };
2936
2991
  for (const record of tree) {
2937
- const match = /^(\d{6}) (blob|commit) ([a-f0-9]{40}|[a-f0-9]{64})\t(.+)$/u.exec(record);
2992
+ const match = /^(\d{6}) (blob|commit) ([a-f0-9]{40}|[a-f0-9]{64})\t([\s\S]+)$/u.exec(record);
2938
2993
  if (!match?.[1] || !match[3] || !match[4]) fail3("DIFF_UNAVAILABLE", "Git returned an invalid tree");
2939
2994
  blobs.set(scoped(match[4]), { mode: match[1], oid: match[3] });
2940
2995
  }
@@ -2946,7 +3001,7 @@ async function changes(context, work) {
2946
3001
  "--",
2947
3002
  ...paths
2948
3003
  ]))) {
2949
- const match = /^(\d{6}) ([a-f0-9]{40}|[a-f0-9]{64}) [0-3]\t(.+)$/u.exec(record);
3004
+ const match = /^(\d{6}) ([a-f0-9]{40}|[a-f0-9]{64}) [0-3]\t([\s\S]+)$/u.exec(record);
2950
3005
  if (!match?.[1] || !match[2] || !match[3]) fail3("DIFF_UNAVAILABLE", "Git returned an invalid index");
2951
3006
  tracked.set(scoped(match[3]), { mode: match[1], oid: match[2] });
2952
3007
  }
@@ -2985,38 +3040,88 @@ async function changes(context, work) {
2985
3040
  files: untracked
2986
3041
  }), "utf8") > SESSION_GIT_DIFF_MAX_RESPONSE_BYTES) limit();
2987
3042
  const result = [];
3043
+ const errors = /* @__PURE__ */ new Map();
2988
3044
  const algorithm = context.baseCommit.length === 64 ? "sha256" : "sha1";
2989
3045
  const currentFiles = /* @__PURE__ */ new Map();
3046
+ if (work.partial && !work.symlinks) {
3047
+ for (const [path, blob] of tracked) if (blob.mode === "120000") work.linkFiles.add(path);
3048
+ }
2990
3049
  for (const path of [...candidates].sort()) {
2991
3050
  work.check();
2992
- const original = blobs.get(path);
2993
- const indexed = tracked.get(path);
2994
- if ([original?.mode, indexed?.mode].some((mode) => mode !== void 0 && mode !== "100644" && mode !== "100755")) {
2995
- await unchangedSpecial(context, path, original, indexed, work);
2996
- candidates.delete(path);
2997
- continue;
3051
+ try {
3052
+ if (!safePath(path)) fail3("DIFF_BLOCKED", "This path cannot be safely accessed on the PC");
3053
+ const original = blobs.get(path);
3054
+ const indexed = tracked.get(path);
3055
+ if ([original?.mode, indexed?.mode].some((mode) => mode !== void 0 && mode !== "100644" && mode !== "100755" && !(work.partial && mode === "120000"))) {
3056
+ await unchangedSpecial(context, path, original, indexed, work);
3057
+ candidates.delete(path);
3058
+ continue;
3059
+ }
3060
+ const current = await readCurrent(context.root, path, algorithm, work);
3061
+ if (current !== void 0) currentFiles.set(path, current);
3062
+ } catch (error) {
3063
+ const failure = fileError(error);
3064
+ if (failure === void 0) throw error;
3065
+ errors.set(path, failure);
2998
3066
  }
2999
- const current = await readCurrent(context.root, path, algorithm, work);
3000
- if (current !== void 0) currentFiles.set(path, current);
3001
3067
  }
3002
- if (currentFiles.size > 0) {
3003
- const hashes = decode(await work.git(context.repository, ["hash-object", "--stdin-paths"], {
3004
- input: [...currentFiles.keys()].map((path) => [context.prefix, path].filter(Boolean).join("/")).join("\n") + "\n"
3005
- })).trim().split("\n");
3006
- if (hashes.length !== currentFiles.size) changed();
3007
- for (const [index, [path, current]] of [...currentFiles].entries()) {
3008
- const oid = hashes[index];
3009
- if (!oid || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u.test(oid)) changed();
3010
- const latest = await inspect(context.root, path, work);
3011
- if (latest === void 0 || identity(latest) !== current.identity) changed();
3012
- current.oid = oid;
3068
+ const regularFiles = [...currentFiles].filter(([, current]) => current.mode !== "120000");
3069
+ if (regularFiles.length > 0) {
3070
+ let hashes;
3071
+ try {
3072
+ hashes = decode(await work.git(context.repository, ["hash-object", "--stdin-paths"], {
3073
+ input: regularFiles.map(([path]) => JSON.stringify([context.prefix, path].filter(Boolean).join("/"))).join("\n") + "\n"
3074
+ })).trim().split("\n");
3075
+ } catch (error) {
3076
+ if (!work.partial || !isExit(error, 128) || regularFiles.length > SESSION_GIT_DIFF_MAX_FILES) throw error;
3077
+ hashes = [];
3078
+ for (const [path] of regularFiles) {
3079
+ const repositoryPath = [context.prefix, path].filter(Boolean).join("/");
3080
+ try {
3081
+ hashes.push(decode(await work.git(context.repository, ["hash-object", "--stdin-paths"], {
3082
+ input: JSON.stringify(repositoryPath) + "\n"
3083
+ })).trim());
3084
+ } catch (error2) {
3085
+ const failure = hashFileError(error2, repositoryPath);
3086
+ if (failure === void 0) throw error2;
3087
+ errors.set(path, failure);
3088
+ currentFiles.delete(path);
3089
+ hashes.push("");
3090
+ }
3091
+ }
3092
+ }
3093
+ if (hashes.length !== regularFiles.length) changed();
3094
+ for (const [index, [path, current]] of regularFiles.entries()) {
3095
+ if (errors.has(path)) continue;
3096
+ try {
3097
+ const oid = hashes[index];
3098
+ if (!oid || !/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/u.test(oid)) changed();
3099
+ const latest = await inspect(context.root, path, work);
3100
+ if (latest === void 0 || identity(latest) !== current.identity) changed();
3101
+ current.oid = oid;
3102
+ } catch (error) {
3103
+ const failure = work.partial ? fileError(error) : void 0;
3104
+ if (failure === void 0) throw error;
3105
+ errors.set(path, failure);
3106
+ currentFiles.delete(path);
3107
+ }
3013
3108
  }
3014
3109
  }
3015
3110
  for (const path of [...candidates].sort()) {
3016
3111
  const original = blobs.get(path);
3017
3112
  const current = currentFiles.get(path);
3113
+ const error = errors.get(path);
3114
+ if (error !== void 0) {
3115
+ result.push({
3116
+ entry: { path, status: original === void 0 ? tracked.has(path) ? "added" : "untracked" : tracked.has(path) ? "modified" : "deleted", error },
3117
+ base: original,
3118
+ current: void 0
3119
+ });
3120
+ if (result.length > SESSION_GIT_DIFF_MAX_FILES) limit();
3121
+ continue;
3122
+ }
3018
3123
  if (original === void 0 && current === void 0) continue;
3019
- if (original?.oid === current?.oid && (process.platform === "win32" || original?.mode === current?.mode)) continue;
3124
+ if (original?.oid === current?.oid && original?.mode === "120000" === (current?.mode === "120000") && (process.platform === "win32" || original?.mode === current?.mode)) continue;
3020
3125
  result.push({
3021
3126
  entry: { path, status: original === void 0 ? tracked.has(path) ? "added" : "untracked" : current === void 0 ? "deleted" : "modified" },
3022
3127
  base: original,
@@ -3068,7 +3173,20 @@ async function patch(context, change, work, scratchDirectory) {
3068
3173
  if (current?.rawOid !== change.current?.rawOid || current?.mode !== change.current?.mode) changed();
3069
3174
  let original = Buffer.alloc(0);
3070
3175
  if (change.base !== void 0) {
3071
- const size = Number(decode(await work.git(context.repository, ["cat-file", "-s", change.base.oid])).trim());
3176
+ let sizeBytes;
3177
+ try {
3178
+ sizeBytes = await work.git(context.repository, ["cat-file", "-s", change.base.oid]);
3179
+ } catch (error) {
3180
+ if (work.partial && isExit(error, 128) && decode(error.stderr).trim() === "fatal: git cat-file: could not get object info") {
3181
+ throw new SessionGitDiffError(
3182
+ "DIFF_FILE_UNAVAILABLE",
3183
+ `${change.entry.path}: The base version of this file is unavailable`,
3184
+ { cause: error }
3185
+ );
3186
+ }
3187
+ throw error;
3188
+ }
3189
+ const size = Number(decode(sizeBytes).trim());
3072
3190
  if (!Number.isSafeInteger(size) || size < 0 || size > SESSION_GIT_DIFF_MAX_SOURCE_BYTES) limit();
3073
3191
  original = await work.git(context.repository, ["cat-file", "blob", change.base.oid], { maxBuffer: size + 1 });
3074
3192
  if (original.length !== size) changed();
@@ -3086,7 +3204,7 @@ async function patch(context, change, work, scratchDirectory) {
3086
3204
  let text;
3087
3205
  try {
3088
3206
  let bytes = current?.bytes ?? Buffer.alloc(0);
3089
- if (current !== void 0) {
3207
+ if (current !== void 0 && current.mode !== "120000") {
3090
3208
  const objectDirectory = join5(scratch, "objects");
3091
3209
  await mkdir2(objectDirectory);
3092
3210
  const path = [context.prefix, change.entry.path].filter(Boolean).join("/");
@@ -3134,6 +3252,18 @@ async function patch(context, change, work, scratchDirectory) {
3134
3252
  } finally {
3135
3253
  await rm(scratch, { recursive: true, force: true, maxRetries: 3 });
3136
3254
  }
3255
+ if (current?.mode === "120000" || change.base?.mode === "120000") {
3256
+ text = text.replace(/^new file mode \d+$/mu, `new file mode ${current?.mode}`).replace(/^deleted file mode \d+$/mu, `deleted file mode ${change.base?.mode}`);
3257
+ if (current !== void 0 && change.base !== void 0 && current.mode !== change.base.mode) {
3258
+ text = text.replace(/^old mode \d+\nnew mode \d+\n/mu, "");
3259
+ if (text === "") text = `diff --git a/${change.entry.path} b/${change.entry.path}
3260
+ `;
3261
+ const end = text.indexOf("\n") + 1;
3262
+ text = `${text.slice(0, end)}old mode ${change.base.mode}
3263
+ new mode ${current.mode}
3264
+ ${text.slice(end)}`;
3265
+ }
3266
+ }
3137
3267
  if (Buffer.byteLength(text, "utf8") > SESSION_GIT_DIFF_MAX_PATCH_BYTES) limit();
3138
3268
  return { patch: text, binary: false };
3139
3269
  }
@@ -3145,14 +3275,14 @@ var SessionGitDiffReader = class {
3145
3275
  metadata;
3146
3276
  scratchDirectory;
3147
3277
  #active = 0;
3148
- async read(sessionId, data) {
3278
+ async read(sessionId, data, version = SESSION_GIT_DIFF_PARTIAL_VERSION) {
3149
3279
  if (!SessionGitDiffDataSchema.safeParse(data).success || data.path !== void 0 && !safePath(data.path)) {
3150
3280
  fail3("INVALID_DIFF_PATH", "The project diff request is invalid");
3151
3281
  }
3152
3282
  if (this.#active >= SESSION_GIT_DIFF_CONCURRENCY) fail3("DIFF_BUSY", "Too many project diff requests");
3153
3283
  this.#active++;
3154
- const work = new Work();
3155
- const pending = this.#read(sessionId, data, work).finally(() => {
3284
+ const work = new Work(version >= SESSION_GIT_DIFF_PARTIAL_VERSION);
3285
+ const pending = this.#read(sessionId, data, work, version).finally(() => {
3156
3286
  this.#active--;
3157
3287
  });
3158
3288
  let timer;
@@ -3225,7 +3355,7 @@ var SessionGitDiffReader = class {
3225
3355
  ...await base(repository, work)
3226
3356
  };
3227
3357
  }
3228
- async #read(sessionId, data, work) {
3358
+ async #read(sessionId, data, work, version) {
3229
3359
  const context = await this.#context(sessionId, data.rootRevision, work);
3230
3360
  if (data.baseCommit !== void 0 && data.baseCommit !== context.baseCommit) changed();
3231
3361
  await work.disableExternalFilters(context.repository);
@@ -3238,7 +3368,23 @@ var SessionGitDiffReader = class {
3238
3368
  } else {
3239
3369
  selected = files.find(({ entry }) => entry.path === data.path);
3240
3370
  if (selected === void 0) changed();
3241
- result = { ...common, path: data.path, ...await patch(context, selected, work, this.scratchDirectory) };
3371
+ if (selected.entry.error !== void 0) {
3372
+ const error = selected.entry.error;
3373
+ fail3(
3374
+ work.partial && error.code === "DIFF_BLOCKED" ? "DIFF_FILE_BLOCKED" : error.code,
3375
+ `${data.path}: ${error.message}`
3376
+ );
3377
+ }
3378
+ const change = selected;
3379
+ result = {
3380
+ ...common,
3381
+ path: data.path,
3382
+ ...await forFile(data.path, work, () => patch(context, change, work, this.scratchDirectory))
3383
+ };
3384
+ }
3385
+ if (version < SESSION_GIT_DIFF_PARTIAL_VERSION) {
3386
+ const blocked = files.find(({ entry }) => entry.error !== void 0)?.entry;
3387
+ if (blocked?.error !== void 0) fail3(blocked.error.code, `${blocked.path}: ${blocked.error.message}`);
3242
3388
  }
3243
3389
  let latest;
3244
3390
  try {
@@ -3257,17 +3403,18 @@ var SessionGitDiffReader = class {
3257
3403
  }
3258
3404
  if (latest.repositoryIdentity !== context.repositoryIdentity || latest.baseRef !== context.baseRef || latest.baseCommit !== context.baseCommit) changed();
3259
3405
  if (selected !== void 0) {
3260
- const current = await readCurrent(
3406
+ const path = selected.entry.path;
3407
+ const current = await forFile(path, work, () => readCurrent(
3261
3408
  context.root,
3262
- selected.entry.path,
3409
+ path,
3263
3410
  context.baseCommit.length === 64 ? "sha256" : "sha1",
3264
3411
  work
3265
- );
3412
+ ));
3266
3413
  if (current?.rawOid !== selected.current?.rawOid || current?.mode !== selected.current?.mode) changed();
3267
3414
  }
3268
3415
  work.check();
3269
3416
  if (Buffer.byteLength(JSON.stringify(result), "utf8") > SESSION_GIT_DIFF_MAX_RESPONSE_BYTES) limit();
3270
- return SessionGitDiffResultDataSchema.parse(result);
3417
+ return (version >= SESSION_GIT_DIFF_PARTIAL_VERSION ? SessionGitDiffPartialResultDataSchema : SessionGitDiffResultDataSchema).parse(result);
3271
3418
  }
3272
3419
  };
3273
3420
 
@@ -3783,16 +3930,16 @@ function createCommunicationOperations(options) {
3783
3930
  ],
3784
3931
  ...options.incrementalOperations,
3785
3932
  ...adapter.getSessionDirectoryMetadata === void 0 ? [] : [
3786
- ...[SESSION_GIT_DIFF_VERSION, SESSION_GIT_DIFF_GZIP_VERSION].map((version) => sessionCommunicationOperation({
3933
+ ...[SESSION_GIT_DIFF_VERSION, SESSION_GIT_DIFF_GZIP_VERSION, SESSION_GIT_DIFF_PARTIAL_VERSION].map((version) => sessionCommunicationOperation({
3787
3934
  operation: SESSION_GIT_DIFF_OPERATION,
3788
3935
  version,
3789
3936
  schema: SessionGitDiffDataSchema,
3790
3937
  handle: async (data, request) => {
3791
3938
  const assertAccess = options.captureRequestAccess();
3792
3939
  assertAccess();
3793
- const result = await gitDiffReader.read(request.sessionId, data);
3940
+ const result = await gitDiffReader.read(request.sessionId, data, version);
3794
3941
  let response = SessionCommunicationDataSchema.parse(result);
3795
- if (version === SESSION_GIT_DIFF_GZIP_VERSION) {
3942
+ if (version >= SESSION_GIT_DIFF_GZIP_VERSION) {
3796
3943
  const bytes = Buffer.from(JSON.stringify(result), "utf8");
3797
3944
  if (bytes.length >= SESSION_GIT_DIFF_GZIP_MIN_BYTES) {
3798
3945
  response = SessionGitDiffGzipResultDataSchema.parse({
package/dist/runtime.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  PEER_CHAT_TIMEOUT_MS,
4
4
  PeerChatRequestSchema,
5
5
  PeerChatResultSchema
6
- } from "./chunks/chunk-M2QZ6EFR.js";
7
- import "./chunks/chunk-7QOBDG6R.js";
6
+ } from "./chunks/chunk-ZGO2OSQZ.js";
7
+ import "./chunks/chunk-W6TZVD7W.js";
8
8
  export {
9
9
  DataDirectoryLease,
10
10
  PEER_CHAT_TIMEOUT_MS,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentknight/sdk",
3
- "version": "0.9.43",
3
+ "version": "0.9.44",
4
4
  "description": "AgentKnight runtime SDK for local and remote coding sessions",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",