@parall/parall 1.54.0 → 1.55.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.
- package/dist/index.bundle.mjs +1076 -1057
- package/package.json +3 -3
- package/skills/parall-clip-authoring/SKILL.md +54 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@parall/parall",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.55.1",
|
|
4
4
|
"description": "OpenClaw channel plugin for Parall IM",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"openclaw.plugin.json"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@parall/agent-core": "1.
|
|
20
|
-
"@parall/sdk": "1.
|
|
19
|
+
"@parall/agent-core": "1.55.1",
|
|
20
|
+
"@parall/sdk": "1.55.1"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"@types/node": "^22.0.0",
|
|
@@ -114,6 +114,7 @@ function parseTweets(data) { /* ... */ }
|
|
|
114
114
|
- `tab.cookie(name)` · `tab.fetch(url, opts)` (in-browser fetch, carries the session)
|
|
115
115
|
- `tab.eval(expr)` (escape hatch) · `tab.click(sel)` · `tab.fill(sel, text)` · `tab.navigate(url)`
|
|
116
116
|
- `tab.waitForSelector(sel)` · `tab.getTitle()` · `tab.getURL()` · `tab.screenshot()` · `tab.close()`
|
|
117
|
+
- `tab.setFileInput(sel, url, opts?)` — upload a file into an `<input type=file>`
|
|
117
118
|
- `fetch` — runtime-side HTTP, does NOT go through the browser (no session)
|
|
118
119
|
- `console` — logs · `args` — the invocation input
|
|
119
120
|
|
|
@@ -122,6 +123,40 @@ returns structured data; eval is the last resort. Always `tab.close()` what you
|
|
|
122
123
|
open, and do it in a `finally` — an early return or a thrown fetch is exactly
|
|
123
124
|
when the tab leaks.
|
|
124
125
|
|
|
126
|
+
### Uploading a file
|
|
127
|
+
|
|
128
|
+
`tab.setFileInput` takes a URL, never a path, and the runtime — not the page —
|
|
129
|
+
fetches the bytes. That is what makes it work where an in-page `fetch` +
|
|
130
|
+
`DataTransfer` cannot: upload targets ship a Content-Security-Policy that
|
|
131
|
+
forbids the page from fetching an arbitrary file host (Instagram's `default-src`
|
|
132
|
+
allows only its own domains), and you cannot change a header on their site. The
|
|
133
|
+
runtime is not a page, so no CSP applies to it — and a large video never has to
|
|
134
|
+
pass through the page's memory.
|
|
135
|
+
|
|
136
|
+
```js
|
|
137
|
+
await tab.setFileInput("input[type=file]", videoUrl, { filename: "clip.mp4" });
|
|
138
|
+
await tab.click("button[type=submit]");
|
|
139
|
+
await tab.waitForSelector(".upload-complete"); // ← do not skip this
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Four rules that decide whether your clip works:
|
|
143
|
+
|
|
144
|
+
1. **The URL must be fetchable with no credentials** — a public direct link or a
|
|
145
|
+
signed temporary one. The runtime sends no cookies, so a Drive or Feishu link
|
|
146
|
+
copied from the address bar will not work: those are HTML pages behind a
|
|
147
|
+
login. If the file needs a session, use a logged-in tab to obtain a signed
|
|
148
|
+
direct link first, then pass THAT here. An HTML answer is refused with
|
|
149
|
+
`EDGE_FILE_SOURCE_NOT_A_FILE` rather than uploaded as if it were a file.
|
|
150
|
+
2. **Finish the upload inside the same command.** The browser reads the file when
|
|
151
|
+
the page submits, and the runtime deletes it when your command ends. Injecting
|
|
152
|
+
and returning immediately uploads nothing — wait for the site to confirm.
|
|
153
|
+
3. **Main-document inputs only.** An input inside an iframe or a shadow root is
|
|
154
|
+
not addressable and returns `EDGE_FILE_SELECTOR_MISS`. If the page rebuilds
|
|
155
|
+
the input after you inject (navigation, re-render), inject again.
|
|
156
|
+
4. **`opts.filename` is what the page sees**, and many sites validate by
|
|
157
|
+
extension — set it when the URL has none. `opts.timeoutMs` bounds the
|
|
158
|
+
download. One file per call; there is no multi-file form yet.
|
|
159
|
+
|
|
125
160
|
## Develop → publish → iterate
|
|
126
161
|
|
|
127
162
|
Use the platform `parall clip` subcommands — they reuse the credentials you
|
|
@@ -228,18 +263,30 @@ and the folder is just a manifest:
|
|
|
228
263
|
}
|
|
229
264
|
```
|
|
230
265
|
|
|
231
|
-
- The `mcp` block takes ONLY `server_url
|
|
232
|
-
"
|
|
233
|
-
|
|
234
|
-
definition.
|
|
266
|
+
- The `mcp` block takes ONLY `server_url`, `auth` (`"none" | "api_key" |
|
|
267
|
+
"basic" | "oauth"`, legacy `"bearer"` accepted) and `auth_headers`. Any
|
|
268
|
+
other key is refused at publish — a credential belongs to the installing
|
|
269
|
+
org's own configuration, NEVER to the clip definition.
|
|
270
|
+
- `auth` is REQUIRED at publish: you know what your server speaks, and this
|
|
271
|
+
one word decides what the install form asks for (`none` = zero input,
|
|
272
|
+
`api_key` = key field(s), `basic` = username + password, `oauth` = a
|
|
273
|
+
Connect button).
|
|
274
|
+
- `api_key` delivers as a single `X-API-Key` header by default. When the
|
|
275
|
+
server wants a different shape, declare `auth_headers` (max 4 slots, one
|
|
276
|
+
admin-supplied value each): `[{"name": "Authorization", "scheme":
|
|
277
|
+
"Bearer"}]` for Bearer tokens, `[{"name": "api-key"}]` for a custom
|
|
278
|
+
header, or a pair like `[{"name": "CF-Access-Client-Id"}, {"name":
|
|
279
|
+
"CF-Access-Client-Secret"}]`. Framing/platform headers (Host, Cookie,
|
|
280
|
+
X-Prll-*, …) are refused.
|
|
235
281
|
- `server_url` must be an absolute **https** URL with no embedded credentials,
|
|
236
282
|
query, or fragment. It is review material, frozen with the approved version.
|
|
283
|
+
It stays OPTIONAL for self-hosted products where each org connects its own
|
|
284
|
+
instance URL.
|
|
237
285
|
- Do NOT put the server in the top-level `server` / `auth` manifest keys —
|
|
238
286
|
those are legacy Edge-manifest fields nothing reads. Only the `mcp` block
|
|
239
287
|
declares the server.
|
|
240
|
-
-
|
|
241
|
-
|
|
242
|
-
republishing.
|
|
288
|
+
- What you declare is LOCKED: the installing org's config must match it, and
|
|
289
|
+
changing the URL, auth mode, or header shape means republishing.
|
|
243
290
|
- Entering the credential / completing OAuth is a HUMAN step in the Clip
|
|
244
291
|
Console (the config-write endpoints are session-only — an API key cannot
|
|
245
292
|
call them). An org can add SEVERAL connections to one MCP clip — one
|