@mastra/code-sdk 1.0.3-alpha.0 → 1.1.0-alpha.2

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 (258) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/dist/acp/agent.js +155 -167
  3. package/dist/acp/agent.js.map +1 -1
  4. package/dist/acp/event-mapper.js +193 -168
  5. package/dist/acp/event-mapper.js.map +1 -1
  6. package/dist/acp/index.js +60 -49
  7. package/dist/acp/index.js.map +1 -1
  8. package/dist/acp/server.js +31 -30
  9. package/dist/acp/server.js.map +1 -1
  10. package/dist/acp.js +1 -4
  11. package/dist/agents/credential-resolver.js +40 -29
  12. package/dist/agents/credential-resolver.js.map +1 -1
  13. package/dist/agents/custom-provider-source.js +16 -9
  14. package/dist/agents/custom-provider-source.js.map +1 -1
  15. package/dist/agents/instructions.js +27 -36
  16. package/dist/agents/instructions.js.map +1 -1
  17. package/dist/agents/mastracode-gateway.js +355 -428
  18. package/dist/agents/mastracode-gateway.js.map +1 -1
  19. package/dist/agents/memory.js +87 -78
  20. package/dist/agents/memory.js.map +1 -1
  21. package/dist/agents/model.js +114 -119
  22. package/dist/agents/model.js.map +1 -1
  23. package/dist/agents/modes/build.js +12 -13
  24. package/dist/agents/modes/build.js.map +1 -1
  25. package/dist/agents/modes/explore.js +14 -13
  26. package/dist/agents/modes/explore.js.map +1 -1
  27. package/dist/agents/modes/plan.js +14 -15
  28. package/dist/agents/modes/plan.js.map +1 -1
  29. package/dist/agents/prompts/agent-instructions.js +78 -69
  30. package/dist/agents/prompts/agent-instructions.js.map +1 -1
  31. package/dist/agents/prompts/build.js +19 -16
  32. package/dist/agents/prompts/build.js.map +1 -1
  33. package/dist/agents/prompts/fast.js +8 -4
  34. package/dist/agents/prompts/fast.js.map +1 -1
  35. package/dist/agents/prompts/index.js +48 -47
  36. package/dist/agents/prompts/index.js.map +1 -1
  37. package/dist/agents/prompts/model.js +6 -5
  38. package/dist/agents/prompts/model.js.map +1 -1
  39. package/dist/agents/prompts/plan.js +20 -16
  40. package/dist/agents/prompts/plan.js.map +1 -1
  41. package/dist/agents/prompts/tool-guidance.js +77 -109
  42. package/dist/agents/prompts/tool-guidance.js.map +1 -1
  43. package/dist/agents/sandbox-filesystem.js +245 -259
  44. package/dist/agents/sandbox-filesystem.js.map +1 -1
  45. package/dist/agents/sandbox-reattach.js +9 -11
  46. package/dist/agents/sandbox-reattach.js.map +1 -1
  47. package/dist/agents/thread-caveman-state.js +92 -81
  48. package/dist/agents/thread-caveman-state.js.map +1 -1
  49. package/dist/agents/tool-availability.js +62 -80
  50. package/dist/agents/tool-availability.js.map +1 -1
  51. package/dist/agents/tools.js +99 -139
  52. package/dist/agents/tools.js.map +1 -1
  53. package/dist/agents/workspace.js +232 -225
  54. package/dist/agents/workspace.js.map +1 -1
  55. package/dist/analytics.js +139 -128
  56. package/dist/analytics.js.map +1 -1
  57. package/dist/auth/authorization-input.js +39 -25
  58. package/dist/auth/authorization-input.js.map +1 -1
  59. package/dist/auth/device-code.js +112 -80
  60. package/dist/auth/device-code.js.map +1 -1
  61. package/dist/auth/index.js +2 -9
  62. package/dist/auth/pkce.js +27 -16
  63. package/dist/auth/pkce.js.map +1 -1
  64. package/dist/auth/providers/anthropic.js +107 -93
  65. package/dist/auth/providers/anthropic.js.map +1 -1
  66. package/dist/auth/providers/github-copilot.js +304 -293
  67. package/dist/auth/providers/github-copilot.js.map +1 -1
  68. package/dist/auth/providers/openai-codex.js +442 -460
  69. package/dist/auth/providers/openai-codex.js.map +1 -1
  70. package/dist/auth/providers/xai.js +179 -145
  71. package/dist/auth/providers/xai.js.map +1 -1
  72. package/dist/auth/storage.js +182 -175
  73. package/dist/auth/storage.js.map +1 -1
  74. package/dist/auth/types.js +1 -1
  75. package/dist/clipboard/index.js +206 -172
  76. package/dist/clipboard/index.js.map +1 -1
  77. package/dist/constants.js +11 -16
  78. package/dist/constants.js.map +1 -1
  79. package/dist/error-classification.js +19 -11
  80. package/dist/error-classification.js.map +1 -1
  81. package/dist/evals/context-builder.js +145 -104
  82. package/dist/evals/context-builder.js.map +1 -1
  83. package/dist/evals/index.js +4 -7
  84. package/dist/evals/scorers/classify-command.js +62 -41
  85. package/dist/evals/scorers/classify-command.js.map +1 -1
  86. package/dist/evals/scorers/efficiency.js +239 -181
  87. package/dist/evals/scorers/efficiency.js.map +1 -1
  88. package/dist/evals/scorers/extract-tools.js +51 -47
  89. package/dist/evals/scorers/extract-tools.js.map +1 -1
  90. package/dist/evals/scorers/index.js +1 -5
  91. package/dist/evals/scorers/outcome.js +321 -212
  92. package/dist/evals/scorers/outcome.js.map +1 -1
  93. package/dist/goal-manager.js +266 -261
  94. package/dist/goal-manager.js.map +1 -1
  95. package/dist/goal-signal.js +14 -13
  96. package/dist/goal-signal.js.map +1 -1
  97. package/dist/headless/cli.js +153 -154
  98. package/dist/headless/cli.js.map +1 -1
  99. package/dist/headless/flags.js +180 -178
  100. package/dist/headless/flags.js.map +1 -1
  101. package/dist/headless/format.js +72 -71
  102. package/dist/headless/format.js.map +1 -1
  103. package/dist/headless/index.js +5 -31
  104. package/dist/headless/policy.js +35 -31
  105. package/dist/headless/policy.js.map +1 -1
  106. package/dist/headless/run-mc.js +332 -334
  107. package/dist/headless/run-mc.js.map +1 -1
  108. package/dist/headless/types.js +16 -7
  109. package/dist/headless/types.js.map +1 -1
  110. package/dist/hooks/config.js +56 -61
  111. package/dist/hooks/config.js.map +1 -1
  112. package/dist/hooks/executor.js +118 -116
  113. package/dist/hooks/executor.js.map +1 -1
  114. package/dist/hooks/index.js +4 -15
  115. package/dist/hooks/manager.js +221 -280
  116. package/dist/hooks/manager.js.map +1 -1
  117. package/dist/hooks/types.js +5 -4
  118. package/dist/hooks/types.js.map +1 -1
  119. package/dist/index.d.ts.map +1 -1
  120. package/dist/index.js +632 -712
  121. package/dist/index.js.map +1 -1
  122. package/dist/ipc/ipc-reporter.js +19 -22
  123. package/dist/ipc/ipc-reporter.js.map +1 -1
  124. package/dist/lsp/client.js +248 -306
  125. package/dist/lsp/client.js.map +1 -1
  126. package/dist/lsp/index.js +1 -6
  127. package/dist/lsp/language.js +39 -43
  128. package/dist/lsp/language.js.map +1 -1
  129. package/dist/lsp/manager.js +78 -93
  130. package/dist/lsp/manager.js.map +1 -1
  131. package/dist/lsp/server.js +151 -120
  132. package/dist/lsp/server.js.map +1 -1
  133. package/dist/lsp/workspace.js +50 -47
  134. package/dist/lsp/workspace.js.map +1 -1
  135. package/dist/mcp/config.js +210 -199
  136. package/dist/mcp/config.js.map +1 -1
  137. package/dist/mcp/index.js +2 -9
  138. package/dist/mcp/manager.js +482 -475
  139. package/dist/mcp/manager.js.map +1 -1
  140. package/dist/mcp/types.js +1 -1
  141. package/dist/onboarding/custom-packs.js +14 -17
  142. package/dist/onboarding/custom-packs.js.map +1 -1
  143. package/dist/onboarding/custom-providers.js +22 -20
  144. package/dist/onboarding/custom-providers.js.map +1 -1
  145. package/dist/onboarding/index.d.ts +1 -1
  146. package/dist/onboarding/index.d.ts.map +1 -1
  147. package/dist/onboarding/index.js +3 -21
  148. package/dist/onboarding/om-settings.d.ts +5 -0
  149. package/dist/onboarding/om-settings.d.ts.map +1 -1
  150. package/dist/onboarding/om-settings.js +41 -20
  151. package/dist/onboarding/om-settings.js.map +1 -1
  152. package/dist/onboarding/packs.d.ts +4 -6
  153. package/dist/onboarding/packs.d.ts.map +1 -1
  154. package/dist/onboarding/packs.js +154 -105
  155. package/dist/onboarding/packs.js.map +1 -1
  156. package/dist/onboarding/settings.js +575 -517
  157. package/dist/onboarding/settings.js.map +1 -1
  158. package/dist/permissions.js +112 -99
  159. package/dist/permissions.js.map +1 -1
  160. package/dist/plugin.js +21 -23
  161. package/dist/plugin.js.map +1 -1
  162. package/dist/plugins/dependencies.js +64 -87
  163. package/dist/plugins/dependencies.js.map +1 -1
  164. package/dist/plugins/install.js +159 -169
  165. package/dist/plugins/install.js.map +1 -1
  166. package/dist/plugins/loader.js +170 -185
  167. package/dist/plugins/loader.js.map +1 -1
  168. package/dist/plugins/manager.js +374 -380
  169. package/dist/plugins/manager.js.map +1 -1
  170. package/dist/plugins/manifest.js +38 -63
  171. package/dist/plugins/manifest.js.map +1 -1
  172. package/dist/plugins/package-link.js +48 -64
  173. package/dist/plugins/package-link.js.map +1 -1
  174. package/dist/plugins/paths.js +18 -19
  175. package/dist/plugins/paths.js.map +1 -1
  176. package/dist/plugins/registry.js +97 -81
  177. package/dist/plugins/registry.js.map +1 -1
  178. package/dist/plugins/scaffold.js +62 -98
  179. package/dist/plugins/scaffold.js.map +1 -1
  180. package/dist/plugins/types.js +1 -1
  181. package/dist/processors/plan-rejection-abort.js +45 -44
  182. package/dist/processors/plan-rejection-abort.js.map +1 -1
  183. package/dist/providers/amazon-bedrock-gateway.js +134 -125
  184. package/dist/providers/amazon-bedrock-gateway.js.map +1 -1
  185. package/dist/providers/amazon-bedrock.js +68 -47
  186. package/dist/providers/amazon-bedrock.js.map +1 -1
  187. package/dist/providers/claude-max.js +153 -133
  188. package/dist/providers/claude-max.js.map +1 -1
  189. package/dist/providers/github-copilot.js +232 -230
  190. package/dist/providers/github-copilot.js.map +1 -1
  191. package/dist/providers/openai-codex.js +271 -260
  192. package/dist/providers/openai-codex.js.map +1 -1
  193. package/dist/providers/xai.js +57 -50
  194. package/dist/providers/xai.js.map +1 -1
  195. package/dist/schema.js +91 -89
  196. package/dist/schema.js.map +1 -1
  197. package/dist/theme-palette.js +18 -14
  198. package/dist/theme-palette.js.map +1 -1
  199. package/dist/tool-names.js +46 -37
  200. package/dist/tool-names.js.map +1 -1
  201. package/dist/tools/index.js +2 -8
  202. package/dist/tools/request-sandbox-access.js +71 -80
  203. package/dist/tools/request-sandbox-access.js.map +1 -1
  204. package/dist/tools/utils.js +26 -16
  205. package/dist/tools/utils.js.map +1 -1
  206. package/dist/tools/web-search.js +51 -55
  207. package/dist/tools/web-search.js.map +1 -1
  208. package/dist/utils/binaries.js +65 -61
  209. package/dist/utils/binaries.js.map +1 -1
  210. package/dist/utils/debug-log.js +51 -47
  211. package/dist/utils/debug-log.js.map +1 -1
  212. package/dist/utils/errors.js +157 -192
  213. package/dist/utils/errors.js.map +1 -1
  214. package/dist/utils/gateway-sync.js +49 -37
  215. package/dist/utils/gateway-sync.js.map +1 -1
  216. package/dist/utils/path-security.js +7 -6
  217. package/dist/utils/path-security.js.map +1 -1
  218. package/dist/utils/plan-diff.js +58 -39
  219. package/dist/utils/plan-diff.js.map +1 -1
  220. package/dist/utils/plans.js +92 -74
  221. package/dist/utils/plans.js.map +1 -1
  222. package/dist/utils/project.js +318 -256
  223. package/dist/utils/project.js.map +1 -1
  224. package/dist/utils/signals-pubsub.js +117 -99
  225. package/dist/utils/signals-pubsub.js.map +1 -1
  226. package/dist/utils/slash-command-loader.js +118 -154
  227. package/dist/utils/slash-command-loader.js.map +1 -1
  228. package/dist/utils/slash-command-processor.js +92 -83
  229. package/dist/utils/slash-command-processor.js.map +1 -1
  230. package/dist/utils/stdin-pipe.js +87 -63
  231. package/dist/utils/stdin-pipe.js.map +1 -1
  232. package/dist/utils/storage-factory.js +104 -84
  233. package/dist/utils/storage-factory.js.map +1 -1
  234. package/dist/utils/storage-maintenance.js +249 -211
  235. package/dist/utils/storage-maintenance.js.map +1 -1
  236. package/dist/utils/thread-lock.js +96 -92
  237. package/dist/utils/thread-lock.js.map +1 -1
  238. package/dist/utils/token-estimator.js +12 -12
  239. package/dist/utils/token-estimator.js.map +1 -1
  240. package/dist/utils/update-check.d.ts +1 -1
  241. package/dist/utils/update-check.js +341 -259
  242. package/dist/utils/update-check.js.map +1 -1
  243. package/dist/voice/stt-registry.js +131 -113
  244. package/dist/voice/stt-registry.js.map +1 -1
  245. package/package.json +11 -11
  246. package/dist/acp.js.map +0 -1
  247. package/dist/auth/index.js.map +0 -1
  248. package/dist/auth/types.js.map +0 -1
  249. package/dist/evals/index.js.map +0 -1
  250. package/dist/evals/scorers/index.js.map +0 -1
  251. package/dist/headless/index.js.map +0 -1
  252. package/dist/hooks/index.js.map +0 -1
  253. package/dist/lsp/index.js.map +0 -1
  254. package/dist/mcp/index.js.map +0 -1
  255. package/dist/mcp/types.js.map +0 -1
  256. package/dist/onboarding/index.js.map +0 -1
  257. package/dist/plugins/types.js.map +0 -1
  258. package/dist/tools/index.js.map +0 -1
@@ -1,192 +1,226 @@
1
- import { execSync } from "node:child_process";
2
- import { readFileSync, unlinkSync } from "node:fs";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
1
+ import { readFileSync, unlinkSync } from "fs";
2
+ import { tmpdir } from "os";
3
+ import { join } from "path";
4
+ import { execSync } from "child_process";
5
+ //#region src/clipboard/index.ts
6
+ /**
7
+ * Platform-specific clipboard image extraction.
8
+ *
9
+ * Checks the system clipboard for image data and returns it as base64.
10
+ * Uses synchronous execution (execSync) since this only runs on paste events.
11
+ */
12
+ /**
13
+ * Read plain text from the system clipboard.
14
+ * Returns null if clipboard is empty or reading fails.
15
+ */
5
16
  function getClipboardText() {
6
- try {
7
- if (process.platform === "darwin") {
8
- const text = execSync("pbpaste", {
9
- encoding: "utf-8",
10
- timeout: 3e3,
11
- stdio: ["pipe", "pipe", "pipe"]
12
- });
13
- return text.length > 0 ? text : null;
14
- }
15
- if (process.platform === "linux") {
16
- try {
17
- const text = execSync("xclip -selection clipboard -o", {
18
- encoding: "utf-8",
19
- timeout: 3e3,
20
- stdio: ["pipe", "pipe", "pipe"]
21
- });
22
- return text.length > 0 ? text : null;
23
- } catch {
24
- const text = execSync("wl-paste", {
25
- encoding: "utf-8",
26
- timeout: 3e3,
27
- stdio: ["pipe", "pipe", "pipe"]
28
- });
29
- return text.length > 0 ? text : null;
30
- }
31
- }
32
- return null;
33
- } catch {
34
- return null;
35
- }
17
+ try {
18
+ if (process.platform === "darwin") {
19
+ const text = execSync("pbpaste", {
20
+ encoding: "utf-8",
21
+ timeout: 3e3,
22
+ stdio: [
23
+ "pipe",
24
+ "pipe",
25
+ "pipe"
26
+ ]
27
+ });
28
+ return text.length > 0 ? text : null;
29
+ }
30
+ if (process.platform === "linux") try {
31
+ const text = execSync("xclip -selection clipboard -o", {
32
+ encoding: "utf-8",
33
+ timeout: 3e3,
34
+ stdio: [
35
+ "pipe",
36
+ "pipe",
37
+ "pipe"
38
+ ]
39
+ });
40
+ return text.length > 0 ? text : null;
41
+ } catch {
42
+ const text = execSync("wl-paste", {
43
+ encoding: "utf-8",
44
+ timeout: 3e3,
45
+ stdio: [
46
+ "pipe",
47
+ "pipe",
48
+ "pipe"
49
+ ]
50
+ });
51
+ return text.length > 0 ? text : null;
52
+ }
53
+ return null;
54
+ } catch {
55
+ return null;
56
+ }
36
57
  }
58
+ /**
59
+ * Write plain text to the system clipboard.
60
+ * Returns true on success, false on failure.
61
+ */
37
62
  function setClipboardText(text) {
38
- try {
39
- if (process.platform === "darwin") {
40
- execSync("pbcopy", {
41
- input: text,
42
- timeout: 3e3,
43
- stdio: ["pipe", "pipe", "pipe"]
44
- });
45
- return true;
46
- }
47
- if (process.platform === "linux") {
48
- try {
49
- execSync("xclip -selection clipboard", {
50
- input: text,
51
- timeout: 3e3,
52
- stdio: ["pipe", "pipe", "pipe"]
53
- });
54
- return true;
55
- } catch {
56
- execSync("wl-copy", {
57
- input: text,
58
- timeout: 3e3,
59
- stdio: ["pipe", "pipe", "pipe"]
60
- });
61
- return true;
62
- }
63
- }
64
- return false;
65
- } catch {
66
- return false;
67
- }
63
+ try {
64
+ if (process.platform === "darwin") {
65
+ execSync("pbcopy", {
66
+ input: text,
67
+ timeout: 3e3,
68
+ stdio: [
69
+ "pipe",
70
+ "pipe",
71
+ "pipe"
72
+ ]
73
+ });
74
+ return true;
75
+ }
76
+ if (process.platform === "linux") try {
77
+ execSync("xclip -selection clipboard", {
78
+ input: text,
79
+ timeout: 3e3,
80
+ stdio: [
81
+ "pipe",
82
+ "pipe",
83
+ "pipe"
84
+ ]
85
+ });
86
+ return true;
87
+ } catch {
88
+ execSync("wl-copy", {
89
+ input: text,
90
+ timeout: 3e3,
91
+ stdio: [
92
+ "pipe",
93
+ "pipe",
94
+ "pipe"
95
+ ]
96
+ });
97
+ return true;
98
+ }
99
+ return false;
100
+ } catch {
101
+ return false;
102
+ }
68
103
  }
104
+ /**
105
+ * Check the system clipboard for image data and return it as base64.
106
+ * Returns null if no image data is found or extraction fails.
107
+ */
69
108
  function getClipboardImage() {
70
- try {
71
- if (process.platform === "darwin") {
72
- return getMacClipboardImage();
73
- }
74
- if (process.platform === "linux") {
75
- return getLinuxClipboardImage();
76
- }
77
- return null;
78
- } catch {
79
- return null;
80
- }
109
+ try {
110
+ if (process.platform === "darwin") return getMacClipboardImage();
111
+ if (process.platform === "linux") return getLinuxClipboardImage();
112
+ return null;
113
+ } catch {
114
+ return null;
115
+ }
81
116
  }
82
117
  function getMacClipboardImage() {
83
- return tryReadMacClipboardImage({
84
- coercion: "\xABclass PNGf\xBB",
85
- extension: "png",
86
- mimeType: "image/png"
87
- }) ?? tryReadMacClipboardImage({
88
- coercion: "TIFF picture",
89
- extension: "tiff",
90
- mimeType: "image/tiff"
91
- }) ?? tryReadMacClipboardImage({
92
- coercion: "\xABclass TIFF\xBB",
93
- extension: "tiff",
94
- mimeType: "image/tiff"
95
- });
118
+ return tryReadMacClipboardImage({
119
+ coercion: "«class PNGf»",
120
+ extension: "png",
121
+ mimeType: "image/png"
122
+ }) ?? tryReadMacClipboardImage({
123
+ coercion: "TIFF picture",
124
+ extension: "tiff",
125
+ mimeType: "image/tiff"
126
+ }) ?? tryReadMacClipboardImage({
127
+ coercion: "«class TIFF»",
128
+ extension: "tiff",
129
+ mimeType: "image/tiff"
130
+ });
96
131
  }
97
- function tryReadMacClipboardImage({
98
- coercion,
99
- extension,
100
- mimeType
101
- }) {
102
- const tmpFile = join(tmpdir(), `mastra-clipboard-${Date.now()}.${extension}`);
103
- try {
104
- const script = `
132
+ function tryReadMacClipboardImage({ coercion, extension, mimeType }) {
133
+ const tmpFile = join(tmpdir(), `mastra-clipboard-${Date.now()}.${extension}`);
134
+ try {
135
+ execSync(`osascript -e '${`
105
136
  set theImage to the clipboard as ${coercion}
106
137
  set theFile to open for access POSIX file "${tmpFile}" with write permission
107
138
  write theImage to theFile
108
139
  close access theFile
109
- `;
110
- execSync(`osascript -e '${script.replace(/'/g, "'\\''")}'`, {
111
- timeout: 5e3,
112
- stdio: ["pipe", "pipe", "pipe"]
113
- });
114
- const buffer = readFileSync(tmpFile);
115
- if (!Buffer.isBuffer(buffer) || buffer.length === 0) {
116
- return null;
117
- }
118
- return {
119
- data: buffer.toString("base64"),
120
- mimeType
121
- };
122
- } catch {
123
- return null;
124
- } finally {
125
- try {
126
- unlinkSync(tmpFile);
127
- } catch {
128
- }
129
- }
140
+ `.replace(/'/g, "'\\''")}'`, {
141
+ timeout: 5e3,
142
+ stdio: [
143
+ "pipe",
144
+ "pipe",
145
+ "pipe"
146
+ ]
147
+ });
148
+ const buffer = readFileSync(tmpFile);
149
+ if (!Buffer.isBuffer(buffer) || buffer.length === 0) return null;
150
+ return {
151
+ data: buffer.toString("base64"),
152
+ mimeType
153
+ };
154
+ } catch {
155
+ return null;
156
+ } finally {
157
+ try {
158
+ unlinkSync(tmpFile);
159
+ } catch {}
160
+ }
130
161
  }
131
162
  function getLinuxClipboardImage() {
132
- return getLinuxClipboardImageXclip() ?? getLinuxClipboardImageWlPaste();
163
+ return getLinuxClipboardImageXclip() ?? getLinuxClipboardImageWlPaste();
133
164
  }
134
165
  function getLinuxClipboardImageXclip() {
135
- try {
136
- const targets = execSync("xclip -selection clipboard -target TARGETS -o", {
137
- encoding: "utf-8",
138
- timeout: 3e3,
139
- stdio: ["pipe", "pipe", "pipe"]
140
- });
141
- if (!targets.includes("image/png")) {
142
- return null;
143
- }
144
- const buffer = execSync("xclip -selection clipboard -target image/png -o", {
145
- timeout: 5e3,
146
- stdio: ["pipe", "pipe", "pipe"],
147
- maxBuffer: 50 * 1024 * 1024
148
- // 50MB max
149
- });
150
- if (!Buffer.isBuffer(buffer) || buffer.length === 0) {
151
- return null;
152
- }
153
- return {
154
- data: buffer.toString("base64"),
155
- mimeType: "image/png"
156
- };
157
- } catch {
158
- return null;
159
- }
166
+ try {
167
+ if (!execSync("xclip -selection clipboard -target TARGETS -o", {
168
+ encoding: "utf-8",
169
+ timeout: 3e3,
170
+ stdio: [
171
+ "pipe",
172
+ "pipe",
173
+ "pipe"
174
+ ]
175
+ }).includes("image/png")) return null;
176
+ const buffer = execSync("xclip -selection clipboard -target image/png -o", {
177
+ timeout: 5e3,
178
+ stdio: [
179
+ "pipe",
180
+ "pipe",
181
+ "pipe"
182
+ ],
183
+ maxBuffer: 50 * 1024 * 1024
184
+ });
185
+ if (!Buffer.isBuffer(buffer) || buffer.length === 0) return null;
186
+ return {
187
+ data: buffer.toString("base64"),
188
+ mimeType: "image/png"
189
+ };
190
+ } catch {
191
+ return null;
192
+ }
160
193
  }
161
194
  function getLinuxClipboardImageWlPaste() {
162
- try {
163
- const types = execSync("wl-paste --list-types", {
164
- encoding: "utf-8",
165
- timeout: 3e3,
166
- stdio: ["pipe", "pipe", "pipe"]
167
- });
168
- if (!types.includes("image/png")) {
169
- return null;
170
- }
171
- const buffer = execSync("wl-paste --type image/png", {
172
- timeout: 5e3,
173
- stdio: ["pipe", "pipe", "pipe"],
174
- maxBuffer: 50 * 1024 * 1024
175
- });
176
- if (!Buffer.isBuffer(buffer) || buffer.length === 0) {
177
- return null;
178
- }
179
- return {
180
- data: buffer.toString("base64"),
181
- mimeType: "image/png"
182
- };
183
- } catch {
184
- return null;
185
- }
195
+ try {
196
+ if (!execSync("wl-paste --list-types", {
197
+ encoding: "utf-8",
198
+ timeout: 3e3,
199
+ stdio: [
200
+ "pipe",
201
+ "pipe",
202
+ "pipe"
203
+ ]
204
+ }).includes("image/png")) return null;
205
+ const buffer = execSync("wl-paste --type image/png", {
206
+ timeout: 5e3,
207
+ stdio: [
208
+ "pipe",
209
+ "pipe",
210
+ "pipe"
211
+ ],
212
+ maxBuffer: 50 * 1024 * 1024
213
+ });
214
+ if (!Buffer.isBuffer(buffer) || buffer.length === 0) return null;
215
+ return {
216
+ data: buffer.toString("base64"),
217
+ mimeType: "image/png"
218
+ };
219
+ } catch {
220
+ return null;
221
+ }
186
222
  }
187
- export {
188
- getClipboardImage,
189
- getClipboardText,
190
- setClipboardText
191
- };
223
+ //#endregion
224
+ export { getClipboardImage, getClipboardText, setClipboardText };
225
+
192
226
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/clipboard/index.ts"],"sourcesContent":["/**\n * Platform-specific clipboard image extraction.\n *\n * Checks the system clipboard for image data and returns it as base64.\n * Uses synchronous execution (execSync) since this only runs on paste events.\n */\n\nimport { execSync } from 'node:child_process';\nimport { readFileSync, unlinkSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\n\nexport interface ClipboardImage {\n data: string; // base64-encoded image data or a remote image URL\n mimeType: string;\n}\n\n/**\n * Read plain text from the system clipboard.\n * Returns null if clipboard is empty or reading fails.\n */\nexport function getClipboardText(): string | null {\n try {\n if (process.platform === 'darwin') {\n const text = execSync('pbpaste', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n }\n if (process.platform === 'linux') {\n // Try xclip first, then wl-paste\n try {\n const text = execSync('xclip -selection clipboard -o', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n } catch {\n const text = execSync('wl-paste', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Write plain text to the system clipboard.\n * Returns true on success, false on failure.\n */\nexport function setClipboardText(text: string): boolean {\n try {\n if (process.platform === 'darwin') {\n execSync('pbcopy', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n }\n if (process.platform === 'linux') {\n try {\n execSync('xclip -selection clipboard', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n } catch {\n execSync('wl-copy', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Check the system clipboard for image data and return it as base64.\n * Returns null if no image data is found or extraction fails.\n */\nexport function getClipboardImage(): ClipboardImage | null {\n try {\n if (process.platform === 'darwin') {\n return getMacClipboardImage();\n }\n if (process.platform === 'linux') {\n return getLinuxClipboardImage();\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// macOS\n// =============================================================================\n\nfunction getMacClipboardImage(): ClipboardImage | null {\n return (\n tryReadMacClipboardImage({\n coercion: '«class PNGf»',\n extension: 'png',\n mimeType: 'image/png',\n }) ??\n tryReadMacClipboardImage({\n coercion: 'TIFF picture',\n extension: 'tiff',\n mimeType: 'image/tiff',\n }) ??\n tryReadMacClipboardImage({\n coercion: '«class TIFF»',\n extension: 'tiff',\n mimeType: 'image/tiff',\n })\n );\n}\n\nfunction tryReadMacClipboardImage({\n coercion,\n extension,\n mimeType,\n}: {\n coercion: string;\n extension: string;\n mimeType: string;\n}): ClipboardImage | null {\n const tmpFile = join(tmpdir(), `mastra-clipboard-${Date.now()}.${extension}`);\n\n try {\n const script = `\n\t\t\tset theImage to the clipboard as ${coercion}\n\t\t\tset theFile to open for access POSIX file \"${tmpFile}\" with write permission\n\t\t\twrite theImage to theFile\n\t\t\tclose access theFile\n\t\t`;\n execSync(`osascript -e '${script.replace(/'/g, \"'\\\\''\")}'`, {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const buffer = readFileSync(tmpFile);\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType,\n };\n } catch {\n return null;\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n // ignore cleanup errors\n }\n }\n}\n\n// =============================================================================\n// Linux\n// =============================================================================\n\nfunction getLinuxClipboardImage(): ClipboardImage | null {\n // Try xclip first, then wl-paste (Wayland)\n return getLinuxClipboardImageXclip() ?? getLinuxClipboardImageWlPaste();\n}\n\nfunction getLinuxClipboardImageXclip(): ClipboardImage | null {\n try {\n // Check available targets\n const targets = execSync('xclip -selection clipboard -target TARGETS -o', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!targets.includes('image/png')) {\n return null;\n }\n\n // Extract PNG data\n const buffer = execSync('xclip -selection clipboard -target image/png -o', {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n maxBuffer: 50 * 1024 * 1024, // 50MB max\n });\n\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType: 'image/png',\n };\n } catch {\n return null;\n }\n}\n\nfunction getLinuxClipboardImageWlPaste(): ClipboardImage | null {\n try {\n // Check if wl-paste is available and clipboard has image\n const types = execSync('wl-paste --list-types', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!types.includes('image/png')) {\n return null;\n }\n\n // Extract PNG data\n const buffer = execSync('wl-paste --type image/png', {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n maxBuffer: 50 * 1024 * 1024,\n });\n\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType: 'image/png',\n };\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/clipboard/index.ts"],"sourcesContent":["/**\n * Platform-specific clipboard image extraction.\n *\n * Checks the system clipboard for image data and returns it as base64.\n * Uses synchronous execution (execSync) since this only runs on paste events.\n */\n\nimport { execSync } from 'node:child_process';\nimport { readFileSync, unlinkSync } from 'node:fs';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\n\nexport interface ClipboardImage {\n data: string; // base64-encoded image data or a remote image URL\n mimeType: string;\n}\n\n/**\n * Read plain text from the system clipboard.\n * Returns null if clipboard is empty or reading fails.\n */\nexport function getClipboardText(): string | null {\n try {\n if (process.platform === 'darwin') {\n const text = execSync('pbpaste', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n }\n if (process.platform === 'linux') {\n // Try xclip first, then wl-paste\n try {\n const text = execSync('xclip -selection clipboard -o', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n } catch {\n const text = execSync('wl-paste', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return text.length > 0 ? text : null;\n }\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/**\n * Write plain text to the system clipboard.\n * Returns true on success, false on failure.\n */\nexport function setClipboardText(text: string): boolean {\n try {\n if (process.platform === 'darwin') {\n execSync('pbcopy', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n }\n if (process.platform === 'linux') {\n try {\n execSync('xclip -selection clipboard', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n } catch {\n execSync('wl-copy', {\n input: text,\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n return true;\n }\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Check the system clipboard for image data and return it as base64.\n * Returns null if no image data is found or extraction fails.\n */\nexport function getClipboardImage(): ClipboardImage | null {\n try {\n if (process.platform === 'darwin') {\n return getMacClipboardImage();\n }\n if (process.platform === 'linux') {\n return getLinuxClipboardImage();\n }\n return null;\n } catch {\n return null;\n }\n}\n\n// =============================================================================\n// macOS\n// =============================================================================\n\nfunction getMacClipboardImage(): ClipboardImage | null {\n return (\n tryReadMacClipboardImage({\n coercion: '«class PNGf»',\n extension: 'png',\n mimeType: 'image/png',\n }) ??\n tryReadMacClipboardImage({\n coercion: 'TIFF picture',\n extension: 'tiff',\n mimeType: 'image/tiff',\n }) ??\n tryReadMacClipboardImage({\n coercion: '«class TIFF»',\n extension: 'tiff',\n mimeType: 'image/tiff',\n })\n );\n}\n\nfunction tryReadMacClipboardImage({\n coercion,\n extension,\n mimeType,\n}: {\n coercion: string;\n extension: string;\n mimeType: string;\n}): ClipboardImage | null {\n const tmpFile = join(tmpdir(), `mastra-clipboard-${Date.now()}.${extension}`);\n\n try {\n const script = `\n\t\t\tset theImage to the clipboard as ${coercion}\n\t\t\tset theFile to open for access POSIX file \"${tmpFile}\" with write permission\n\t\t\twrite theImage to theFile\n\t\t\tclose access theFile\n\t\t`;\n execSync(`osascript -e '${script.replace(/'/g, \"'\\\\''\")}'`, {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n const buffer = readFileSync(tmpFile);\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType,\n };\n } catch {\n return null;\n } finally {\n try {\n unlinkSync(tmpFile);\n } catch {\n // ignore cleanup errors\n }\n }\n}\n\n// =============================================================================\n// Linux\n// =============================================================================\n\nfunction getLinuxClipboardImage(): ClipboardImage | null {\n // Try xclip first, then wl-paste (Wayland)\n return getLinuxClipboardImageXclip() ?? getLinuxClipboardImageWlPaste();\n}\n\nfunction getLinuxClipboardImageXclip(): ClipboardImage | null {\n try {\n // Check available targets\n const targets = execSync('xclip -selection clipboard -target TARGETS -o', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!targets.includes('image/png')) {\n return null;\n }\n\n // Extract PNG data\n const buffer = execSync('xclip -selection clipboard -target image/png -o', {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n maxBuffer: 50 * 1024 * 1024, // 50MB max\n });\n\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType: 'image/png',\n };\n } catch {\n return null;\n }\n}\n\nfunction getLinuxClipboardImageWlPaste(): ClipboardImage | null {\n try {\n // Check if wl-paste is available and clipboard has image\n const types = execSync('wl-paste --list-types', {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n });\n\n if (!types.includes('image/png')) {\n return null;\n }\n\n // Extract PNG data\n const buffer = execSync('wl-paste --type image/png', {\n timeout: 5000,\n stdio: ['pipe', 'pipe', 'pipe'],\n maxBuffer: 50 * 1024 * 1024,\n });\n\n if (!Buffer.isBuffer(buffer) || buffer.length === 0) {\n return null;\n }\n\n return {\n data: buffer.toString('base64'),\n mimeType: 'image/png',\n };\n } catch {\n return null;\n }\n}\n"],"mappings":"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"}
package/dist/constants.js CHANGED
@@ -1,23 +1,18 @@
1
- import * as path from "node:path";
1
+ import * as path$1 from "path";
2
+ //#region src/constants.ts
2
3
  const DEFAULT_CONFIG_DIR = ".mastracode";
4
+ /**
5
+ * Validate that a configDirName is a safe single directory name.
6
+ * Rejects absolute paths, path separators, and traversal components.
7
+ */
3
8
  function validateConfigDirName(configDirName) {
4
- if (configDirName.trim().length === 0) {
5
- throw new Error("configDirName must be a non-empty directory name");
6
- }
7
- if (path.isAbsolute(configDirName) || configDirName.includes("/") || configDirName.includes("\\") || configDirName === ".." || configDirName === ".") {
8
- throw new Error(
9
- `configDirName must be a single directory name without path separators or traversal components, got: "${configDirName}"`
10
- );
11
- }
9
+ if (configDirName.trim().length === 0) throw new Error("configDirName must be a non-empty directory name");
10
+ if (path$1.isAbsolute(configDirName) || configDirName.includes("/") || configDirName.includes("\\") || configDirName === ".." || configDirName === ".") throw new Error(`configDirName must be a single directory name without path separators or traversal components, got: "${configDirName}"`);
12
11
  }
13
12
  const DEFAULT_OM_MODEL_ID = process.env.DEFAULT_OM_MODEL_ID ?? "google/gemini-3.5-flash";
14
13
  const DEFAULT_OBS_THRESHOLD = 3e4;
15
14
  const DEFAULT_REF_THRESHOLD = 4e4;
16
- export {
17
- DEFAULT_CONFIG_DIR,
18
- DEFAULT_OBS_THRESHOLD,
19
- DEFAULT_OM_MODEL_ID,
20
- DEFAULT_REF_THRESHOLD,
21
- validateConfigDirName
22
- };
15
+ //#endregion
16
+ export { DEFAULT_CONFIG_DIR, DEFAULT_OBS_THRESHOLD, DEFAULT_OM_MODEL_ID, DEFAULT_REF_THRESHOLD, validateConfigDirName };
17
+
23
18
  //# sourceMappingURL=constants.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import * as path from 'node:path';\n\n// Default config directory name used for all project-level and global config paths.\nexport const DEFAULT_CONFIG_DIR = '.mastracode';\n\n/**\n * Validate that a configDirName is a safe single directory name.\n * Rejects absolute paths, path separators, and traversal components.\n */\nexport function validateConfigDirName(configDirName: string): void {\n if (configDirName.trim().length === 0) {\n throw new Error('configDirName must be a non-empty directory name');\n }\n\n if (\n path.isAbsolute(configDirName) ||\n configDirName.includes('/') ||\n configDirName.includes('\\\\') ||\n configDirName === '..' ||\n configDirName === '.'\n ) {\n throw new Error(\n `configDirName must be a single directory name without path separators or traversal components, got: \"${configDirName}\"`,\n );\n }\n}\n\n// Default OM model - using gemini-3.5-flash for efficiency\nexport const DEFAULT_OM_MODEL_ID = process.env.DEFAULT_OM_MODEL_ID ?? 'google/gemini-3.5-flash';\n\n// Default OM thresholds — per-thread overrides are loaded from thread metadata\nexport const DEFAULT_OBS_THRESHOLD = 30_000;\nexport const DEFAULT_REF_THRESHOLD = 40_000;\n"],"mappings":"AAAA,YAAY,UAAU;AAGf,MAAM,qBAAqB;AAM3B,SAAS,sBAAsB,eAA6B;AACjE,MAAI,cAAc,KAAK,EAAE,WAAW,GAAG;AACrC,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AAEA,MACE,KAAK,WAAW,aAAa,KAC7B,cAAc,SAAS,GAAG,KAC1B,cAAc,SAAS,IAAI,KAC3B,kBAAkB,QAClB,kBAAkB,KAClB;AACA,UAAM,IAAI;AAAA,MACR,wGAAwG,aAAa;AAAA,IACvH;AAAA,EACF;AACF;AAGO,MAAM,sBAAsB,QAAQ,IAAI,uBAAuB;AAG/D,MAAM,wBAAwB;AAC9B,MAAM,wBAAwB;","names":[]}
1
+ {"version":3,"file":"constants.js","names":["path"],"sources":["../src/constants.ts"],"sourcesContent":["import * as path from 'node:path';\n\n// Default config directory name used for all project-level and global config paths.\nexport const DEFAULT_CONFIG_DIR = '.mastracode';\n\n/**\n * Validate that a configDirName is a safe single directory name.\n * Rejects absolute paths, path separators, and traversal components.\n */\nexport function validateConfigDirName(configDirName: string): void {\n if (configDirName.trim().length === 0) {\n throw new Error('configDirName must be a non-empty directory name');\n }\n\n if (\n path.isAbsolute(configDirName) ||\n configDirName.includes('/') ||\n configDirName.includes('\\\\') ||\n configDirName === '..' ||\n configDirName === '.'\n ) {\n throw new Error(\n `configDirName must be a single directory name without path separators or traversal components, got: \"${configDirName}\"`,\n );\n }\n}\n\n// Default OM model - using gemini-3.5-flash for efficiency\nexport const DEFAULT_OM_MODEL_ID = process.env.DEFAULT_OM_MODEL_ID ?? 'google/gemini-3.5-flash';\n\n// Default OM thresholds — per-thread overrides are loaded from thread metadata\nexport const DEFAULT_OBS_THRESHOLD = 30_000;\nexport const DEFAULT_REF_THRESHOLD = 40_000;\n"],"mappings":";;AAGA,MAAa,qBAAqB;;;;;AAMlC,SAAgB,sBAAsB,eAA6B;CACjE,IAAI,cAAc,KAAK,CAAC,CAAC,WAAW,GAClC,MAAM,IAAI,MAAM,kDAAkD;CAGpE,IACEA,OAAK,WAAW,aAAa,KAC7B,cAAc,SAAS,GAAG,KAC1B,cAAc,SAAS,IAAI,KAC3B,kBAAkB,QAClB,kBAAkB,KAElB,MAAM,IAAI,MACR,wGAAwG,cAAc,EACxH;AAEJ;AAGA,MAAa,sBAAsB,QAAQ,IAAI,uBAAuB;AAGtE,MAAa,wBAAwB;AACrC,MAAa,wBAAwB"}
@@ -1,14 +1,22 @@
1
+ //#region src/error-classification.ts
2
+ /**
3
+ * Checks whether an error is an ERR_STREAM_DESTROYED error, which is a
4
+ * non-fatal condition that occurs when code writes to a stream after it
5
+ * has been closed (e.g., client disconnect, cancelled LLM stream, LSP
6
+ * shutdown, killed subprocess).
7
+ *
8
+ * Walks the `.cause` chain up to a depth limit.
9
+ */
1
10
  function isStreamDestroyedError(err, depth = 0) {
2
- if (!err || depth > 5) return false;
3
- const e = err;
4
- if (e.code === "ERR_STREAM_DESTROYED") return true;
5
- if (typeof e.message === "string" && e.message.includes("stream was destroyed")) return true;
6
- if (e.cause && isStreamDestroyedError(e.cause, depth + 1)) return true;
7
- if (Array.isArray(e.errors) && e.errors.some((inner) => isStreamDestroyedError(inner, depth + 1)))
8
- return true;
9
- return false;
11
+ if (!err || depth > 5) return false;
12
+ const e = err;
13
+ if (e.code === "ERR_STREAM_DESTROYED") return true;
14
+ if (typeof e.message === "string" && e.message.includes("stream was destroyed")) return true;
15
+ if (e.cause && isStreamDestroyedError(e.cause, depth + 1)) return true;
16
+ if (Array.isArray(e.errors) && e.errors.some((inner) => isStreamDestroyedError(inner, depth + 1))) return true;
17
+ return false;
10
18
  }
11
- export {
12
- isStreamDestroyedError
13
- };
19
+ //#endregion
20
+ export { isStreamDestroyedError };
21
+
14
22
  //# sourceMappingURL=error-classification.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/error-classification.ts"],"sourcesContent":["/**\n * Checks whether an error is an ERR_STREAM_DESTROYED error, which is a\n * non-fatal condition that occurs when code writes to a stream after it\n * has been closed (e.g., client disconnect, cancelled LLM stream, LSP\n * shutdown, killed subprocess).\n *\n * Walks the `.cause` chain up to a depth limit.\n */\nexport function isStreamDestroyedError(err: unknown, depth = 0): boolean {\n if (!err || depth > 5) return false;\n const e = err as any;\n if (e.code === 'ERR_STREAM_DESTROYED') return true;\n if (typeof e.message === 'string' && e.message.includes('stream was destroyed')) return true;\n if (e.cause && isStreamDestroyedError(e.cause, depth + 1)) return true;\n if (Array.isArray(e.errors) && e.errors.some((inner: unknown) => isStreamDestroyedError(inner, depth + 1)))\n return true;\n return false;\n}\n"],"mappings":"AAQO,SAAS,uBAAuB,KAAc,QAAQ,GAAY;AACvE,MAAI,CAAC,OAAO,QAAQ,EAAG,QAAO;AAC9B,QAAM,IAAI;AACV,MAAI,EAAE,SAAS,uBAAwB,QAAO;AAC9C,MAAI,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,SAAS,sBAAsB,EAAG,QAAO;AACxF,MAAI,EAAE,SAAS,uBAAuB,EAAE,OAAO,QAAQ,CAAC,EAAG,QAAO;AAClE,MAAI,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,KAAK,CAAC,UAAmB,uBAAuB,OAAO,QAAQ,CAAC,CAAC;AACvG,WAAO;AACT,SAAO;AACT;","names":[]}
1
+ {"version":3,"file":"error-classification.js","names":[],"sources":["../src/error-classification.ts"],"sourcesContent":["/**\n * Checks whether an error is an ERR_STREAM_DESTROYED error, which is a\n * non-fatal condition that occurs when code writes to a stream after it\n * has been closed (e.g., client disconnect, cancelled LLM stream, LSP\n * shutdown, killed subprocess).\n *\n * Walks the `.cause` chain up to a depth limit.\n */\nexport function isStreamDestroyedError(err: unknown, depth = 0): boolean {\n if (!err || depth > 5) return false;\n const e = err as any;\n if (e.code === 'ERR_STREAM_DESTROYED') return true;\n if (typeof e.message === 'string' && e.message.includes('stream was destroyed')) return true;\n if (e.cause && isStreamDestroyedError(e.cause, depth + 1)) return true;\n if (Array.isArray(e.errors) && e.errors.some((inner: unknown) => isStreamDestroyedError(inner, depth + 1)))\n return true;\n return false;\n}\n"],"mappings":";;;;;;;;;AAQA,SAAgB,uBAAuB,KAAc,QAAQ,GAAY;CACvE,IAAI,CAAC,OAAO,QAAQ,GAAG,OAAO;CAC9B,MAAM,IAAI;CACV,IAAI,EAAE,SAAS,wBAAwB,OAAO;CAC9C,IAAI,OAAO,EAAE,YAAY,YAAY,EAAE,QAAQ,SAAS,sBAAsB,GAAG,OAAO;CACxF,IAAI,EAAE,SAAS,uBAAuB,EAAE,OAAO,QAAQ,CAAC,GAAG,OAAO;CAClE,IAAI,MAAM,QAAQ,EAAE,MAAM,KAAK,EAAE,OAAO,MAAM,UAAmB,uBAAuB,OAAO,QAAQ,CAAC,CAAC,GACvG,OAAO;CACT,OAAO;AACT"}