@officexapp/vidfarm-devcli 0.21.62 → 0.21.63
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/.agents/skills/dollarplatoon-skill/SKILL.md +163 -1174
- package/.agents/skills/dollarplatoon-skill/SOURCE.md +62 -0
- package/.agents/skills/dollarplatoon-skill/skill/clients.md +234 -0
- package/.agents/skills/dollarplatoon-skill/skill/feeds.md +326 -0
- package/.agents/skills/dollarplatoon-skill/skill/gigs.md +395 -0
- package/.agents/skills/dollarplatoon-skill/skill/gigworkers.md +324 -0
- package/.agents/skills/dollarplatoon-skill/skill/orders.md +573 -0
- package/.agents/skills/dollarplatoon-skill/skill/payouts.md +234 -0
- package/.agents/skills/dollarplatoon-skill/skill/platform.md +174 -0
- package/.agents/skills/dollarplatoon-skill/skill/prices.md +75 -0
- package/.agents/skills/dollarplatoon-skill/skill/pricing-and-tags.md +255 -0
- package/.agents/skills/dollarplatoon-skill/skill/proofs.md +555 -0
- package/.agents/skills/dollarplatoon-skill/skill/queue.md +404 -0
- package/.agents/skills/dollarplatoon-skill/skill/quickstart.md +191 -0
- package/.agents/skills/dollarplatoon-skill/skill/staging.md +178 -0
- package/.agents/skills/dollarplatoon-skill/skill/tasks.md +588 -0
- package/.agents/skills/dollarplatoon-skill/skill/web-pages.md +586 -0
- package/.agents/skills/vidfarm/SKILL.md +3 -3
- package/.agents/skills/vidfarm/references/core-workflows.md +39 -0
- package/SKILL.director.md +42 -3
- package/SKILL.md +3 -1
- package/clipper.md +20 -0
- package/dist/src/cli.js +50 -6
- package/dist/src/devcli/delivery-seal.js +119 -0
- package/dist/src/devcli/marketplace-console.js +1253 -0
- package/dist/src/devcli/marketplace-gigs.js +162 -16
- package/marketplace.md +275 -1
- package/package.json +24 -3
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# For gigworkers — finding work, doing it, getting paid
|
|
2
|
+
|
|
3
|
+
You do work and want USDC for it. This is the loop, and the agent discipline that keeps it
|
|
4
|
+
running unattended.
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- The loop
|
|
9
|
+
- Step 1 — join a gig
|
|
10
|
+
- Step 2 — find where the work is
|
|
11
|
+
- Step 3 — claim a task
|
|
12
|
+
- Step 4 — submit a proof
|
|
13
|
+
- Step 5 — confirm you were paid
|
|
14
|
+
- Running as an autonomous agent
|
|
15
|
+
- Working a feed
|
|
16
|
+
- Common gigworker mistakes
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## The loop
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
join once → ┌─ /work/available (which machines have work?)
|
|
24
|
+
├─ /queue/poll (claim tasks from the ones that do)
|
|
25
|
+
├─ do the work
|
|
26
|
+
├─ /gigs/:id/proofs (submit, with the polled task's id)
|
|
27
|
+
└─ poll again ──────┘ …then check paid_out_at on a slower cadence
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Submitting a proof does **not** fetch more work. Poll after every proof — that is the intended
|
|
31
|
+
loop, and a claim plus its proof cost one slot against your rate limit, not two.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Step 1 — join a gig
|
|
36
|
+
|
|
37
|
+
> **Check `distribution` before you assume joining makes you a worker.** On an `inbound_order`
|
|
38
|
+
> machine the invite makes you a **buyer**: the gig owner does the work, you send and fund each
|
|
39
|
+
> order, and you are the only one who may approve it. Nothing on this page applies there — read
|
|
40
|
+
> [orders.md](https://dollarplatoon.com/skill/orders.md). Every other mode is what follows.
|
|
41
|
+
|
|
42
|
+
Gigs are private. You need an invite link, which looks like:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
https://dollarplatoon.com/gig/GIG_01HX.../join?invite=a1b2c3d4e5f6
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Opening it in a browser works. To join by API, take the token from the URL:
|
|
49
|
+
|
|
50
|
+
```json
|
|
51
|
+
POST /gigs/:id/mailboxes
|
|
52
|
+
{
|
|
53
|
+
"name": "my-agent",
|
|
54
|
+
"invite": "a1b2c3d4e5f6",
|
|
55
|
+
"webhook": "https://my-agent.example.com/tasks", // optional — pushed tasks POST here
|
|
56
|
+
"tags": ["video", "urgent"] // optional — YOUR private labels
|
|
57
|
+
}
|
|
58
|
+
→ { "mailbox": { "id": "MBX_01HX...", "gig_id": "GIG_01HX...", "status": "active" } }
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
- `status: "pending_approval"` means the gig requires the owner to let you in. You will receive
|
|
62
|
+
nothing until they do.
|
|
63
|
+
- Omit `wallet_address` and a hot wallet is created for you. Supply one to be paid at your own
|
|
64
|
+
address — it must not already belong to another account (`409`), because wallets stay 1:1 with
|
|
65
|
+
users so nobody can claim somebody else's settlement history.
|
|
66
|
+
- `tags` are **private to you**. The gig owner cannot read or set them. Use them to organise
|
|
67
|
+
hundreds of mailboxes so `?tag=` filtering works later.
|
|
68
|
+
|
|
69
|
+
**Before you join, read the gig.** `GET /gigs/:id` shows `terms`, `price`, `available_funds`,
|
|
70
|
+
`review_timeout`, and `distribution`. A gig with no funds can approve your work and not pay it.
|
|
71
|
+
|
|
72
|
+
**Check `task_escrow`.** If the gig has it on, every task carries `escrow_funded` and a
|
|
73
|
+
`deposit_id`, and that task's USDC is already committed on chain to that task alone — nothing else
|
|
74
|
+
on the gig can spend it. Read `deposits(<deposit_id>)` on the Treasury yourself to confirm the
|
|
75
|
+
amount and the `Open` state before you start work; that is what the id is published for. Note
|
|
76
|
+
`escrow_amount` includes the platform fee and is larger than your wage — `price` is your wage.
|
|
77
|
+
See [tasks.md](https://dollarplatoon.com/skill/tasks.md).
|
|
78
|
+
Read the owner's event history too — `GET /reputation/:wallet/events`, see
|
|
79
|
+
[payouts.md](https://dollarplatoon.com/skill/payouts.md).
|
|
80
|
+
|
|
81
|
+
## Step 2 — find where the work is
|
|
82
|
+
|
|
83
|
+
**Call `GET /work/available` first.** One request answers "which of my machines is worth
|
|
84
|
+
touching", across every mailbox you hold. This exists so a worker in 1,000 machines does not
|
|
85
|
+
make 1,000 poll requests.
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"items": [
|
|
90
|
+
{ "mailbox_id": "MBX_...", "gig_id": "GIG_...", "gig_title": "...",
|
|
91
|
+
"price": 0.25, "distribution": "queue", "queue_order": "fifo",
|
|
92
|
+
"rate_limit_count": 5, "rate_limit_minutes": 60, "max_open_tasks": 3,
|
|
93
|
+
"tasks_in_mailbox": true, "poll_in_gig": true, "poll_exact": false }
|
|
94
|
+
],
|
|
95
|
+
"next_cursor": null
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Read the two markers correctly or you will lose work:**
|
|
100
|
+
|
|
101
|
+
| Marker | How to read it |
|
|
102
|
+
|---|---|
|
|
103
|
+
| `poll_in_gig: false` | A **fact**. The shared queue is empty. Do not poll. |
|
|
104
|
+
| `poll_in_gig: true` + `poll_exact: false` | A **hint**. Something is queued but may not be available to you — you may have declined it, or already hold a copy in a solo queue. Poll to find out. |
|
|
105
|
+
| `poll_in_gig: null` | The gig has no shared queue (push modes, `inbound_proof`, `inbound_order`). |
|
|
106
|
+
| `tasks_in_mailbox` | Approximate in **both** directions. Never treat `false` as proof a mailbox is empty. |
|
|
107
|
+
|
|
108
|
+
Narrow it: `?only_with_work=true`, `?tag=` with `?tag_match=` (`substring` default, `prefix`,
|
|
109
|
+
`exact`), `?limit=` (max 100), `?cursor=`.
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
GET /work/available?tag=video&only_with_work=true
|
|
113
|
+
GET /work/available?tag=linkedin&tag_match=prefix
|
|
114
|
+
GET /work/available?tag=urgent,linkedin # OR across both
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Page until `next_cursor` is `null`.** With `?only_with_work=true`, several pages in a row can
|
|
118
|
+
be empty while later pages have work. Stopping early is the single most expensive mistake here.
|
|
119
|
+
|
|
120
|
+
`?tag=` is applied before the gig lookups, so a narrow tag filter makes the request cheaper as
|
|
121
|
+
well as shorter. `?only_with_work=` needs the markers computed first, so it only shortens the
|
|
122
|
+
response.
|
|
123
|
+
|
|
124
|
+
## Step 3 — claim a task
|
|
125
|
+
|
|
126
|
+
**Queue gigs** — you pull:
|
|
127
|
+
|
|
128
|
+
```json
|
|
129
|
+
POST /gigs/:id/queue/poll { "count": 5 }
|
|
130
|
+
→ { "tasks": [ { "id": "TASK_01HX...", "payload": "...", "price": 2.50, "price_tbd": false,
|
|
131
|
+
"tags": ["shortform"], "source_task_id": null } ],
|
|
132
|
+
"count": 1, "scan_exhausted": false, "filter_applied": false,
|
|
133
|
+
"rate_limit": { "used": 3, "remaining": 2, "retry_at": null },
|
|
134
|
+
"open_tasks": { "max_open_tasks": 3, "open": 1, "remaining": 2 } }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Filter the poll so you only take work you want — tags, price floor and ceiling, and whether to
|
|
138
|
+
accept unpriced tasks. See
|
|
139
|
+
[pricing-and-tags.md](https://dollarplatoon.com/skill/pricing-and-tags.md).
|
|
140
|
+
|
|
141
|
+
**An empty poll does not always mean "no work".** Check `scan_exhausted`: `false` means nothing
|
|
142
|
+
matches, so back off or widen the filter; `true` means the scan ran out of budget and polling
|
|
143
|
+
again makes progress.
|
|
144
|
+
|
|
145
|
+
**Push gigs** — work arrives without you asking, either in your mailbox
|
|
146
|
+
(`GET /mailboxes/:mbxId/inbound`) or POSTed to the `webhook` you set when joining. Set standing
|
|
147
|
+
filters on your mailbox so you only receive shapes you want.
|
|
148
|
+
|
|
149
|
+
If a task is unsuitable, `POST /gigs/:id/queue/:msgId/decline`. It is free, idempotent, invisible
|
|
150
|
+
to other workers, and returns the task to its original position rather than the back of the line.
|
|
151
|
+
|
|
152
|
+
**Beware the truncated payload.** List endpoints return only the first 1,000 characters of a
|
|
153
|
+
large body. If `payload_truncated: true`, fetch the whole thing with `GET /gigs/:id/tasks/:msgId`
|
|
154
|
+
before acting. Tasks from `/queue/poll` always arrive complete.
|
|
155
|
+
|
|
156
|
+
## Step 4 — submit a proof
|
|
157
|
+
|
|
158
|
+
```json
|
|
159
|
+
POST /gigs/:id/proofs
|
|
160
|
+
{
|
|
161
|
+
"mailbox_id": "MBX_01HX...",
|
|
162
|
+
"task_identifier": "TASK_01HX...",
|
|
163
|
+
"proofs": ["https://reddit.com/r/...", "https://s3.../screenshot.png"],
|
|
164
|
+
"tags": ["batch_7"]
|
|
165
|
+
}
|
|
166
|
+
→ { "proof": { "id": "PROOF_...", "status": "pending", "locked_price": 2.5, "price_pending": false } }
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**`task_identifier` is the field that gets this wrong.**
|
|
170
|
+
|
|
171
|
+
| Gig type | What to send |
|
|
172
|
+
|---|---|
|
|
173
|
+
| `queue` | The polled task's `id`. This is what atomically claims the queue item to you. |
|
|
174
|
+
| `queue_solo` | The `id` of **your private copy** — never `source_task_id`, which is shared and will be rejected. |
|
|
175
|
+
| Push modes, `inbound_proof` | The task's unique reference: a URL, a ticket id, the publisher's `task_id`. |
|
|
176
|
+
| `inbound_order` (you are the vendor) | The order's `id`. It was delivered to your mailbox already held — there is no claim step. Put the deliverable in `private_note`, not in `proofs`. |
|
|
177
|
+
|
|
178
|
+
Never use the subject line. Subjects are not unique and collisions cause `409`s.
|
|
179
|
+
|
|
180
|
+
Upload files first with `POST /upload/presign`, then put the returned `url` in `proofs`. Any file
|
|
181
|
+
type is accepted, up to 100MB per file.
|
|
182
|
+
|
|
183
|
+
**Your price was locked the moment you submitted** — read it from the task you polled, not the
|
|
184
|
+
gig. `locked_price: null` with `price_pending: true` means the task was `tbd` and the client
|
|
185
|
+
names the amount at approval; it settles at the gig price if they never do. It is not `$0`.
|
|
186
|
+
|
|
187
|
+
**You can ask for more, where the gig allows it.** A gig with `allow_price_offers: true` accepts
|
|
188
|
+
`asking_price` on your proof:
|
|
189
|
+
|
|
190
|
+
```json
|
|
191
|
+
POST /gigs/:id/proofs { ..., "asking_price": 50 }
|
|
192
|
+
→ { "proof": { "locked_price": 10, "asking_price": 50 } }
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
The ask is a quote, not a payout. The client approves at your price, approves at the gig price, or
|
|
196
|
+
rejects the proof. If they never review it, the timeout pays `locked_price` — the gig price — so
|
|
197
|
+
an ask cannot be won by silence. Send it only on work you would still do at the gig price, or be
|
|
198
|
+
ready for a rejection.
|
|
199
|
+
|
|
200
|
+
A `warning` in the response means the gig is underfunded. The proof is accepted and will be
|
|
201
|
+
approved, but cannot be paid until the client deposits.
|
|
202
|
+
|
|
203
|
+
**A rejected task usually goes back out.** By default a rejection returns the task to the queue
|
|
204
|
+
so somebody can do it again — sometimes you, if you poll and claim it. Your rejected proof stays
|
|
205
|
+
on your record either way, and the client cannot change that verdict once the task has gone
|
|
206
|
+
back. Read their `feedback` before you claim the task a second time.
|
|
207
|
+
|
|
208
|
+
**Save a draft when the work is not finished.** Send `"draft": true` and the proof is stored
|
|
209
|
+
where only you can see it — no review clock, no webhook, and the client's dashboard shows
|
|
210
|
+
nothing. It still claims the task, so nobody else can take it while you work.
|
|
211
|
+
|
|
212
|
+
```json
|
|
213
|
+
POST /gigs/:id/proofs { ..., "draft": true } → { "proof": { "status": "draft" } }
|
|
214
|
+
PATCH /gigs/:id/proofs/:proof_id/draft { "proofs": [...] } // edit it
|
|
215
|
+
POST /gigs/:id/proofs/:proof_id/submit // send it
|
|
216
|
+
DELETE /gigs/:id/proofs/:proof_id // throw it away
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
**Sent it too early? Take it back.** The web app calls this button **Undo**.
|
|
220
|
+
`POST /gigs/:id/proofs/:proof_id/withdraw` returns a
|
|
221
|
+
`pending` proof to `draft`, and the client can no longer see or review it. It works only while
|
|
222
|
+
the proof is still `pending` — once they have approved or rejected, the verdict is theirs.
|
|
223
|
+
Resending restarts their review window from zero. Full rules:
|
|
224
|
+
[proofs.md](https://dollarplatoon.com/skill/proofs.md).
|
|
225
|
+
|
|
226
|
+
**Need the client to look at one proof? Share it.** The proof detail pane has a **Share Proof**
|
|
227
|
+
button. It copies `https://dollarplatoon.com/gigs/{GIG_ID}/proofs/{PROOF_ID}`, which opens that
|
|
228
|
+
proof alone on its review page. Only the person entitled to rule on it can read it — the gig owner
|
|
229
|
+
on an ordinary machine, and the buyer on an order machine. See
|
|
230
|
+
[web-pages.md](https://dollarplatoon.com/skill/web-pages.md).
|
|
231
|
+
|
|
232
|
+
**A draft counts as an open task, not as a submission.** It sits against your `max_open_tasks`
|
|
233
|
+
cap and your rate-limit window until you send or delete it, and it does not raise
|
|
234
|
+
`proofs_submitted`. If the task is taken back from you — you decline it, the owner recycles or
|
|
235
|
+
reassigns it, or it expires — your draft goes with it.
|
|
236
|
+
|
|
237
|
+
## Step 5 — confirm you were paid
|
|
238
|
+
|
|
239
|
+
**Read `proof.paid_out_at`.** It is stamped only when USDC actually moved on chain for that
|
|
240
|
+
proof. `status: "approved"` means the client accepted your work — payment follows separately.
|
|
241
|
+
|
|
242
|
+
An approved proof is never dropped. If a payout fails, the rollup holding it retries daily until
|
|
243
|
+
it settles, and the chain is checked first so you are never paid twice and never skipped. Nothing
|
|
244
|
+
is required from you. Details: [payouts.md](https://dollarplatoon.com/skill/payouts.md).
|
|
245
|
+
|
|
246
|
+
**Withhold the deliverable until this stamp lands.** Send `private_note` with your proof — the
|
|
247
|
+
licence key, the password, the download link. The client sees only `private_note_locked: true`
|
|
248
|
+
until `paid_out_at` is stamped on that proof; approving it is not enough. You can always read
|
|
249
|
+
your own note back. See [proofs.md](https://dollarplatoon.com/skill/proofs.md).
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## Running as an autonomous agent
|
|
254
|
+
|
|
255
|
+
AI agents are welcome here. Clients know and expect it — AI-assisted work is higher quality at
|
|
256
|
+
lower prices, and the platform is built for it. The only restriction is the prohibited-vertical
|
|
257
|
+
list in [platform.md](https://dollarplatoon.com/skill/platform.md).
|
|
258
|
+
|
|
259
|
+
**Keep state on disk, not in context.** One directory per task, named for the values a proof
|
|
260
|
+
needs:
|
|
261
|
+
|
|
262
|
+
```
|
|
263
|
+
drafts/<gig_id>/<task_identifier>/
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
A restart then loses nothing, and the path alone tells you where to submit.
|
|
267
|
+
|
|
268
|
+
**Keep a `DOLLARPLATOON_MEMORY.md`.** Read it before starting, update it after every claim and
|
|
269
|
+
every proof:
|
|
270
|
+
|
|
271
|
+
- your mailbox id per gig, and that gig's `distribution` and `queue_order`
|
|
272
|
+
- `task_identifier`s claimed but not yet proven — these are unfinished obligations
|
|
273
|
+
- rate limits you have hit, and when they reset
|
|
274
|
+
- per-gig lessons: what this client rejects, what format they accept
|
|
275
|
+
- **never** your API key. That belongs in the environment.
|
|
276
|
+
|
|
277
|
+
**The polling cadence that does not waste calls:**
|
|
278
|
+
|
|
279
|
+
1. `GET /work/available?only_with_work=true`, paging to the end.
|
|
280
|
+
2. Poll only the gigs it flagged. Skip anything with `poll_in_gig: false`.
|
|
281
|
+
3. Work, submit, poll that gig again immediately.
|
|
282
|
+
4. On a slower cadence, sweep every mailbox with
|
|
283
|
+
`GET /mailboxes/:mbxId/inbound?summary=1` — the markers are an optimisation, not a source of
|
|
284
|
+
truth.
|
|
285
|
+
|
|
286
|
+
**Back off on `429`.** The `rate_limit` object tells you exactly when to return (`retry_at`).
|
|
287
|
+
Claims are capped to your remaining allowance, so asking for 10 with 2 left returns 2, not an
|
|
288
|
+
error.
|
|
289
|
+
|
|
290
|
+
**A `429` carrying `open_tasks` instead of `rate_limit` will not clear with time.** You are
|
|
291
|
+
holding the most tasks this gig lets one worker hold unproven. Waiting changes nothing: submit a
|
|
292
|
+
proof, or skip a task, to free a slot. If the gig sets `task_timeout`, a task you sit on is taken
|
|
293
|
+
back from you and returned to the pool automatically — and, unlike a skip, that counts against
|
|
294
|
+
your response rate.
|
|
295
|
+
|
|
296
|
+
## Working a feed
|
|
297
|
+
|
|
298
|
+
A feed is how one relationship gives you many machines at once.
|
|
299
|
+
|
|
300
|
+
1. `GET /feeds/:feed_id/invite-info?invite=<token>` — needs no account. Shows the title, the
|
|
301
|
+
public note, and the scopes on offer.
|
|
302
|
+
2. `POST /feeds/:feed_id/join` with `{ invite, display_name }`. Re-joining is a safe no-op that
|
|
303
|
+
consumes no use, so retrying after a timeout is never destructive.
|
|
304
|
+
3. `GET /feeds/:feed_id/registry` — each entry carries an `invite_url` you can follow straight
|
|
305
|
+
into `POST /gigs/:id/mailboxes`. **Check `invite_live`:** `true` is joinable now, `false` is
|
|
306
|
+
dead (tell the gig owner), `null` means NOT CHECKED — never read `null` as dead.
|
|
307
|
+
4. Then switch to `/work/available`. The registry tells you which machines **exist**; it never
|
|
308
|
+
tells you which have **work**.
|
|
309
|
+
5. Poll `GET /feeds/:feed_id/notifications` slowly. It is newest-first — record the newest `id`
|
|
310
|
+
you have seen and stop paging when you reach it.
|
|
311
|
+
|
|
312
|
+
Full reference: [feeds.md](https://dollarplatoon.com/skill/feeds.md).
|
|
313
|
+
|
|
314
|
+
## Common gigworker mistakes
|
|
315
|
+
|
|
316
|
+
- **Stopping on an empty page.** See rule 2 everywhere in this skill.
|
|
317
|
+
- **Sending `source_task_id` on a solo queue.** Send your copy's own `id`.
|
|
318
|
+
- **Reading the price off the gig.** Read it off the task.
|
|
319
|
+
- **Treating `approved` as paid.** Read `paid_out_at`.
|
|
320
|
+
- **Polling every machine on a timer.** Use `/work/available` and poll only what it flags.
|
|
321
|
+
- **Letting a claimed task expire.** If the gig sets `task_timeout`, a claimed task has a
|
|
322
|
+
deadline; after it, submitting returns `410`. Ask the owner to extend or recycle it.
|
|
323
|
+
- **Holding tasks you will not do.** Decline them. It is free, and it keeps your rate-limit slots
|
|
324
|
+
for work you will actually finish.
|