Skip to content

feat(upwork): add search, feed, and detail commands#1609

Open
NSOiO wants to merge 3 commits into
jackwener:mainfrom
NSOiO:feat/upwork-adapter
Open

feat(upwork): add search, feed, and detail commands#1609
NSOiO wants to merge 3 commits into
jackwener:mainfrom
NSOiO:feat/upwork-adapter

Conversation

@NSOiO
Copy link
Copy Markdown

@NSOiO NSOiO commented May 16, 2026

Description

Three browser-mode adapters for upwork.com, all read-only. Closes #1608.

  • search — keyword job search with --location / --sort / --page / --per_page filters
  • feed — personalized recommended feed (best-matches | most-recent), requires login
  • detail — full job posting + client stats by ciphertext id

Related issue: #1608

Type of Change

  • 🌐 New site adapter

Approach

All three commands run through Strategy.COOKIE because upwork.com sits behind Cloudflare. List adapters read from window.__NUXT__.state.{jobsSearch,feedBestMatch,feedMostRecent}.jobs[] rather than DOM-scraping cards; detail reads the Vuex store at window.$nuxt.$store.state.jobDetails.{job,buyer}. This keeps the columns stable when Upwork ships card markup changes.

Decoders in clis/upwork/utils.js handle Upwork's three coded-enum styles so output stays consistent across surfaces:

Surface Style Example
search i18n keys jsn_Intermediate_206
feed rendered labels Intermediate
detail numeric tier contractorTier: 2

Tests

41 unit tests in clis/upwork/upwork.test.js cover validators, decoders, URL builders, row mappers, and the func() happy / auth-required / Cloudflare-challenge / empty-result paths against mocked page.evaluate.

$ npx vitest run clis/upwork/upwork.test.js
 Test Files  1 passed (1)
      Tests  41 passed (41)

Full npm test shows 11 failures, none in this PR — they are pre-existing in main:

  • 8 in src/weixin-download.test.ts (@jackwener/opencli/registry package resolution)
  • 1 in src/browser/article-extract.e2e.test.ts (Wikipedia fixture 5s timeout)
  • 1 in src/package-exports.test.ts (5s timeout while scanning all adapters)
  • 1 not surfaced in the FAIL log

Checklist

  • I ran the checks relevant to this PR (tsc --noEmit, upwork test file, opencli validate)
  • I updated tests
  • I included CLI output where useful

Documentation

  • Added doc page under docs/adapters/browser/upwork.md
  • Updated docs/adapters/index.md table
  • Updated sidebar in docs/.vitepress/config.mts (added in dfbc2266)
  • Updated README.md / README.zh-CN.md (added in dfbc2266)
  • Used positional args for the primary subject (search <query>, detail <jobId>)
  • Normalized expected adapter failures to CliError subclasses

Screenshots / Output

$ opencli upwork search react --limit 3 -f json
[
  { "title": "...", "budget": "...", "level": "intermediate", "url": "..." },
  ...
]

Updated in dfbc2266 after a re-read of the contribution checklist — sidebar entry and README/README.zh-CN command-table row are now included.

Implementation drafted with Claude Code assistance.

NSOiO and others added 2 commits May 20, 2026 02:27
Three browser-mode adapters for upwork.com, all read-only.

- search: keyword job search with location/sort/page/per_page filters
- feed:   personalized recommended feed (best-matches | most-recent),
          requires login
- detail: full job posting + client stats by ciphertext id

All three run through Strategy.COOKIE (Cloudflare-protected). List
adapters read from window.__NUXT__.state.{jobsSearch,feedBestMatch,
feedMostRecent}.jobs[] rather than DOM-scraping cards; detail reads
the Vuex store at window.$nuxt.$store.state.jobDetails.{job,buyer}.

Decoders handle Upwork's three coded enum styles (i18n keys like
jsn_Intermediate_206 on search, rendered labels like 'Intermediate'
on feed, numeric contractorTier on detail) so the output columns
stay stable across surfaces. 41 unit tests cover validators,
decoders, URL builders, row mappers, and the func-level happy /
auth / challenge / empty paths against mocked page.evaluate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Surfaces the upwork adapter through the same entry points other
browser adapters use:

- docs/.vitepress/config.mts: add Upwork to the Browser Adapters
  sidebar next to Indeed
- README.md / README.zh-CN.md: add an upwork row to the Built-in
  Commands / 内置命令 tables

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jackwener jackwener force-pushed the feat/upwork-adapter branch from dfbc226 to 004458d Compare May 19, 2026 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Upwork]: add search, feed, and detail commands

2 participants