hirify-cli 0.6.5 → 0.6.7

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/README.md CHANGED
@@ -64,7 +64,7 @@ Open the printed link on the computer that owns the tunnel. Confirm access withi
64
64
  a reminder appears every 30 seconds. Ctrl+C cancels and closes the listener. Start a fresh login
65
65
  after cancellation. `hirify login --force` replaces an existing or unusable sign-in.
66
66
 
67
- For unattended work, obtain a key at [API access](https://hirify.me/account/api-access), supply it
67
+ For unattended work, obtain a key at [MCP/API](https://hirify.me/account/mcp-api), supply it
68
68
  as `HIRIFY_KEY`, or pipe it to `hirify auth --stdin`. Avoid putting keys in shell history with
69
69
  `hirify auth <key>`; that legacy form is still accepted. Never put a real key in a support report.
70
70
  `HIRIFY_KEY` takes precedence over the saved sign-in. `hirify logout` removes local access only;
package/bin/lib/api.js CHANGED
@@ -31,7 +31,11 @@ export function responseError(response, { key = false } = {}) {
31
31
  if (status === 401) return new CliError('auth_required', key ? 'the key was not accepted (401). It may have been revoked, or copied incompletely.' : 'your sign-in is no longer valid. Please run hirify login --force.', options)
32
32
  if (status === 403 && body?.error?.code === 'access_restricted') return new CliError('access_restricted', accessRestrictedMessage(body), options)
33
33
  if (status === 409 && body?.error?.code === 'action_required') return new CliError('action_required', actionRequiredMessage(body), options)
34
- if (status === 403) return new CliError('access_denied', 'no access (403). This needs an active paid plan, or the sign-in is missing a permission.', options)
34
+ if (status === 403) {
35
+ const code = typeof body?.error?.code === 'string' && body.error.code.trim() ? body.error.code : 'access_denied'
36
+ const message = typeof body?.error?.message === 'string' && body.error.message.trim() ? body.error.message : typeof body?.message === 'string' && body.message.trim() ? body.message : 'Access was denied (403).'
37
+ return new CliError(code, message, options)
38
+ }
35
39
  if (status === 404) return new CliError('not_found', 'not found (404).', options)
36
40
  if (status === 429) {
37
41
  const action = body?.quota?.action
@@ -76,7 +80,7 @@ export function createApi({ config, http, auth, output }) {
76
80
  const doc = await agentDiscovery()
77
81
  if (!doc.manifest_url) throw new CliError('manifest_unavailable', 'could not reach Hirify to load what it can do. Please check your connection and try again.')
78
82
  const res = await authenticated(doc.manifest_url, { safe: true })
79
- if (!res.ok) { if (res.status === 401) throw responseError(res, { key: Boolean(config.envKey) }); throw new CliError('manifest_unavailable', 'could not load what Hirify can do right now. Please try again in a minute.', { status: res.status }) }
83
+ if (!res.ok) { if ([401, 403].includes(res.status)) throw responseError(res, { key: Boolean(config.envKey) }); throw new CliError('manifest_unavailable', 'could not load what Hirify can do right now. Please try again in a minute.', { status: res.status }) }
80
84
  return validateManifest(requireJSON(res), config.api)
81
85
  })()
82
86
  return manifest
package/bin/lib/auth.js CHANGED
@@ -94,7 +94,7 @@ export function createAuth({ config, store, http, signal, output, event, secrets
94
94
  reminder = setInterval(() => output.progress('Still waiting for browser confirmation. Use the sign-in link above, or press Ctrl+C.'), 30000)
95
95
  if (!noBrowser && info.canOpen) launchTask = openBrowser(url.href, { signal }).then(result => { event('browser', result); if (['launcher_missing', 'spawn_error', 'nonzero_exit'].includes(result.code)) output.progress('The browser launcher did not complete. Open the link above manually.') })
96
96
  const answer = await listener.received
97
- if (answer.error) throw new CliError(answer.error === 'access_denied' ? 'auth_denied' : 'oauth_error', 'Sign-in was not approved. Nothing was saved. Run hirify login again when ready.')
97
+ if (answer.error) throw new CliError(answer.error === 'access_denied' ? 'auth_denied' : answer.error, answer.error_description || 'Sign-in was not approved. Nothing was saved. Run hirify login again when ready.')
98
98
  secrets.add(answer.code)
99
99
  const res = await form(endpoints.token_endpoint, { grant_type: 'authorization_code', client_id: client.client_id, code: answer.code, redirect_uri: listener.redirectUri, code_verifier: verifier })
100
100
  if (!res.ok) throw new CliError('oauth_exchange', 'The confirmation could not be exchanged. Run hirify login again.', { status: res.status })
@@ -632,7 +632,7 @@ Setting up
632
632
  Signing in
633
633
  hirify login prints a link and tries the browser when available. Your user confirms access.
634
634
  Manual sign-in: hirify login --no-browser. For automation, use HIRIFY_KEY or hirify auth --stdin; get a key at
635
- hirify.me/account/api-access.
635
+ hirify.me/account/mcp-api.
636
636
 
637
637
  Commands
638
638
  hirify account show, hirify feed list, hirify vacancy search, hirify vacancy read,
@@ -27,7 +27,7 @@ export async function startCallbackServer({ state, issuer, port = 0, signal, tim
27
27
  if (settled || !validState || params.getAll('state').length !== 1 || params.getAll('code').length > 1 || params.getAll('error').length > 1 || Boolean(code) === Boolean(error) || (params.has('iss') && (params.getAll('iss').length !== 1 || params.get('iss') !== issuer))) return reply(400, 'This callback does not match the pending sign-in.')
28
28
  settled = true
29
29
  reply(200, '<!doctype html><html lang="en"><meta charset="utf-8"><title>Hirify</title><h1>Confirmation received</h1><p>Return to your terminal to see the sign-in result.</p></html>', true)
30
- settle({ code, error })
30
+ settle({ code, error, error_description: params.get('error_description') })
31
31
  })
32
32
  server.requestTimeout = 5000
33
33
  server.headersTimeout = 5000
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "hirify-cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "hirify-cli",
9
- "version": "0.6.5",
9
+ "version": "0.6.7",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "cross-spawn": "7.0.6",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hirify-cli",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "description": "Hirify CLI for AI agents: browser sign-in, job feeds, search, reading a vacancy in full, contacts to apply to, and applying on Hirify.",
5
5
  "bin": {
6
6
  "hirify": "bin/hirify.js"