@tickernelz/paperclip-pro-adapter-claude-local 2026.925.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (206) hide show
  1. package/LICENSE +22 -0
  2. package/dist/cli/format-event.d.ts +2 -0
  3. package/dist/cli/format-event.d.ts.map +1 -0
  4. package/dist/cli/format-event.js +141 -0
  5. package/dist/cli/format-event.js.map +1 -0
  6. package/dist/cli/index.d.ts +2 -0
  7. package/dist/cli/index.d.ts.map +1 -0
  8. package/dist/cli/index.js +2 -0
  9. package/dist/cli/index.js.map +1 -0
  10. package/dist/cli/quota-probe.d.ts +3 -0
  11. package/dist/cli/quota-probe.d.ts.map +1 -0
  12. package/dist/cli/quota-probe.js +106 -0
  13. package/dist/cli/quota-probe.js.map +1 -0
  14. package/dist/index.d.ts +13 -0
  15. package/dist/index.d.ts.map +1 -0
  16. package/dist/index.js +90 -0
  17. package/dist/index.js.map +1 -0
  18. package/dist/index.test.d.ts +2 -0
  19. package/dist/index.test.d.ts.map +1 -0
  20. package/dist/index.test.js +35 -0
  21. package/dist/index.test.js.map +1 -0
  22. package/dist/server/acp.auth.test.d.ts +2 -0
  23. package/dist/server/acp.auth.test.d.ts.map +1 -0
  24. package/dist/server/acp.auth.test.js +581 -0
  25. package/dist/server/acp.auth.test.js.map +1 -0
  26. package/dist/server/acp.d.ts +68 -0
  27. package/dist/server/acp.d.ts.map +1 -0
  28. package/dist/server/acp.js +779 -0
  29. package/dist/server/acp.js.map +1 -0
  30. package/dist/server/acp.quota.test.d.ts +2 -0
  31. package/dist/server/acp.quota.test.d.ts.map +1 -0
  32. package/dist/server/acp.quota.test.js +114 -0
  33. package/dist/server/acp.quota.test.js.map +1 -0
  34. package/dist/server/acp.test.d.ts +2 -0
  35. package/dist/server/acp.test.d.ts.map +1 -0
  36. package/dist/server/acp.test.js +1153 -0
  37. package/dist/server/acp.test.js.map +1 -0
  38. package/dist/server/auth-check.d.ts +8 -0
  39. package/dist/server/auth-check.d.ts.map +1 -0
  40. package/dist/server/auth-check.js +8 -0
  41. package/dist/server/auth-check.js.map +1 -0
  42. package/dist/server/claude-config.d.ts +49 -0
  43. package/dist/server/claude-config.d.ts.map +1 -0
  44. package/dist/server/claude-config.js +279 -0
  45. package/dist/server/claude-config.js.map +1 -0
  46. package/dist/server/claude-config.test.d.ts +2 -0
  47. package/dist/server/claude-config.test.d.ts.map +1 -0
  48. package/dist/server/claude-config.test.js +197 -0
  49. package/dist/server/claude-config.test.js.map +1 -0
  50. package/dist/server/cli-capabilities.d.ts +26 -0
  51. package/dist/server/cli-capabilities.d.ts.map +1 -0
  52. package/dist/server/cli-capabilities.js +115 -0
  53. package/dist/server/cli-capabilities.js.map +1 -0
  54. package/dist/server/config-schema.d.ts +3 -0
  55. package/dist/server/config-schema.d.ts.map +1 -0
  56. package/dist/server/config-schema.js +67 -0
  57. package/dist/server/config-schema.js.map +1 -0
  58. package/dist/server/engine-availability.test.d.ts +2 -0
  59. package/dist/server/engine-availability.test.d.ts.map +1 -0
  60. package/dist/server/engine-availability.test.js +41 -0
  61. package/dist/server/engine-availability.test.js.map +1 -0
  62. package/dist/server/execute.acp-fallback.test.d.ts +2 -0
  63. package/dist/server/execute.acp-fallback.test.d.ts.map +1 -0
  64. package/dist/server/execute.acp-fallback.test.js +104 -0
  65. package/dist/server/execute.acp-fallback.test.js.map +1 -0
  66. package/dist/server/execute.d.ts +23 -0
  67. package/dist/server/execute.d.ts.map +1 -0
  68. package/dist/server/execute.js +1089 -0
  69. package/dist/server/execute.js.map +1 -0
  70. package/dist/server/execute.remote.test.d.ts +2 -0
  71. package/dist/server/execute.remote.test.d.ts.map +1 -0
  72. package/dist/server/execute.remote.test.js +484 -0
  73. package/dist/server/execute.remote.test.js.map +1 -0
  74. package/dist/server/index.d.ts +16 -0
  75. package/dist/server/index.d.ts.map +1 -0
  76. package/dist/server/index.js +84 -0
  77. package/dist/server/index.js.map +1 -0
  78. package/dist/server/models.d.ts +13 -0
  79. package/dist/server/models.d.ts.map +1 -0
  80. package/dist/server/models.js +153 -0
  81. package/dist/server/models.js.map +1 -0
  82. package/dist/server/parse.d.ts +58 -0
  83. package/dist/server/parse.d.ts.map +1 -0
  84. package/dist/server/parse.js +459 -0
  85. package/dist/server/parse.js.map +1 -0
  86. package/dist/server/parse.test.d.ts +2 -0
  87. package/dist/server/parse.test.d.ts.map +1 -0
  88. package/dist/server/parse.test.js +419 -0
  89. package/dist/server/parse.test.js.map +1 -0
  90. package/dist/server/permissions.d.ts +14 -0
  91. package/dist/server/permissions.d.ts.map +1 -0
  92. package/dist/server/permissions.js +13 -0
  93. package/dist/server/permissions.js.map +1 -0
  94. package/dist/server/permissions.test.d.ts +2 -0
  95. package/dist/server/permissions.test.d.ts.map +1 -0
  96. package/dist/server/permissions.test.js +22 -0
  97. package/dist/server/permissions.test.js.map +1 -0
  98. package/dist/server/probe-diagnostics.d.ts +102 -0
  99. package/dist/server/probe-diagnostics.d.ts.map +1 -0
  100. package/dist/server/probe-diagnostics.js +140 -0
  101. package/dist/server/probe-diagnostics.js.map +1 -0
  102. package/dist/server/probe-diagnostics.test.d.ts +2 -0
  103. package/dist/server/probe-diagnostics.test.d.ts.map +1 -0
  104. package/dist/server/probe-diagnostics.test.js +114 -0
  105. package/dist/server/probe-diagnostics.test.js.map +1 -0
  106. package/dist/server/probe-env.d.ts +42 -0
  107. package/dist/server/probe-env.d.ts.map +1 -0
  108. package/dist/server/probe-env.js +149 -0
  109. package/dist/server/probe-env.js.map +1 -0
  110. package/dist/server/probe-env.test.d.ts +2 -0
  111. package/dist/server/probe-env.test.d.ts.map +1 -0
  112. package/dist/server/probe-env.test.js +135 -0
  113. package/dist/server/probe-env.test.js.map +1 -0
  114. package/dist/server/probe-redaction.test.d.ts +2 -0
  115. package/dist/server/probe-redaction.test.d.ts.map +1 -0
  116. package/dist/server/probe-redaction.test.js +86 -0
  117. package/dist/server/probe-redaction.test.js.map +1 -0
  118. package/dist/server/prompt-cache.d.ts +17 -0
  119. package/dist/server/prompt-cache.d.ts.map +1 -0
  120. package/dist/server/prompt-cache.js +126 -0
  121. package/dist/server/prompt-cache.js.map +1 -0
  122. package/dist/server/quota-keychain.test.d.ts +2 -0
  123. package/dist/server/quota-keychain.test.d.ts.map +1 -0
  124. package/dist/server/quota-keychain.test.js +83 -0
  125. package/dist/server/quota-keychain.test.js.map +1 -0
  126. package/dist/server/quota.d.ts +30 -0
  127. package/dist/server/quota.d.ts.map +1 -0
  128. package/dist/server/quota.js +543 -0
  129. package/dist/server/quota.js.map +1 -0
  130. package/dist/server/setup-token-characterization.test.d.ts +2 -0
  131. package/dist/server/setup-token-characterization.test.d.ts.map +1 -0
  132. package/dist/server/setup-token-characterization.test.js +123 -0
  133. package/dist/server/setup-token-characterization.test.js.map +1 -0
  134. package/dist/server/setup-token-parse.d.ts +47 -0
  135. package/dist/server/setup-token-parse.d.ts.map +1 -0
  136. package/dist/server/setup-token-parse.js +506 -0
  137. package/dist/server/setup-token-parse.js.map +1 -0
  138. package/dist/server/setup-token-parse.test.d.ts +2 -0
  139. package/dist/server/setup-token-parse.test.d.ts.map +1 -0
  140. package/dist/server/setup-token-parse.test.js +587 -0
  141. package/dist/server/setup-token-parse.test.js.map +1 -0
  142. package/dist/server/setup-token-runner.d.ts +115 -0
  143. package/dist/server/setup-token-runner.d.ts.map +1 -0
  144. package/dist/server/setup-token-runner.js +317 -0
  145. package/dist/server/setup-token-runner.js.map +1 -0
  146. package/dist/server/setup-token-runner.test.d.ts +2 -0
  147. package/dist/server/setup-token-runner.test.d.ts.map +1 -0
  148. package/dist/server/setup-token-runner.test.js +336 -0
  149. package/dist/server/setup-token-runner.test.js.map +1 -0
  150. package/dist/server/skills.d.ts +8 -0
  151. package/dist/server/skills.d.ts.map +1 -0
  152. package/dist/server/skills.js +42 -0
  153. package/dist/server/skills.js.map +1 -0
  154. package/dist/server/test.d.ts +3 -0
  155. package/dist/server/test.d.ts.map +1 -0
  156. package/dist/server/test.js +434 -0
  157. package/dist/server/test.js.map +1 -0
  158. package/dist/server/test.probe.test.d.ts +2 -0
  159. package/dist/server/test.probe.test.d.ts.map +1 -0
  160. package/dist/server/test.probe.test.js +608 -0
  161. package/dist/server/test.probe.test.js.map +1 -0
  162. package/dist/server/test.remote.test.d.ts +2 -0
  163. package/dist/server/test.remote.test.d.ts.map +1 -0
  164. package/dist/server/test.remote.test.js +149 -0
  165. package/dist/server/test.remote.test.js.map +1 -0
  166. package/dist/ui/build-config.d.ts +3 -0
  167. package/dist/ui/build-config.d.ts.map +1 -0
  168. package/dist/ui/build-config.js +76 -0
  169. package/dist/ui/build-config.js.map +1 -0
  170. package/dist/ui/build-config.test.d.ts +2 -0
  171. package/dist/ui/build-config.test.d.ts.map +1 -0
  172. package/dist/ui/build-config.test.js +68 -0
  173. package/dist/ui/build-config.test.js.map +1 -0
  174. package/dist/ui/index.d.ts +3 -0
  175. package/dist/ui/index.d.ts.map +1 -0
  176. package/dist/ui/index.js +3 -0
  177. package/dist/ui/index.js.map +1 -0
  178. package/dist/ui/parse-stdout.d.ts +3 -0
  179. package/dist/ui/parse-stdout.d.ts.map +1 -0
  180. package/dist/ui/parse-stdout.js +153 -0
  181. package/dist/ui/parse-stdout.js.map +1 -0
  182. package/package.json +63 -0
  183. package/skills/agentmail/SKILL.md +70 -0
  184. package/skills/paperclip/SKILL.md +712 -0
  185. package/skills/paperclip/references/api-reference.md +1675 -0
  186. package/skills/paperclip/references/artifacts.md +158 -0
  187. package/skills/paperclip/references/cases.md +295 -0
  188. package/skills/paperclip/references/company-skills.md +266 -0
  189. package/skills/paperclip/references/issue-workspaces.md +80 -0
  190. package/skills/paperclip/references/routines.md +231 -0
  191. package/skills/paperclip/references/workflows.md +141 -0
  192. package/skills/paperclip/scripts/paperclip-upload-artifact.sh +592 -0
  193. package/skills/paperclip-board/SKILL.md +619 -0
  194. package/skills/paperclip-converting-plans-to-tasks/SKILL.md +60 -0
  195. package/skills/paperclip-create-agent/SKILL.md +179 -0
  196. package/skills/paperclip-create-agent/references/agent-instruction-templates.md +123 -0
  197. package/skills/paperclip-create-agent/references/agents/coder.md +64 -0
  198. package/skills/paperclip-create-agent/references/agents/qa.md +88 -0
  199. package/skills/paperclip-create-agent/references/agents/securityengineer.md +135 -0
  200. package/skills/paperclip-create-agent/references/agents/uxdesigner.md +115 -0
  201. package/skills/paperclip-create-agent/references/api-reference.md +110 -0
  202. package/skills/paperclip-create-agent/references/baseline-role-guide.md +168 -0
  203. package/skills/paperclip-create-agent/references/draft-review-checklist.md +95 -0
  204. package/skills/para-memory-files/SKILL.md +100 -0
  205. package/skills/para-memory-files/references/schemas.md +35 -0
  206. package/skills/slack/SKILL.md +65 -0
@@ -0,0 +1,419 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { claudeModelUsageTotals, parseClaudeStreamJson, detectClaudeLoginRequired, extractClaudeRetryNotBefore, isClaudeProviderQuotaError, isClaudeTransientUpstreamError, isClaudePoisonedPreviousMessageIdError, isClaudeRefusalResult, isClaudeUnknownSessionError, isClaudeImageProcessingError, isClaudeModelNotFoundError, } from "./parse.js";
3
+ describe("detectClaudeLoginRequired", () => {
4
+ it("classifies Claude's invalid API key login prompt as auth required", () => {
5
+ expect(detectClaudeLoginRequired({
6
+ parsed: null,
7
+ stdout: "",
8
+ stderr: "Invalid API key · Please run /login",
9
+ })).toEqual({ requiresLogin: true, loginUrl: null });
10
+ });
11
+ it("does not classify a bare invalid API key as the Claude login flow", () => {
12
+ expect(detectClaudeLoginRequired({
13
+ parsed: null,
14
+ stdout: "",
15
+ stderr: "Invalid API key",
16
+ }).requiresLogin).toBe(false);
17
+ });
18
+ it("classifies an invalid or expired OAuth bearer token as login required", () => {
19
+ // Grounded on the real Claude CLI output for CLAUDE_CODE_OAUTH_TOKEN=invalid:
20
+ // the result event carries a 401 authentication failure and an "Invalid
21
+ // bearer token" message. This is an auth failure, not a probe that could not
22
+ // run, so the detector must classify it as login required.
23
+ const parsed = {
24
+ is_error: true,
25
+ subtype: "success",
26
+ api_error_status: 401,
27
+ error: "authentication_failed",
28
+ result: "Failed to authenticate. API Error: 401 Invalid bearer token",
29
+ };
30
+ expect(detectClaudeLoginRequired({
31
+ parsed,
32
+ stdout: '{"type":"assistant","message":{"content":[{"type":"text","text":"Failed to authenticate. API Error: 401 Invalid bearer token"}]},"error":"authentication_failed"}',
33
+ stderr: "",
34
+ }).requiresLogin).toBe(true);
35
+ });
36
+ it("does not route an invalid token to the transient or quota classifiers", () => {
37
+ // An auth failure must win over the transient and quota lanes, so a run
38
+ // surfaces login required instead of a retry.
39
+ const input = {
40
+ parsed: {
41
+ is_error: true,
42
+ result: "Failed to authenticate. API Error: 401 Invalid bearer token",
43
+ },
44
+ stdout: "",
45
+ stderr: "",
46
+ };
47
+ expect(isClaudeTransientUpstreamError(input)).toBe(false);
48
+ expect(isClaudeProviderQuotaError(input)).toBe(false);
49
+ });
50
+ it("classifies an expired or revoked token in the parsed result as login required", () => {
51
+ // The result event marks the run as a failure and reports an expired token.
52
+ // This is a token failure, so the detector classifies it as login required.
53
+ const parsed = {
54
+ is_error: true,
55
+ subtype: "success",
56
+ result: "Failed to authenticate. Your OAuth access token is expired.",
57
+ };
58
+ expect(detectClaudeLoginRequired({ parsed, stdout: "", stderr: "" }).requiresLogin).toBe(true);
59
+ });
60
+ it("does not classify a successful probe whose assistant text repeats a token phrase", () => {
61
+ // A healthy run can print an auth phrase in its answer text. The parsed
62
+ // result is a success, so the token-failure markers must not fire on the raw
63
+ // stdout assistant event.
64
+ const parsed = {
65
+ is_error: false,
66
+ subtype: "success",
67
+ result: "hello",
68
+ };
69
+ expect(detectClaudeLoginRequired({
70
+ parsed,
71
+ stdout: '{"type":"assistant","message":{"content":[{"type":"text","text":"The phrase authentication_failed means an invalid bearer token."}]}}',
72
+ stderr: "",
73
+ }).requiresLogin).toBe(false);
74
+ });
75
+ it("does not classify a success whose result text repeats a token phrase", () => {
76
+ // The model's own answer repeats a token phrase, so the phrase lands in the
77
+ // parsed result. The run is a success, so the failure gate keeps it healthy.
78
+ const parsed = {
79
+ is_error: false,
80
+ subtype: "success",
81
+ result: "Sure. An invalid bearer token means authentication_failed.",
82
+ };
83
+ expect(detectClaudeLoginRequired({ parsed, stdout: "", stderr: "" }).requiresLogin).toBe(false);
84
+ });
85
+ it("keeps a transient failure with an assistant token phrase on the transient lane", () => {
86
+ // The run fails on a 503 transient error. The token phrase appears only in
87
+ // the raw stdout assistant event, not the parsed result, so the run stays
88
+ // transient and never classifies as login required.
89
+ const input = {
90
+ parsed: {
91
+ is_error: true,
92
+ subtype: "error_during_execution",
93
+ result: "API Error: 503 service unavailable",
94
+ },
95
+ stdout: '{"type":"assistant","message":{"content":[{"type":"text","text":"authentication_failed: the bearer token is invalid"}]}}',
96
+ stderr: "",
97
+ };
98
+ expect(detectClaudeLoginRequired(input).requiresLogin).toBe(false);
99
+ expect(isClaudeTransientUpstreamError(input)).toBe(true);
100
+ });
101
+ it("does not treat a bare token phrase in raw stdout with no parsed result as login required", () => {
102
+ // Untrusted stdout alone must not satisfy a token-failure marker. Only the
103
+ // parsed terminal result fields of a failed run can trip the token markers.
104
+ expect(detectClaudeLoginRequired({
105
+ parsed: null,
106
+ stdout: "authentication_failed while the assistant called a tool",
107
+ stderr: "",
108
+ }).requiresLogin).toBe(false);
109
+ });
110
+ });
111
+ describe("isClaudeModelNotFoundError", () => {
112
+ it("detects model resolution failures from structured and fallback output", () => {
113
+ expect(isClaudeModelNotFoundError({
114
+ parsed: {
115
+ result: "API Error: 404 model not found: claude-haiku-4-6",
116
+ },
117
+ })).toBe(true);
118
+ expect(isClaudeModelNotFoundError({
119
+ stderr: "Unknown model claude-haiku-4-6",
120
+ })).toBe(true);
121
+ });
122
+ it("does not classify unrelated provider failures as model resolution errors", () => {
123
+ expect(isClaudeModelNotFoundError({
124
+ errorMessage: "API Error: 503 service unavailable",
125
+ })).toBe(false);
126
+ });
127
+ });
128
+ describe("isClaudeTransientUpstreamError", () => {
129
+ it("classifies the 'out of extra usage' subscription window failure as provider quota", () => {
130
+ expect(isClaudeProviderQuotaError({
131
+ errorMessage: "You're out of extra usage · resets 4pm (America/Chicago)",
132
+ })).toBe(true);
133
+ expect(isClaudeProviderQuotaError({
134
+ parsed: {
135
+ is_error: true,
136
+ result: "You're out of extra usage. Resets at 4pm (America/Chicago).",
137
+ },
138
+ })).toBe(true);
139
+ expect(isClaudeTransientUpstreamError({
140
+ errorMessage: "You're out of extra usage · resets 4pm (America/Chicago)",
141
+ })).toBe(false);
142
+ });
143
+ it("classifies Claude session-limit windows as provider quota and extracts the retry time", () => {
144
+ const now = new Date("2026-04-22T15:15:00.000Z");
145
+ const errorMessage = "You've hit your session limit - resets at 4pm (America/Chicago).";
146
+ expect(isClaudeProviderQuotaError({ errorMessage })).toBe(true);
147
+ expect(isClaudeTransientUpstreamError({ errorMessage })).toBe(false);
148
+ expect(extractClaudeRetryNotBefore({ errorMessage }, now)?.toISOString()).toBe("2026-04-22T21:00:00.000Z");
149
+ });
150
+ it("classifies the qualifier-less limit wording as provider quota and extracts the retry time", () => {
151
+ // Current Claude CLI phrasing: no "session"/"usage" qualifier before "limit".
152
+ const now = new Date("2026-08-28T22:30:00.000Z");
153
+ const errorMessage = "You've hit your limit · resets 2:30am (UTC)";
154
+ expect(isClaudeProviderQuotaError({ errorMessage })).toBe(true);
155
+ expect(isClaudeTransientUpstreamError({ errorMessage })).toBe(false);
156
+ expect(extractClaudeRetryNotBefore({ errorMessage }, now)?.toISOString()).toBe("2026-08-29T02:30:00.000Z");
157
+ });
158
+ it("classifies Anthropic API rate_limit_error and overloaded_error as transient", () => {
159
+ expect(isClaudeTransientUpstreamError({
160
+ parsed: {
161
+ is_error: true,
162
+ errors: [{ type: "rate_limit_error", message: "Rate limit reached for requests." }],
163
+ },
164
+ })).toBe(true);
165
+ expect(isClaudeTransientUpstreamError({
166
+ parsed: {
167
+ is_error: true,
168
+ errors: [{ type: "overloaded_error", message: "Overloaded" }],
169
+ },
170
+ })).toBe(true);
171
+ expect(isClaudeTransientUpstreamError({
172
+ stderr: "HTTP 429: Too Many Requests",
173
+ })).toBe(true);
174
+ expect(isClaudeTransientUpstreamError({
175
+ stderr: "Bedrock ThrottlingException: slow down",
176
+ })).toBe(true);
177
+ });
178
+ it("classifies the subscription 5-hour / weekly limit wording as provider quota", () => {
179
+ expect(isClaudeProviderQuotaError({
180
+ errorMessage: "Claude usage limit reached — weekly limit reached. Try again in 2 days.",
181
+ })).toBe(true);
182
+ expect(isClaudeProviderQuotaError({
183
+ errorMessage: "5-hour limit reached.",
184
+ })).toBe(true);
185
+ });
186
+ it("does not classify login/auth failures as transient", () => {
187
+ expect(isClaudeTransientUpstreamError({
188
+ stderr: "Please log in. Run `claude login` first.",
189
+ })).toBe(false);
190
+ });
191
+ it("does not classify max-turns or unknown-session as transient", () => {
192
+ expect(isClaudeTransientUpstreamError({
193
+ parsed: { subtype: "error_max_turns", result: "Maximum turns reached." },
194
+ })).toBe(false);
195
+ expect(isClaudeTransientUpstreamError({
196
+ parsed: {
197
+ result: "No conversation found with session id abc-123",
198
+ errors: [{ message: "No conversation found with session id abc-123" }],
199
+ },
200
+ })).toBe(false);
201
+ });
202
+ it("does not classify deterministic validation errors as transient", () => {
203
+ expect(isClaudeTransientUpstreamError({
204
+ errorMessage: "Invalid request_error: Unknown parameter 'foo'.",
205
+ })).toBe(false);
206
+ });
207
+ it("does not classify poisoned previous_message_id errors as transient", () => {
208
+ expect(isClaudeTransientUpstreamError({
209
+ parsed: {
210
+ subtype: "success",
211
+ is_error: true,
212
+ result: "API Error: 400 diagnostics.previous_message_id: must be the `id` from a prior /v1/messages response (starts with `msg_`)",
213
+ },
214
+ })).toBe(false);
215
+ });
216
+ });
217
+ describe("isClaudePoisonedPreviousMessageIdError", () => {
218
+ it("detects the previous_message_id 400 error in the result field", () => {
219
+ expect(isClaudePoisonedPreviousMessageIdError({
220
+ subtype: "success",
221
+ is_error: true,
222
+ result: "API Error: 400 diagnostics.previous_message_id: must be the `id` from a prior /v1/messages response (starts with `msg_`)",
223
+ })).toBe(true);
224
+ });
225
+ it("detects the error in the errors array", () => {
226
+ expect(isClaudePoisonedPreviousMessageIdError({
227
+ is_error: true,
228
+ result: "",
229
+ errors: [{ message: "400 diagnostics.previous_message_id: must be the `id` from a prior /v1/messages response (starts with `msg_`)" }],
230
+ })).toBe(true);
231
+ });
232
+ it("returns false for unrelated errors", () => {
233
+ expect(isClaudePoisonedPreviousMessageIdError({
234
+ is_error: true,
235
+ result: "No conversation found with session id abc-123",
236
+ })).toBe(false);
237
+ });
238
+ it("returns false for empty parsed result", () => {
239
+ expect(isClaudePoisonedPreviousMessageIdError({})).toBe(false);
240
+ });
241
+ });
242
+ describe("isClaudeRefusalResult", () => {
243
+ it("detects stop_reason: refusal even on a clean (is_error=false) result", () => {
244
+ expect(isClaudeRefusalResult({
245
+ type: "result",
246
+ subtype: "success",
247
+ is_error: false,
248
+ stop_reason: "refusal",
249
+ result: "",
250
+ })).toBe(true);
251
+ });
252
+ it("detects the camelCase stopReason variant", () => {
253
+ expect(isClaudeRefusalResult({ stopReason: "refusal" })).toBe(true);
254
+ });
255
+ it("detects subtype: model_refusal", () => {
256
+ expect(isClaudeRefusalResult({ subtype: "model_refusal", is_error: false })).toBe(true);
257
+ });
258
+ it("is case-insensitive and tolerant of surrounding whitespace", () => {
259
+ expect(isClaudeRefusalResult({ stop_reason: " Refusal " })).toBe(true);
260
+ });
261
+ it("returns false for ordinary successful turns", () => {
262
+ expect(isClaudeRefusalResult({
263
+ subtype: "success",
264
+ is_error: false,
265
+ stop_reason: "end_turn",
266
+ result: "Here is your answer.",
267
+ })).toBe(false);
268
+ });
269
+ it("returns false for max-turns and other stop reasons", () => {
270
+ expect(isClaudeRefusalResult({ stop_reason: "max_turns" })).toBe(false);
271
+ expect(isClaudeRefusalResult({ subtype: "error_max_turns" })).toBe(false);
272
+ });
273
+ it("returns false for null/empty parsed result", () => {
274
+ expect(isClaudeRefusalResult(null)).toBe(false);
275
+ expect(isClaudeRefusalResult({})).toBe(false);
276
+ });
277
+ });
278
+ describe("isClaudeUnknownSessionError", () => {
279
+ it("detects the legacy 'no conversation found' message", () => {
280
+ expect(isClaudeUnknownSessionError({
281
+ result: "Error: No conversation found with session id 1234",
282
+ })).toBe(true);
283
+ });
284
+ it("detects 'session ... not found' style errors", () => {
285
+ expect(isClaudeUnknownSessionError({
286
+ errors: [{ message: "Session abc123 not found" }],
287
+ })).toBe(true);
288
+ });
289
+ it("detects '--resume requires a valid session' validation error from non-UUID input", () => {
290
+ expect(isClaudeUnknownSessionError({
291
+ errors: [
292
+ {
293
+ message: 'Error: --resume requires a valid session ID or session title when used with --print. Usage: claude -p --resume <session-id|title>. Provided value "ses_268c2d0a5ffemYbEaeG7c86Uvo" is not a UUID and does not match any session title.',
294
+ },
295
+ ],
296
+ })).toBe(true);
297
+ });
298
+ it("returns false for unrelated error text", () => {
299
+ expect(isClaudeUnknownSessionError({
300
+ result: "Some other failure",
301
+ errors: [{ message: "Network timeout" }],
302
+ })).toBe(false);
303
+ });
304
+ });
305
+ describe("isClaudeImageProcessingError", () => {
306
+ it("detects the 'Could not process image' 400 error in the result field", () => {
307
+ expect(isClaudeImageProcessingError({
308
+ subtype: "success",
309
+ is_error: true,
310
+ result: "API Error: 400 Could not process image: image source URL has expired",
311
+ })).toBe(true);
312
+ });
313
+ it("detects the error in the errors array", () => {
314
+ expect(isClaudeImageProcessingError({
315
+ is_error: true,
316
+ result: "",
317
+ errors: [{ message: "400 Could not process image" }],
318
+ })).toBe(true);
319
+ });
320
+ it("is case-insensitive", () => {
321
+ expect(isClaudeImageProcessingError({
322
+ is_error: true,
323
+ result: "could not process image attached to message",
324
+ })).toBe(true);
325
+ });
326
+ it("returns false for unrelated errors", () => {
327
+ expect(isClaudeImageProcessingError({
328
+ is_error: true,
329
+ result: "No conversation found with session id abc-123",
330
+ })).toBe(false);
331
+ });
332
+ it("returns false for empty parsed result", () => {
333
+ expect(isClaudeImageProcessingError({})).toBe(false);
334
+ });
335
+ });
336
+ describe("extractClaudeRetryNotBefore", () => {
337
+ it("parses the 'resets 4pm' hint in its explicit timezone", () => {
338
+ const now = new Date("2026-04-22T15:15:00.000Z");
339
+ const extracted = extractClaudeRetryNotBefore({ errorMessage: "You're out of extra usage · resets 4pm (America/Chicago)" }, now);
340
+ expect(extracted?.toISOString()).toBe("2026-04-22T21:00:00.000Z");
341
+ });
342
+ it("rolls forward past midnight when the reset time has already passed today", () => {
343
+ const now = new Date("2026-04-22T23:30:00.000Z");
344
+ const extracted = extractClaudeRetryNotBefore({ errorMessage: "Usage limit reached. Resets at 3:15 AM (UTC)." }, now);
345
+ expect(extracted?.toISOString()).toBe("2026-04-23T03:15:00.000Z");
346
+ });
347
+ it("returns null when no reset hint is present", () => {
348
+ expect(extractClaudeRetryNotBefore({ errorMessage: "Overloaded. Try again later." }, new Date())).toBeNull();
349
+ });
350
+ });
351
+ describe("claudeModelUsageTotals", () => {
352
+ it("sums per-model usage across models and counts cache writes as input", () => {
353
+ const totals = claudeModelUsageTotals({
354
+ "claude-fable-5": {
355
+ inputTokens: 100,
356
+ outputTokens: 70_000,
357
+ cacheReadInputTokens: 250_000,
358
+ cacheCreationInputTokens: 4_000,
359
+ costUSD: 1.2,
360
+ },
361
+ "claude-haiku-4-5": {
362
+ inputTokens: 50,
363
+ outputTokens: 7_000,
364
+ cacheReadInputTokens: 10_000,
365
+ cacheCreationInputTokens: 500,
366
+ costUSD: 0.05,
367
+ },
368
+ });
369
+ expect(totals).toEqual({
370
+ inputTokens: 4_650,
371
+ outputTokens: 77_000,
372
+ cachedInputTokens: 260_000,
373
+ });
374
+ });
375
+ it("returns null for missing or empty modelUsage", () => {
376
+ expect(claudeModelUsageTotals(undefined)).toBeNull();
377
+ expect(claudeModelUsageTotals({})).toBeNull();
378
+ });
379
+ });
380
+ describe("parseClaudeStreamJson usage extraction", () => {
381
+ const resultEvent = (extra) => JSON.stringify({
382
+ type: "result",
383
+ subtype: "success",
384
+ session_id: "sess-1",
385
+ result: "done",
386
+ total_cost_usd: 1.25,
387
+ usage: { input_tokens: 10, output_tokens: 1_800, cache_read_input_tokens: 20 },
388
+ ...extra,
389
+ });
390
+ it("prefers modelUsage totals over the main-loop usage block and marks them per-run", () => {
391
+ const parsed = parseClaudeStreamJson(`${resultEvent({
392
+ modelUsage: {
393
+ "claude-fable-5": {
394
+ inputTokens: 90,
395
+ outputTokens: 77_000,
396
+ cacheReadInputTokens: 300_000,
397
+ cacheCreationInputTokens: 2_000,
398
+ },
399
+ },
400
+ })}\n`);
401
+ expect(parsed.usage).toEqual({
402
+ inputTokens: 2_090,
403
+ outputTokens: 77_000,
404
+ cachedInputTokens: 300_000,
405
+ });
406
+ expect(parsed.usageBasis).toBe("per_run");
407
+ expect(parsed.costUsd).toBeCloseTo(1.25);
408
+ });
409
+ it("falls back to the result usage block when modelUsage is absent", () => {
410
+ const parsed = parseClaudeStreamJson(`${resultEvent({})}\n`);
411
+ expect(parsed.usage).toEqual({
412
+ inputTokens: 10,
413
+ outputTokens: 1_800,
414
+ cachedInputTokens: 20,
415
+ });
416
+ expect(parsed.usageBasis).toBe("per_run");
417
+ });
418
+ });
419
+ //# sourceMappingURL=parse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.test.js","sourceRoot":"","sources":["../../src/server/parse.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ interface ClaudePermissionInput {
2
+ dangerouslySkipPermissions: boolean;
3
+ targetIsRemote: boolean;
4
+ localProcessUid?: number | null;
5
+ }
6
+ export declare function buildClaudeExecutionPermissionArgs(input: ClaudePermissionInput): string[];
7
+ export declare const buildClaudeProbePermissionArgs: typeof buildClaudeExecutionPermissionArgs;
8
+ /** Claude permits full bypass as root only inside an identified sandbox. */
9
+ export declare function claudeSandboxPermissionEnv(input: {
10
+ dangerouslySkipPermissions: boolean;
11
+ targetIsSandbox: boolean;
12
+ }): Record<string, string>;
13
+ export {};
14
+ //# sourceMappingURL=permissions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/server/permissions.ts"],"names":[],"mappings":"AAAA,UAAU,qBAAqB;IAC7B,0BAA0B,EAAE,OAAO,CAAC;IACpC,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAMD,wBAAgB,kCAAkC,CAAC,KAAK,EAAE,qBAAqB,GAAG,MAAM,EAAE,CAEzF;AAED,eAAO,MAAM,8BAA8B,2CAAqC,CAAC;AAEjF,4EAA4E;AAC5E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE;IAChD,0BAA0B,EAAE,OAAO,CAAC;IACpC,eAAe,EAAE,OAAO,CAAC;CAC1B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAEzB"}
@@ -0,0 +1,13 @@
1
+ // Permission defaults are identical for local, remote, and connected tools.
2
+ // A tool allowlist is not equivalent to full bypass: it misses MCP tools and
3
+ // tools added by later provider releases. Let Claude enforce its own launch
4
+ // requirements rather than silently downgrading the requested permission mode.
5
+ export function buildClaudeExecutionPermissionArgs(input) {
6
+ return input.dangerouslySkipPermissions ? ["--dangerously-skip-permissions"] : [];
7
+ }
8
+ export const buildClaudeProbePermissionArgs = buildClaudeExecutionPermissionArgs;
9
+ /** Claude permits full bypass as root only inside an identified sandbox. */
10
+ export function claudeSandboxPermissionEnv(input) {
11
+ return input.dangerouslySkipPermissions && input.targetIsSandbox ? { IS_SANDBOX: "1" } : {};
12
+ }
13
+ //# sourceMappingURL=permissions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/server/permissions.ts"],"names":[],"mappings":"AAMA,4EAA4E;AAC5E,6EAA6E;AAC7E,4EAA4E;AAC5E,+EAA+E;AAC/E,MAAM,UAAU,kCAAkC,CAAC,KAA4B;IAC7E,OAAO,KAAK,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACpF,CAAC;AAED,MAAM,CAAC,MAAM,8BAA8B,GAAG,kCAAkC,CAAC;AAEjF,4EAA4E;AAC5E,MAAM,UAAU,0BAA0B,CAAC,KAG1C;IACC,OAAO,KAAK,CAAC,0BAA0B,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9F,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=permissions.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.test.d.ts","sourceRoot":"","sources":["../../src/server/permissions.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildClaudeExecutionPermissionArgs, buildClaudeProbePermissionArgs, claudeSandboxPermissionEnv } from "./permissions.js";
3
+ describe("Claude full-auto permission args", () => {
4
+ for (const [name, build] of [["execution", buildClaudeExecutionPermissionArgs], ["probe", buildClaudeProbePermissionArgs]]) {
5
+ it.each([
6
+ { targetIsRemote: false, localProcessUid: 1000 },
7
+ { targetIsRemote: true, localProcessUid: 1000 },
8
+ { targetIsRemote: false, localProcessUid: 0 },
9
+ { targetIsRemote: true, localProcessUid: 0 },
10
+ ])(`${name} requests full bypass for %j`, (target) => {
11
+ expect(build({ ...target, dangerouslySkipPermissions: true }))
12
+ .toEqual(["--dangerously-skip-permissions"]);
13
+ expect(build({ ...target, dangerouslySkipPermissions: false })).toEqual([]);
14
+ });
15
+ }
16
+ it("identifies managed sandboxes for Claude's root launch check only when full auto is enabled", () => {
17
+ expect(claudeSandboxPermissionEnv({ dangerouslySkipPermissions: true, targetIsSandbox: true })).toEqual({ IS_SANDBOX: "1" });
18
+ expect(claudeSandboxPermissionEnv({ dangerouslySkipPermissions: false, targetIsSandbox: true })).toEqual({});
19
+ expect(claudeSandboxPermissionEnv({ dangerouslySkipPermissions: true, targetIsSandbox: false })).toEqual({});
20
+ });
21
+ });
22
+ //# sourceMappingURL=permissions.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions.test.js","sourceRoot":"","sources":["../../src/server/permissions.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kCAAkC,EAAE,8BAA8B,EAAE,0BAA0B,EAAE,MAAM,kBAAkB,CAAC;AAElI,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,kCAAkC,CAAC,EAAE,CAAC,OAAO,EAAE,8BAA8B,CAAC,CAAU,EAAE,CAAC;QACpI,EAAE,CAAC,IAAI,CAAC;YACN,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE;YAChD,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE;YAC/C,EAAE,cAAc,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC,EAAE;YAC7C,EAAE,cAAc,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,EAAE;SAC7C,CAAC,CAAC,GAAG,IAAI,8BAA8B,EAAE,CAAC,MAAM,EAAE,EAAE;YACnD,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,0BAA0B,EAAE,IAAI,EAAE,CAAC,CAAC;iBAC3D,OAAO,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,MAAM,EAAE,0BAA0B,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC9E,CAAC,CAAC,CAAC;IACL,CAAC;IAED,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,MAAM,CAAC,0BAA0B,CAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC,CAAC;QAC7H,MAAM,CAAC,0BAA0B,CAAC,EAAE,0BAA0B,EAAE,KAAK,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC7G,MAAM,CAAC,0BAA0B,CAAC,EAAE,0BAA0B,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/G,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,102 @@
1
+ import type { AdapterEnvironmentCheck } from "@tickernelz/paperclip-pro-adapter-utils";
2
+ /**
3
+ * The fixed label a Test result shows when the probe runs on the local
4
+ * Paperclip host. The label is a constant, so a local target check never
5
+ * carries an environment ID, a config value, or a credential-derived string.
6
+ */
7
+ export declare const ADAPTER_TEST_HOST_TARGET_LABEL = "Paperclip host";
8
+ /**
9
+ * The allowlisted classification for a sandbox probe diagnostic. The call site
10
+ * picks one fixed label from this set. The label never holds a copy of
11
+ * untrusted probe text.
12
+ *
13
+ * - `timeout`: the probe process did not finish before the deadline.
14
+ * - `auth_required`: the probe ran and reported that login is required.
15
+ * - `nonzero_exit`: the probe process exited with a non-zero exit code.
16
+ * - `spawn_error`: the probe process, or a setup step, threw before it ran.
17
+ * - `empty_output`: the probe produced no output.
18
+ * - `unexpected_output`: the probe ran and exited zero, but the output did
19
+ * not match the expected reply.
20
+ */
21
+ export type SandboxProbeDiagnosticClassification = "timeout" | "auth_required" | "nonzero_exit" | "spawn_error" | "empty_output" | "unexpected_output";
22
+ /**
23
+ * The safe structured fields a call site may add to a probe diagnostic. Each
24
+ * field is a fixed shape, not free text. The helper drops any value that is not
25
+ * safe.
26
+ */
27
+ export interface SandboxProbeDiagnosticFields {
28
+ exitCode?: number | null;
29
+ errorClass?: string | null;
30
+ }
31
+ /**
32
+ * Read the class name of a thrown value for a safe probe diagnostic. The
33
+ * function returns the constructor name of an `Error`, or `null` for any other
34
+ * value. The name is a bounded identifier, not a copy of the error message, so
35
+ * it carries no untrusted probe text.
36
+ */
37
+ export declare function classifyThrownErrorClass(err: unknown): string | null;
38
+ /**
39
+ * Send a sandbox probe or config materialization diagnostic to the server log.
40
+ *
41
+ * Three Test-lane call sites use this helper:
42
+ * - the Claude CLI Test lane (`test.ts`),
43
+ * - the Claude ACP Test lane (`acp.ts`),
44
+ * - the managed-config materialization step (`claude-config.ts`).
45
+ *
46
+ * Contract: no untrusted text reaches the log. The helper logs only the fixed
47
+ * context string, one allowlisted classification, and safe structured fields.
48
+ * The safe fields are the process exit code and a sanitized error class name.
49
+ * The helper never logs raw probe stdout, raw stderr, or a raw thrown-error
50
+ * message. A call site must never copy raw probe text into a Test-result check,
51
+ * because the user interface renders check text.
52
+ *
53
+ * @param context A short fixed description of the failed step. It carries no
54
+ * untrusted text.
55
+ * @param classification One allowlisted label that the call site derives from
56
+ * the probe state. It carries no untrusted text.
57
+ * @param fields Optional safe structured fields, such as the exit code.
58
+ */
59
+ export declare function logSandboxProbeDiagnostic(context: string, classification: SandboxProbeDiagnosticClassification, fields?: SandboxProbeDiagnosticFields): void;
60
+ /**
61
+ * Normalize an untrusted login URL for a Test-result hint.
62
+ *
63
+ * The extractor reads the URL from raw sandbox stdout or stderr, so the value is
64
+ * untrusted. The function accepts the URL only when every rule holds:
65
+ * - the protocol is `https`,
66
+ * - the host equals or ends with an allowlisted Claude or Anthropic host,
67
+ * - the URL has no user, password, or port,
68
+ * - the URL has no query and no fragment.
69
+ *
70
+ * The function returns the normalized URL string, or `null` when any rule
71
+ * fails. The caller shows a fixed `claude login` hint when the function returns
72
+ * `null`.
73
+ */
74
+ export declare function normalizeClaudeLoginUrl(raw: string | null | undefined): string | null;
75
+ /**
76
+ * Build the fixed auth-required hint for a Test-result check. When the login URL
77
+ * normalizes to a safe value, the hint names it. Otherwise the hint tells the
78
+ * operator to run `claude login`.
79
+ */
80
+ export declare function buildClaudeLoginRequiredHint(loginUrl: string | null | undefined): string;
81
+ /**
82
+ * Resolve the label a Test result shows for the probed target. A remote target
83
+ * uses the authorized environment name. A remote target with no name uses a
84
+ * fixed generic label. A local target uses the fixed host label. The function
85
+ * never returns an environment ID, a config value, or a credential-derived
86
+ * string.
87
+ */
88
+ export declare function resolveAdapterTestTargetLabel(input: {
89
+ targetIsRemote: boolean;
90
+ environmentName: string | null | undefined;
91
+ }): string;
92
+ /**
93
+ * Build the target check every Test result carries, so the result names the
94
+ * target it probed. Both the Claude CLI Test lane and the Claude ACP Test lane
95
+ * use this builder. The check text carries only the authorized environment
96
+ * label or the fixed host label.
97
+ */
98
+ export declare function buildAdapterTestTargetCheck(input: {
99
+ targetIsRemote: boolean;
100
+ environmentName: string | null | undefined;
101
+ }): AdapterEnvironmentCheck;
102
+ //# sourceMappingURL=probe-diagnostics.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probe-diagnostics.d.ts","sourceRoot":"","sources":["../../src/server/probe-diagnostics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,yCAAyC,CAAC;AAEvF;;;;GAIG;AACH,eAAO,MAAM,8BAA8B,mBAAmB,CAAC;AAW/D;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,oCAAoC,GAC5C,SAAS,GACT,eAAe,GACf,cAAc,GACd,aAAa,GACb,cAAc,GACd,mBAAmB,CAAC;AAExB;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAE3C,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAGpE;AAUD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,oCAAoC,EACpD,MAAM,CAAC,EAAE,4BAA4B,GACpC,IAAI,CAYN;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAiBrF;AAED;;;;GAIG;AACH,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAKxF;AAED;;;;;;GAMG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE;IACnD,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC5C,GAAG,MAAM,CAIT;AAED;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,cAAc,EAAE,OAAO,CAAC;IACxB,eAAe,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;CAC5C,GAAG,uBAAuB,CAS1B"}