@agentrhq/webcmd 0.2.5 → 0.3.1

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 (200) hide show
  1. package/README.md +13 -2
  2. package/cli-manifest.json +217 -13
  3. package/clis/_shared/site-auth.js +3 -3
  4. package/clis/_shared/site-auth.test.js +4 -4
  5. package/clis/chatgpt/ask.js +1 -1
  6. package/clis/chatgpt/ask.test.js +11 -0
  7. package/clis/chatgpt/commands.test.js +102 -1
  8. package/clis/chatgpt/deep-research-result.js +45 -3
  9. package/clis/chatgpt/image.js +22 -2
  10. package/clis/chatgpt/project-file-add.js +24 -1
  11. package/clis/chatgpt/utils.js +258 -52
  12. package/clis/chatgpt/utils.test.js +259 -1
  13. package/clis/claude/ask.js +21 -1
  14. package/clis/facebook/feed.js +110 -24
  15. package/clis/facebook/feed.test.js +62 -0
  16. package/clis/facebook/search.js +185 -38
  17. package/clis/facebook/search.test.js +95 -50
  18. package/clis/instagram/explore.js +30 -12
  19. package/clis/instagram/explore.test.js +77 -0
  20. package/clis/instagram/post.js +14 -1
  21. package/clis/instagram/reel.js +13 -1
  22. package/clis/linkedin/company.js +153 -0
  23. package/clis/linkedin/company.test.js +111 -0
  24. package/clis/linkedin/connections.js +135 -0
  25. package/clis/linkedin/connections.test.js +141 -0
  26. package/clis/mercury/reimbursement-draft.js +12 -1
  27. package/clis/slock/whoami.test.js +2 -2
  28. package/clis/twitter/article-evaluate.test.js +27 -0
  29. package/clis/twitter/article.js +73 -16
  30. package/clis/twitter/article.test.js +209 -0
  31. package/clis/twitter/download.js +6 -1
  32. package/clis/twitter/post.js +14 -1
  33. package/clis/twitter/profile.js +1 -1
  34. package/clis/twitter/profile.test.js +8 -0
  35. package/clis/twitter/quote.js +11 -1
  36. package/clis/twitter/reply.js +11 -1
  37. package/dist/src/browser/base-page.d.ts +26 -0
  38. package/dist/src/browser/base-page.js +23 -8
  39. package/dist/src/browser/base-page.test.js +45 -12
  40. package/dist/src/browser/command-catalog.d.ts +6 -0
  41. package/dist/src/browser/command-catalog.js +259 -0
  42. package/dist/src/browser/command-catalog.test.d.ts +1 -0
  43. package/dist/src/browser/command-catalog.test.js +79 -0
  44. package/dist/src/browser/daemon-client.d.ts +2 -1
  45. package/dist/src/browser/runtime/local-cloak/actions.js +4 -1
  46. package/dist/src/browser/runtime/local-cloak/darwin-background-launch.d.ts +17 -0
  47. package/dist/src/browser/runtime/local-cloak/darwin-background-launch.js +106 -0
  48. package/dist/src/browser/runtime/local-cloak/darwin-background-launch.test.d.ts +1 -0
  49. package/dist/src/browser/runtime/local-cloak/darwin-background-launch.test.js +65 -0
  50. package/dist/src/browser/runtime/local-cloak/provider.test.js +36 -0
  51. package/dist/src/browser/runtime/local-cloak/session-manager.d.ts +10 -2
  52. package/dist/src/browser/runtime/local-cloak/session-manager.js +25 -9
  53. package/dist/src/browser/runtime/local-cloak/session-manager.test.js +36 -0
  54. package/dist/src/browser/target-resolver.d.ts +1 -0
  55. package/dist/src/browser/target-resolver.js +99 -4
  56. package/dist/src/browser/target-resolver.test.js +141 -1
  57. package/dist/src/build-manifest.d.ts +6 -0
  58. package/dist/src/build-manifest.js +18 -1
  59. package/dist/src/build-manifest.test.js +57 -1
  60. package/dist/src/builtin-command-surface.d.ts +9 -0
  61. package/dist/src/builtin-command-surface.js +16 -0
  62. package/dist/src/check-hosted-contract.test.d.ts +1 -0
  63. package/dist/src/check-hosted-contract.test.js +56 -0
  64. package/dist/src/cli.js +63 -110
  65. package/dist/src/cli.test.js +82 -6
  66. package/dist/src/command-presentation.d.ts +95 -0
  67. package/dist/src/command-presentation.js +486 -0
  68. package/dist/src/command-presentation.test.d.ts +1 -0
  69. package/dist/src/command-presentation.test.js +97 -0
  70. package/dist/src/command-surface.d.ts +43 -0
  71. package/dist/src/command-surface.js +205 -0
  72. package/dist/src/command-surface.test.d.ts +1 -0
  73. package/dist/src/command-surface.test.js +406 -0
  74. package/dist/src/commanderAdapter.d.ts +5 -1
  75. package/dist/src/commanderAdapter.js +12 -55
  76. package/dist/src/commanderAdapter.test.js +15 -3
  77. package/dist/src/commands/auth.js +3 -2
  78. package/dist/src/commands/auth.test.js +6 -6
  79. package/dist/src/community-plugin-sync.d.ts +11 -0
  80. package/dist/src/community-plugin-sync.js +138 -0
  81. package/dist/src/community-plugin-sync.test.d.ts +1 -0
  82. package/dist/src/community-plugin-sync.test.js +123 -0
  83. package/dist/src/completion-fast.d.ts +4 -4
  84. package/dist/src/completion-fast.js +15 -34
  85. package/dist/src/completion-shared.d.ts +4 -0
  86. package/dist/src/completion-shared.js +38 -0
  87. package/dist/src/completion.js +3 -27
  88. package/dist/src/completion.test.js +31 -2
  89. package/dist/src/docs-sync-review-cli.test.d.ts +1 -0
  90. package/dist/src/docs-sync-review-cli.test.js +322 -0
  91. package/dist/src/docs-sync-review.d.ts +117 -0
  92. package/dist/src/docs-sync-review.js +475 -0
  93. package/dist/src/docs-sync-review.test.d.ts +1 -0
  94. package/dist/src/docs-sync-review.test.js +324 -0
  95. package/dist/src/errors.d.ts +12 -3
  96. package/dist/src/errors.js +11 -7
  97. package/dist/src/errors.test.js +14 -1
  98. package/dist/src/execution.d.ts +1 -2
  99. package/dist/src/execution.js +4 -45
  100. package/dist/src/generate-release-notes-cli.test.js +11 -1
  101. package/dist/src/help.d.ts +4 -0
  102. package/dist/src/help.js +50 -255
  103. package/dist/src/help.test.js +27 -1
  104. package/dist/src/hosted/args.d.ts +4 -0
  105. package/dist/src/hosted/args.js +4 -0
  106. package/dist/src/hosted/args.test.d.ts +1 -0
  107. package/dist/src/hosted/args.test.js +49 -0
  108. package/dist/src/hosted/availability.d.ts +13 -0
  109. package/dist/src/hosted/availability.js +16 -0
  110. package/dist/src/hosted/availability.test.d.ts +1 -0
  111. package/dist/src/hosted/availability.test.js +180 -0
  112. package/dist/src/hosted/browser-args.d.ts +18 -0
  113. package/dist/src/hosted/browser-args.js +152 -0
  114. package/dist/src/hosted/browser-args.test.d.ts +1 -0
  115. package/dist/src/hosted/browser-args.test.js +182 -0
  116. package/dist/src/hosted/client.d.ts +59 -0
  117. package/dist/src/hosted/client.js +510 -0
  118. package/dist/src/hosted/client.test.d.ts +1 -0
  119. package/dist/src/hosted/client.test.js +738 -0
  120. package/dist/src/hosted/config.d.ts +55 -0
  121. package/dist/src/hosted/config.js +112 -0
  122. package/dist/src/hosted/config.test.d.ts +1 -0
  123. package/dist/src/hosted/config.test.js +81 -0
  124. package/dist/src/hosted/contract.d.ts +94 -0
  125. package/dist/src/hosted/contract.js +208 -0
  126. package/dist/src/hosted/contract.test.d.ts +1 -0
  127. package/dist/src/hosted/contract.test.js +361 -0
  128. package/dist/src/hosted/credentials.d.ts +38 -0
  129. package/dist/src/hosted/credentials.js +248 -0
  130. package/dist/src/hosted/credentials.test.d.ts +1 -0
  131. package/dist/src/hosted/credentials.test.js +93 -0
  132. package/dist/src/hosted/file-contract.test.d.ts +1 -0
  133. package/dist/src/hosted/file-contract.test.js +174 -0
  134. package/dist/src/hosted/files.d.ts +29 -0
  135. package/dist/src/hosted/files.js +296 -0
  136. package/dist/src/hosted/files.test.d.ts +1 -0
  137. package/dist/src/hosted/files.test.js +231 -0
  138. package/dist/src/hosted/main-lifecycle.test.d.ts +1 -0
  139. package/dist/src/hosted/main-lifecycle.test.js +213 -0
  140. package/dist/src/hosted/manifest.d.ts +14 -0
  141. package/dist/src/hosted/manifest.js +47 -0
  142. package/dist/src/hosted/manifest.test.d.ts +1 -0
  143. package/dist/src/hosted/manifest.test.js +164 -0
  144. package/dist/src/hosted/output-parity.test.d.ts +1 -0
  145. package/dist/src/hosted/output-parity.test.js +108 -0
  146. package/dist/src/hosted/root-command-surface.test.d.ts +1 -0
  147. package/dist/src/hosted/root-command-surface.test.js +646 -0
  148. package/dist/src/hosted/runner.d.ts +19 -0
  149. package/dist/src/hosted/runner.js +705 -0
  150. package/dist/src/hosted/runner.test.d.ts +1 -0
  151. package/dist/src/hosted/runner.test.js +1607 -0
  152. package/dist/src/hosted/setup.d.ts +10 -0
  153. package/dist/src/hosted/setup.js +79 -0
  154. package/dist/src/hosted/setup.test.d.ts +1 -0
  155. package/dist/src/hosted/setup.test.js +195 -0
  156. package/dist/src/hosted/types.d.ts +175 -0
  157. package/dist/src/hosted/types.js +1 -0
  158. package/dist/src/main.js +123 -97
  159. package/dist/src/manifest-types.d.ts +2 -0
  160. package/dist/src/output.d.ts +17 -2
  161. package/dist/src/output.js +88 -81
  162. package/dist/src/output.test.js +141 -51
  163. package/dist/src/pipeline/executor.test.js +1 -0
  164. package/dist/src/pipeline/steps/download.test.js +1 -0
  165. package/dist/src/plugin-create-cli.test.d.ts +1 -0
  166. package/dist/src/plugin-create-cli.test.js +37 -0
  167. package/dist/src/plugin-manifest.d.ts +12 -0
  168. package/dist/src/plugin-manifest.js +16 -0
  169. package/dist/src/plugin-manifest.test.js +19 -1
  170. package/dist/src/plugin-scaffold.d.ts +4 -1
  171. package/dist/src/plugin-scaffold.js +4 -1
  172. package/dist/src/plugin-scaffold.test.js +23 -8
  173. package/dist/src/plugin.js +4 -1
  174. package/dist/src/plugin.test.js +13 -0
  175. package/dist/src/registry.d.ts +2 -0
  176. package/dist/src/release-notes.d.ts +6 -1
  177. package/dist/src/release-notes.js +192 -4
  178. package/dist/src/release-notes.test.js +143 -4
  179. package/dist/src/root-command-surface.d.ts +31 -0
  180. package/dist/src/root-command-surface.js +106 -0
  181. package/dist/src/serialization.d.ts +1 -16
  182. package/dist/src/serialization.js +5 -55
  183. package/dist/src/stream-write.d.ts +12 -0
  184. package/dist/src/stream-write.js +91 -0
  185. package/dist/src/stream-write.test.d.ts +1 -0
  186. package/dist/src/stream-write.test.js +186 -0
  187. package/dist/src/types.d.ts +5 -0
  188. package/dist/src/utils.d.ts +1 -1
  189. package/dist/src/utils.js +2 -8
  190. package/dist/src/utils.test.js +50 -0
  191. package/hosted-contract.json +36748 -0
  192. package/package.json +6 -1
  193. package/scripts/check-hosted-contract.mjs +108 -0
  194. package/scripts/docs-sync-review.ts +332 -0
  195. package/scripts/generate-release-notes.ts +1 -1
  196. package/scripts/sync-community-plugins.ts +14 -0
  197. package/skills/smart-search/SKILL.md +14 -3
  198. package/skills/webcmd-autofix/SKILL.md +26 -37
  199. package/skills/webcmd-usage/SKILL.md +21 -7
  200. package/clis/antigravity/SKILL.md +0 -38
@@ -0,0 +1,510 @@
1
+ import { attachTraceReceipt, CliError, EXIT_CODES } from '../errors.js';
2
+ export class HostedClientError extends CliError {
3
+ execution;
4
+ trace;
5
+ constructor(code, message, help, exitCode = EXIT_CODES.GENERIC_ERROR, metadata = {}) {
6
+ super(code, message, help, exitCode);
7
+ this.execution = metadata.execution;
8
+ this.trace = metadata.trace;
9
+ if (metadata.trace)
10
+ attachTraceReceipt(this, metadata.trace);
11
+ }
12
+ }
13
+ export class HostedClient {
14
+ apiBaseUrl;
15
+ apiKey;
16
+ fetchImpl;
17
+ constructor(options) {
18
+ this.apiBaseUrl = options.apiBaseUrl.replace(/\/+$/, '');
19
+ this.apiKey = options.apiKey;
20
+ this.fetchImpl = options.fetchImpl ?? fetch;
21
+ }
22
+ async getMe() {
23
+ return this.request('/v1/me');
24
+ }
25
+ async getManifest() {
26
+ const body = await this.request('/v1/manifest');
27
+ if (!hasExactKeys(body, ['ok', 'manifest']) || !isHostedManifest(body.manifest)) {
28
+ throw protocolError('Webcmd Cloud returned an invalid manifest.');
29
+ }
30
+ return body.manifest;
31
+ }
32
+ async listProfiles() {
33
+ const body = await this.request('/v1/profiles');
34
+ if (!isHostedProfilesResponse(body)) {
35
+ throw protocolError('Webcmd Cloud returned an invalid profiles response.');
36
+ }
37
+ return body;
38
+ }
39
+ async execute(input) {
40
+ const traceMode = normalizeTraceMode(input.trace);
41
+ const body = await this.request('/v1/execute', {
42
+ method: 'POST',
43
+ body: JSON.stringify(input),
44
+ }, { command: input.command, traceMode });
45
+ if (!isHostedExecuteResponse(body, input.command, traceMode)) {
46
+ throw protocolError('Webcmd Cloud returned an invalid execution response.');
47
+ }
48
+ return body;
49
+ }
50
+ async prepareExecution(input) {
51
+ const body = await this.request('/v1/executions', {
52
+ method: 'POST',
53
+ body: JSON.stringify(input),
54
+ });
55
+ if (!isHostedPrepareExecutionResponse(body, input.command)) {
56
+ throw protocolError('Webcmd Cloud returned an invalid prepared execution response.');
57
+ }
58
+ return body;
59
+ }
60
+ async uploadExecutionArtifact(input) {
61
+ const body = await this.request(`/v1/executions/${encodeURIComponent(input.executionId)}/artifacts/${encodeURIComponent(input.argument)}`, {
62
+ method: 'POST',
63
+ headers: {
64
+ 'content-type': 'application/octet-stream',
65
+ 'x-webcmd-filename': input.filename,
66
+ 'x-webcmd-content-type': input.contentType,
67
+ },
68
+ body: input.body,
69
+ });
70
+ if (!isHostedUploadArtifactResponse(body, input.argument)) {
71
+ throw protocolError('Webcmd Cloud returned an invalid artifact upload response.');
72
+ }
73
+ return body;
74
+ }
75
+ async runPreparedExecution(input) {
76
+ const traceMode = normalizeTraceMode(input.trace);
77
+ const body = await this.request(`/v1/executions/${encodeURIComponent(input.executionId)}/run`, {
78
+ method: 'POST',
79
+ body: JSON.stringify({
80
+ command: input.command,
81
+ args: input.args,
82
+ ...(input.format !== undefined ? { format: input.format } : {}),
83
+ ...(input.trace !== undefined ? { trace: input.trace } : {}),
84
+ ...(input.profile !== undefined ? { profile: input.profile } : {}),
85
+ }),
86
+ }, { command: input.command, traceMode });
87
+ if (!isHostedExecuteResponse(body, input.command, traceMode)) {
88
+ throw protocolError('Webcmd Cloud returned an invalid execution response.');
89
+ }
90
+ return body;
91
+ }
92
+ async downloadExecutionArtifact(input) {
93
+ const response = await this.fetchImpl(`${this.apiBaseUrl}/v1/executions/${encodeURIComponent(input.executionId)}/artifacts/${encodeURIComponent(input.artifactId)}`, {
94
+ headers: {
95
+ accept: 'application/octet-stream',
96
+ authorization: `Bearer ${this.apiKey}`,
97
+ },
98
+ });
99
+ if (!response.ok) {
100
+ const text = await response.text();
101
+ const body = text ? parseJson(text) : {};
102
+ if (!isHostedError(body))
103
+ throw protocolError('Webcmd Cloud returned an invalid artifact download failure.');
104
+ const error = body.error;
105
+ throw new HostedClientError(error.code, error.message, error.help, normalizeExitCode(error.exitCode, response.status === 401 ? EXIT_CODES.NOPERM : EXIT_CODES.GENERIC_ERROR), {
106
+ ...(body.execution ? { execution: body.execution } : {}),
107
+ ...(body.trace ? { trace: body.trace } : {}),
108
+ });
109
+ }
110
+ return new Uint8Array(await response.arrayBuffer());
111
+ }
112
+ async startBrowserRun(session, input) {
113
+ const body = await this.request(`/v1/browser/${encodeURIComponent(session)}/runs`, {
114
+ method: 'POST',
115
+ body: JSON.stringify(input),
116
+ });
117
+ if (!isHostedBrowserRunResponse(body, session)) {
118
+ throw protocolError('Webcmd Cloud returned an invalid browser run response.');
119
+ }
120
+ return body;
121
+ }
122
+ async browserAction(session, executionId, input) {
123
+ const body = await this.request(`/v1/browser/${encodeURIComponent(session)}/runs/${encodeURIComponent(executionId)}/actions`, {
124
+ method: 'POST',
125
+ body: JSON.stringify(input),
126
+ });
127
+ if (!isHostedBrowserActionResponse(body)) {
128
+ throw protocolError('Webcmd Cloud returned an invalid browser action response.');
129
+ }
130
+ return body;
131
+ }
132
+ async finishBrowserRun(session, executionId, input) {
133
+ const body = await this.request(`/v1/browser/${encodeURIComponent(session)}/runs/${encodeURIComponent(executionId)}/finish`, {
134
+ method: 'POST',
135
+ body: JSON.stringify(input),
136
+ });
137
+ if (!isHostedBrowserFinishResponse(body, executionId, input.status)) {
138
+ throw protocolError('Webcmd Cloud returned an invalid browser finish response.');
139
+ }
140
+ return body;
141
+ }
142
+ async runBrowserAction(session, input) {
143
+ return this.executeBrowserCommand(session, input);
144
+ }
145
+ async executeBrowserCommand(session, input) {
146
+ const body = await this.request(`/v1/browser/${encodeURIComponent(session)}/commands`, {
147
+ method: 'POST',
148
+ body: JSON.stringify(input),
149
+ });
150
+ if (!isHostedBrowserRunActionResponse(body, session)) {
151
+ throw protocolError('Webcmd Cloud returned an invalid browser action response.');
152
+ }
153
+ return body;
154
+ }
155
+ async request(path, init = {}, executionExpectation) {
156
+ const response = await this.fetchImpl(`${this.apiBaseUrl}${path}`, {
157
+ ...init,
158
+ headers: {
159
+ accept: 'application/json',
160
+ ...(init.body ? { 'content-type': 'application/json' } : {}),
161
+ authorization: `Bearer ${this.apiKey}`,
162
+ ...(init.headers ?? {}),
163
+ },
164
+ });
165
+ const text = await response.text();
166
+ const body = text ? parseJson(text) : {};
167
+ if (!isRecord(body) || (body.ok !== true && body.ok !== false)) {
168
+ throw protocolError('Webcmd Cloud returned an invalid response envelope.');
169
+ }
170
+ if (body.ok === false) {
171
+ if (!isHostedError(body))
172
+ throw protocolError('Webcmd Cloud returned an invalid failure response.');
173
+ if (body.execution && !isValidExecutedFailure(body, executionExpectation)) {
174
+ throw protocolError('Webcmd Cloud returned an invalid executed failure response.');
175
+ }
176
+ const error = body.error;
177
+ throw new HostedClientError(error.code, error.message, error.help, normalizeExitCode(error.exitCode, response.status === 401 ? EXIT_CODES.NOPERM : EXIT_CODES.GENERIC_ERROR), {
178
+ ...(body.execution ? { execution: body.execution } : {}),
179
+ ...(body.trace ? { trace: body.trace } : {}),
180
+ });
181
+ }
182
+ if (!response.ok)
183
+ throw protocolError('Webcmd Cloud returned a success envelope with an HTTP error status.');
184
+ return body;
185
+ }
186
+ }
187
+ function parseJson(text) {
188
+ try {
189
+ return JSON.parse(text);
190
+ }
191
+ catch {
192
+ throw protocolError('Webcmd Cloud returned non-JSON response.');
193
+ }
194
+ }
195
+ function isHostedError(value) {
196
+ if (!hasOnlyKeys(value, ['ok', 'error', 'execution', 'trace']) || value.ok !== false || !isRecord(value.error))
197
+ return false;
198
+ if (!hasOnlyKeys(value.error, ['code', 'message', 'help', 'exitCode']))
199
+ return false;
200
+ if (typeof value.error.code !== 'string' || typeof value.error.message !== 'string')
201
+ return false;
202
+ if (value.error.exitCode !== undefined
203
+ && (typeof value.error.exitCode !== 'number' || !isAllowedExitCode(value.error.exitCode)))
204
+ return false;
205
+ if (value.error.help !== undefined && typeof value.error.help !== 'string')
206
+ return false;
207
+ if (value.execution !== undefined && !isHostedExecution(value.execution))
208
+ return false;
209
+ if (value.trace !== undefined && !isHostedTraceReceipt(value.trace))
210
+ return false;
211
+ if (value.execution?.status === 'succeeded')
212
+ return false;
213
+ if (value.trace && (!value.execution || value.trace.executionId !== value.execution.id))
214
+ return false;
215
+ return true;
216
+ }
217
+ function isHostedManifest(value) {
218
+ return hasExactKeys(value, ['userId', 'metadata', 'commands'])
219
+ && typeof value.userId === 'string'
220
+ && hasExactKeys(value.metadata, ['contractSchemaVersion', 'webcmdPackageVersion', 'generatedAt'])
221
+ && typeof value.metadata.contractSchemaVersion === 'number'
222
+ && Number.isInteger(value.metadata.contractSchemaVersion)
223
+ && value.metadata.contractSchemaVersion > 0
224
+ && typeof value.metadata.webcmdPackageVersion === 'string'
225
+ && typeof value.metadata.generatedAt === 'string'
226
+ && Array.isArray(value.commands)
227
+ && value.commands.every(isHostedManifestCommand);
228
+ }
229
+ function isHostedExecuteResponse(value, requestedCommand, traceMode) {
230
+ if (!hasOnlyKeys(value, ['ok', 'result', 'columns', 'footerExtra', 'execution', 'trace', 'artifacts'])
231
+ || value.ok !== true
232
+ || !Object.prototype.hasOwnProperty.call(value, 'result'))
233
+ return false;
234
+ if (!isHostedExecution(value.execution) || value.execution.status !== 'succeeded')
235
+ return false;
236
+ if (value.execution.command !== requestedCommand)
237
+ return false;
238
+ if (value.columns !== undefined && (!Array.isArray(value.columns) || !value.columns.every(column => typeof column === 'string'))) {
239
+ return false;
240
+ }
241
+ if (value.footerExtra !== undefined && typeof value.footerExtra !== 'string')
242
+ return false;
243
+ if (value.artifacts !== undefined && (!Array.isArray(value.artifacts) || !value.artifacts.every(isHostedArtifactReceipt)))
244
+ return false;
245
+ if (value.trace !== undefined && !isHostedTraceReceipt(value.trace))
246
+ return false;
247
+ if (value.trace && value.trace.executionId !== value.execution.id)
248
+ return false;
249
+ if (traceMode === 'on' ? !value.trace : value.trace !== undefined)
250
+ return false;
251
+ return true;
252
+ }
253
+ function isHostedPrepareExecutionResponse(value, requestedCommand) {
254
+ return hasExactKeys(value, ['ok', 'execution', 'fileArguments'])
255
+ && value.ok === true
256
+ && hasExactKeys(value.execution, ['id', 'command', 'status'])
257
+ && typeof value.execution.id === 'string'
258
+ && value.execution.command === requestedCommand
259
+ && value.execution.status === 'queued'
260
+ && Array.isArray(value.fileArguments)
261
+ && value.fileArguments.every(isHostedFileArgument);
262
+ }
263
+ function isHostedUploadArtifactResponse(value, argument) {
264
+ if (!hasExactKeys(value, ['ok', 'artifact', 'reference']) || value.ok !== true)
265
+ return false;
266
+ const artifact = value.artifact;
267
+ if (!isHostedArtifactReceipt(artifact))
268
+ return false;
269
+ if (artifact.argument !== argument)
270
+ return false;
271
+ if (!hasExactKeys(value.reference, ['$webcmdArtifact']))
272
+ return false;
273
+ const reference = value.reference.$webcmdArtifact;
274
+ return hasOnlyKeys(reference, ['id', 'direction', 'filename', 'contentType'])
275
+ && typeof reference.id === 'string'
276
+ && (reference.direction === undefined || reference.direction === 'input');
277
+ }
278
+ function isHostedProfilesResponse(value) {
279
+ return hasExactKeys(value, ['ok', 'profiles'])
280
+ && value.ok === true
281
+ && Array.isArray(value.profiles)
282
+ && value.profiles.every(isHostedPublicProfile);
283
+ }
284
+ function isHostedPublicProfile(value) {
285
+ return hasExactKeys(value, ['name', 'default', 'status', 'createdAt', 'lastUsedAt'])
286
+ && typeof value.name === 'string'
287
+ && typeof value.default === 'boolean'
288
+ && value.status === 'available'
289
+ && typeof value.createdAt === 'string'
290
+ && typeof value.lastUsedAt === 'string';
291
+ }
292
+ function isHostedManifestCommand(value) {
293
+ if (!hasOnlyKeys(value, [
294
+ 'site', 'name', 'aliases', 'command', 'description', 'access', 'example', 'domain', 'strategy', 'browser',
295
+ 'args', 'columns', 'pipeline', 'defaultFormat', 'type', 'modulePath', 'sourceFile', 'navigateBefore',
296
+ 'siteSession', 'defaultWindowMode', 'adapterPackageId', 'adapterPackageName', 'adapterPackageVersion',
297
+ ]))
298
+ return false;
299
+ if (typeof value.site !== 'string' || typeof value.name !== 'string' || typeof value.command !== 'string')
300
+ return false;
301
+ if (typeof value.description !== 'string' || typeof value.access !== 'string' || typeof value.strategy !== 'string')
302
+ return false;
303
+ if (typeof value.browser !== 'boolean' || !Array.isArray(value.args) || !value.args.every(isHostedManifestArg))
304
+ return false;
305
+ if (value.aliases !== undefined && (!Array.isArray(value.aliases) || !value.aliases.every(item => typeof item === 'string')))
306
+ return false;
307
+ if (!Array.isArray(value.columns) || !value.columns.every(item => typeof item === 'string'))
308
+ return false;
309
+ if (value.domain !== undefined && value.domain !== null && typeof value.domain !== 'string')
310
+ return false;
311
+ if (value.defaultFormat !== undefined && value.defaultFormat !== null && typeof value.defaultFormat !== 'string')
312
+ return false;
313
+ if (value.example !== undefined && typeof value.example !== 'string')
314
+ return false;
315
+ if (value.pipeline !== undefined && (!Array.isArray(value.pipeline) || !value.pipeline.every(isRecord)))
316
+ return false;
317
+ for (const key of ['type', 'modulePath', 'sourceFile', 'siteSession', 'defaultWindowMode', 'adapterPackageId', 'adapterPackageName', 'adapterPackageVersion']) {
318
+ if (value[key] !== undefined && typeof value[key] !== 'string')
319
+ return false;
320
+ }
321
+ return value.navigateBefore === undefined || typeof value.navigateBefore === 'boolean' || typeof value.navigateBefore === 'string';
322
+ }
323
+ function isHostedManifestArg(value) {
324
+ if (!hasOnlyKeys(value, ['name', 'type', 'required', 'default', 'valueRequired', 'positional', 'help', 'choices', 'file']))
325
+ return false;
326
+ if (typeof value.name !== 'string')
327
+ return false;
328
+ if (value.type !== undefined && typeof value.type !== 'string')
329
+ return false;
330
+ for (const key of ['required', 'valueRequired', 'positional']) {
331
+ if (value[key] !== undefined && typeof value[key] !== 'boolean')
332
+ return false;
333
+ }
334
+ if (value.help !== undefined && typeof value.help !== 'string')
335
+ return false;
336
+ if (value.file !== undefined && !isHostedArgFileMetadata(value.file))
337
+ return false;
338
+ return value.choices === undefined
339
+ || (Array.isArray(value.choices) && value.choices.every(choice => typeof choice === 'string'));
340
+ }
341
+ function isHostedArgFileMetadata(value) {
342
+ return hasOnlyKeys(value, ['direction', 'pathKind', 'multiple', 'separator', 'contentTypes', 'contentType', 'maxBytes', 'defaultPath'])
343
+ && (value.direction === 'input' || value.direction === 'output')
344
+ && (value.pathKind === 'file' || value.pathKind === 'directory')
345
+ && typeof value.multiple === 'boolean'
346
+ && (value.separator === undefined || value.separator === ',')
347
+ && (value.contentTypes === undefined || (Array.isArray(value.contentTypes) && value.contentTypes.every(item => typeof item === 'string')))
348
+ && (value.contentType === undefined || typeof value.contentType === 'string')
349
+ && (value.maxBytes === undefined || (typeof value.maxBytes === 'number' && Number.isFinite(value.maxBytes) && value.maxBytes > 0))
350
+ && (value.defaultPath === undefined || typeof value.defaultPath === 'string');
351
+ }
352
+ function isHostedFileArgument(value) {
353
+ return hasOnlyKeys(value, ['name', 'direction', 'pathKind', 'multiple', 'required', 'separator', 'contentTypes', 'contentType', 'maxBytes', 'defaultPath'])
354
+ && typeof value.name === 'string'
355
+ && (value.direction === 'input' || value.direction === 'output')
356
+ && (value.pathKind === 'file' || value.pathKind === 'directory')
357
+ && typeof value.multiple === 'boolean'
358
+ && typeof value.required === 'boolean'
359
+ && (value.separator === undefined || value.separator === ',')
360
+ && (value.contentTypes === undefined || (Array.isArray(value.contentTypes) && value.contentTypes.every(item => typeof item === 'string')))
361
+ && (value.contentType === undefined || typeof value.contentType === 'string')
362
+ && (value.maxBytes === undefined || (typeof value.maxBytes === 'number' && Number.isFinite(value.maxBytes) && value.maxBytes > 0))
363
+ && (value.defaultPath === undefined || typeof value.defaultPath === 'string');
364
+ }
365
+ function isHostedArtifactReceipt(value) {
366
+ return hasOnlyKeys(value, [
367
+ 'artifactId', 'argument', 'direction', 'pathKind', 'filename', 'contentType',
368
+ 'byteSize', 'sha256', 'relativePath', 'expiresAt',
369
+ ])
370
+ && typeof value.artifactId === 'string'
371
+ && typeof value.argument === 'string'
372
+ && (value.direction === 'input' || value.direction === 'output')
373
+ && (value.pathKind === 'file' || value.pathKind === 'directory')
374
+ && typeof value.filename === 'string'
375
+ && typeof value.contentType === 'string'
376
+ && typeof value.byteSize === 'number'
377
+ && Number.isInteger(value.byteSize)
378
+ && value.byteSize >= 0
379
+ && (value.sha256 === undefined || typeof value.sha256 === 'string')
380
+ && (value.relativePath === undefined || isSafeRelativeArtifactPath(value.relativePath))
381
+ && typeof value.expiresAt === 'string';
382
+ }
383
+ function isSafeRelativeArtifactPath(value) {
384
+ return typeof value === 'string'
385
+ && value.length > 0
386
+ && !value.startsWith('/')
387
+ && !value.includes('\\')
388
+ && !value.split('/').some(segment => !segment || segment === '.' || segment === '..' || segment.includes('\0'));
389
+ }
390
+ function isHostedBrowserRunResponse(value, requestedSession) {
391
+ return hasExactKeys(value, ['ok', 'run']) && value.ok === true && isHostedBrowserRunPayload(value.run, requestedSession);
392
+ }
393
+ function isHostedBrowserRunPayload(value, requestedSession) {
394
+ const run = value;
395
+ if (!hasOnlyKeys(run, ['executionId', 'session', 'profile', 'liveViewUrl']))
396
+ return false;
397
+ if (typeof run.executionId !== 'string' || run.session !== requestedSession)
398
+ return false;
399
+ if (!hasExactKeys(run.profile, ['id', 'displayName']))
400
+ return false;
401
+ if (typeof run.profile.id !== 'string' || typeof run.profile.displayName !== 'string')
402
+ return false;
403
+ return run.liveViewUrl === undefined || typeof run.liveViewUrl === 'string';
404
+ }
405
+ function isHostedBrowserActionResponse(value) {
406
+ if (!hasExactKeys(value, ['ok', 'result', 'columns', 'trace']) || value.ok !== true)
407
+ return false;
408
+ if (!Array.isArray(value.columns) || !value.columns.every(column => typeof column === 'string'))
409
+ return false;
410
+ return value.trace === null || isHostedBrowserActionTrace(value.trace);
411
+ }
412
+ function isHostedBrowserRunActionResponse(value, requestedSession) {
413
+ if (!hasExactKeys(value, ['ok', 'result', 'columns', 'trace', 'run', 'execution']) || value.ok !== true)
414
+ return false;
415
+ if (!Array.isArray(value.columns) || !value.columns.every(column => typeof column === 'string'))
416
+ return false;
417
+ if (value.trace !== null && !isHostedBrowserActionTrace(value.trace))
418
+ return false;
419
+ if (!isHostedBrowserRunPayload(value.run, requestedSession))
420
+ return false;
421
+ return hasExactKeys(value.execution, ['id', 'status'])
422
+ && typeof value.execution.id === 'string'
423
+ && value.execution.id === value.run.executionId
424
+ && (value.execution.status === 'succeeded' || value.execution.status === 'failed' || value.execution.status === 'timed_out');
425
+ }
426
+ function isHostedBrowserActionTrace(value) {
427
+ if (!hasOnlyKeys(value, ['id', 'receipt', 'kind', 'contentType', 'byteSize', 'storagePath']))
428
+ return false;
429
+ if (typeof value.id !== 'string' || typeof value.receipt !== 'string' || typeof value.kind !== 'string')
430
+ return false;
431
+ if (value.contentType !== undefined && typeof value.contentType !== 'string')
432
+ return false;
433
+ if (value.byteSize !== undefined
434
+ && (typeof value.byteSize !== 'number' || !Number.isInteger(value.byteSize) || value.byteSize < 0))
435
+ return false;
436
+ return value.storagePath === undefined || typeof value.storagePath === 'string';
437
+ }
438
+ function isHostedBrowserFinishResponse(value, executionId, status) {
439
+ return hasExactKeys(value, ['ok', 'execution'])
440
+ && value.ok === true
441
+ && hasExactKeys(value.execution, ['id', 'status'])
442
+ && value.execution.id === executionId
443
+ && value.execution.status === status;
444
+ }
445
+ function isHostedExecution(value) {
446
+ return hasExactKeys(value, ['id', 'command', 'status'])
447
+ && typeof value.id === 'string'
448
+ && typeof value.command === 'string'
449
+ && (value.status === 'succeeded' || value.status === 'failed' || value.status === 'timed_out');
450
+ }
451
+ function isHostedTraceReceipt(value) {
452
+ if (!hasOnlyKeys(value, ['receipt', 'executionId', 'artifactsUrl', 'liveViewUrl', 'replayUrl'])
453
+ || !isSafeReceiptToken(value.receipt)
454
+ || !isSafeReceiptToken(value.executionId))
455
+ return false;
456
+ const executionBase = publicExecutionBase(value.executionId);
457
+ if (!executionBase)
458
+ return false;
459
+ return optionalExactPath(value.artifactsUrl, `${executionBase}/artifacts`)
460
+ && optionalExactPath(value.liveViewUrl, `${executionBase}/live`)
461
+ && optionalExactPath(value.replayUrl, `${executionBase}/replay`);
462
+ }
463
+ function publicExecutionBase(executionId) {
464
+ try {
465
+ const encoded = encodeURIComponent(executionId);
466
+ if (encoded === '.' || encoded === '..')
467
+ return undefined;
468
+ return `/v1/executions/${encoded}`;
469
+ }
470
+ catch {
471
+ return undefined;
472
+ }
473
+ }
474
+ function optionalExactPath(value, expected) {
475
+ return value === undefined || value === expected;
476
+ }
477
+ function isSafeReceiptToken(value) {
478
+ return typeof value === 'string'
479
+ && value.length > 0
480
+ && !/[\u0000-\u001f\u007f\u2028\u2029]/u.test(value);
481
+ }
482
+ function isRecord(value) {
483
+ return !!value && typeof value === 'object' && !Array.isArray(value);
484
+ }
485
+ function hasOnlyKeys(value, allowed) {
486
+ return isRecord(value) && Object.keys(value).every(key => allowed.includes(key));
487
+ }
488
+ function hasExactKeys(value, expected) {
489
+ return hasOnlyKeys(value, expected) && expected.every(key => Object.prototype.hasOwnProperty.call(value, key));
490
+ }
491
+ function isAllowedExitCode(value) {
492
+ return Object.values(EXIT_CODES).includes(value);
493
+ }
494
+ function normalizeExitCode(value, fallback) {
495
+ return value !== undefined && isAllowedExitCode(value) ? value : fallback;
496
+ }
497
+ function protocolError(message) {
498
+ return new HostedClientError('HOSTED_PROTOCOL', message);
499
+ }
500
+ function normalizeTraceMode(value) {
501
+ return value === 'on' || value === 'retain-on-failure' ? value : 'off';
502
+ }
503
+ function isValidExecutedFailure(value, expectation) {
504
+ if (!value.execution || !expectation || value.error.exitCode === undefined)
505
+ return false;
506
+ if (value.execution.command !== expectation.command)
507
+ return false;
508
+ const traceRequired = expectation.traceMode === 'on' || expectation.traceMode === 'retain-on-failure';
509
+ return traceRequired ? value.trace !== undefined : value.trace === undefined;
510
+ }
@@ -0,0 +1 @@
1
+ export {};