happyskills 0.12.0 → 0.12.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/CHANGELOG.md CHANGED
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.12.1] - 2026-03-12
11
+
12
+ ### Fixed
13
+ - Fix `whoami` silently swallowing workspace listing errors — now surfaces a `workspace_error` field in JSON mode and prints a warning with auth hint in human mode
14
+ - Fix `check` and `refresh` reporting `status: "unknown"` for private skills the user owns but can't access due to auth issues — now reports `status: "no-access"` with a login hint
15
+
10
16
  ## [0.12.0] - 2026-03-12
11
17
 
12
18
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "happyskills",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Package manager for AI agent skills",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "author": "Nicolas Dao <nic@cloudlesslabs.com> (https://cloudlesslabs.com)",
@@ -2,7 +2,7 @@ const { error: { catch_errors, wrap_errors: e } } = require('puffy-core')
2
2
  const { read_lock, get_all_locked_skills } = require('../lock/reader')
3
3
  const repos_api = require('../api/repos')
4
4
  const { gt } = require('../utils/semver')
5
- const { print_help, print_table, print_json, print_info, print_success, print_hint, code } = require('../ui/output')
5
+ const { print_help, print_table, print_json, print_info, print_success, print_warn, print_hint, code } = require('../ui/output')
6
6
  const { green, yellow, red } = require('../ui/colors')
7
7
  const { exit_with_error } = require('../utils/errors')
8
8
  const { find_project_root } = require('../config/paths')
@@ -68,7 +68,9 @@ const run = (args) => catch_errors('Check failed', async () => {
68
68
  } else {
69
69
  for (const [name, data] of to_check) {
70
70
  const info = batch_data?.results?.[name]
71
- if (!info || !info.latest_version) {
71
+ if (info?.access_denied) {
72
+ results.push({ skill: name, installed: data.version, latest: '-', status: 'no-access' })
73
+ } else if (!info || !info.latest_version) {
72
74
  results.push({ skill: name, installed: data.version, latest: '-', status: 'unknown' })
73
75
  } else if (info.latest_version === data.version) {
74
76
  results.push({ skill: name, installed: data.version, latest: info.latest_version, status: 'up-to-date' })
@@ -90,6 +92,7 @@ const run = (args) => catch_errors('Check failed', async () => {
90
92
  const status_colors = {
91
93
  'up-to-date': green,
92
94
  'outdated': yellow,
95
+ 'no-access': yellow,
93
96
  'error': red,
94
97
  'unknown': (s) => s
95
98
  }
@@ -104,6 +107,7 @@ const run = (args) => catch_errors('Check failed', async () => {
104
107
  print_table(['Skill', 'Installed', 'Latest', 'Status'], rows)
105
108
 
106
109
  const outdated = results.filter(r => r.status === 'outdated')
110
+ const no_access = results.filter(r => r.status === 'no-access')
107
111
  if (outdated.length > 0) {
108
112
  console.log()
109
113
  print_info(`Run ${code('happyskills update')} to upgrade ${outdated.length} skill(s).`)
@@ -111,6 +115,11 @@ const run = (args) => catch_errors('Check failed', async () => {
111
115
  console.log()
112
116
  print_success('All skills are up to date.')
113
117
  }
118
+ if (no_access.length > 0) {
119
+ console.log()
120
+ print_warn('Some skills require authentication.')
121
+ print_hint(`Run ${code('happyskills login')} to refresh your session.`)
122
+ }
114
123
  }).then(([errors]) => { if (errors) { exit_with_error(errors); return } })
115
124
 
116
125
  module.exports = { run }
@@ -3,7 +3,7 @@ const { install } = require('../engine/installer')
3
3
  const { read_lock, get_all_locked_skills } = require('../lock/reader')
4
4
  const repos_api = require('../api/repos')
5
5
  const { gt } = require('../utils/semver')
6
- const { print_help, print_table, print_json, print_info, print_success, code } = require('../ui/output')
6
+ const { print_help, print_table, print_json, print_info, print_success, print_warn, print_hint, code } = require('../ui/output')
7
7
  const { green, yellow, red } = require('../ui/colors')
8
8
  const { create_spinner } = require('../ui/spinner')
9
9
  const { exit_with_error } = require('../utils/errors')
@@ -74,7 +74,9 @@ const run = (args) => catch_errors('Refresh failed', async () => {
74
74
  spinner?.succeed('Checked for updates')
75
75
  for (const [name, data] of to_check) {
76
76
  const info = batch_data?.results?.[name]
77
- if (!info || !info.latest_version) {
77
+ if (info?.access_denied) {
78
+ results.push({ skill: name, installed: data.version, latest: '-', status: 'no-access' })
79
+ } else if (!info || !info.latest_version) {
78
80
  results.push({ skill: name, installed: data.version, latest: '-', status: 'unknown' })
79
81
  } else if (info.latest_version === data.version) {
80
82
  results.push({ skill: name, installed: data.version, latest: info.latest_version, status: 'up-to-date' })
@@ -105,7 +107,7 @@ const run = (args) => catch_errors('Refresh failed', async () => {
105
107
 
106
108
  // 3. Show results table (non-json)
107
109
  if (!args.flags.json) {
108
- const status_colors = { 'up-to-date': green, 'outdated': yellow, 'error': red, 'unknown': (s) => s }
110
+ const status_colors = { 'up-to-date': green, 'outdated': yellow, 'no-access': yellow, 'error': red, 'unknown': (s) => s }
109
111
  print_table(['Skill', 'Installed', 'Latest', 'Status'], results.map(r => [
110
112
  r.skill, r.installed, r.latest, (status_colors[r.status] || ((s) => s))(r.status)
111
113
  ]))
@@ -1,7 +1,7 @@
1
1
  const { error: { catch_errors, wrap_errors: e } } = require('puffy-core')
2
2
  const { require_token } = require('../auth/token_store')
3
3
  const workspaces_api = require('../api/workspaces')
4
- const { print_help, print_label, print_json } = require('../ui/output')
4
+ const { print_help, print_label, print_json, print_warn, print_hint } = require('../ui/output')
5
5
  const { exit_with_error } = require('../utils/errors')
6
6
  const { EXIT_CODES } = require('../constants')
7
7
 
@@ -42,14 +42,20 @@ const run = (args) => catch_errors('Whoami failed', async () => {
42
42
  const [ws_err, workspaces] = await workspaces_api.list_workspaces()
43
43
 
44
44
  if (args.flags.json) {
45
- print_json({ data: { username, email, workspaces: ws_err ? [] : workspaces } })
45
+ const json_data = { username, email, workspaces: ws_err ? [] : workspaces }
46
+ if (ws_err) json_data.workspace_error = ws_err.map(er => er.message).join(': ')
47
+ print_json({ data: json_data })
46
48
  return
47
49
  }
48
50
 
49
51
  print_label('Username', username)
50
52
  print_label('Email', email)
51
53
 
52
- if (!ws_err && workspaces && workspaces.length > 0) {
54
+ if (ws_err) {
55
+ console.log()
56
+ print_warn(`Failed to list workspaces: ${ws_err.map(er => er.message).join(': ')}`)
57
+ print_hint('Check your authentication with happyskills login')
58
+ } else if (workspaces && workspaces.length > 0) {
53
59
  console.log()
54
60
  print_label('Workspaces', '')
55
61
  for (const ws of workspaces) {