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 +6 -0
- package/package.json +1 -1
- package/src/commands/check.js +11 -2
- package/src/commands/refresh.js +5 -3
- package/src/commands/whoami.js +9 -3
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
package/src/commands/check.js
CHANGED
|
@@ -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 (
|
|
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 }
|
package/src/commands/refresh.js
CHANGED
|
@@ -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 (
|
|
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
|
]))
|
package/src/commands/whoami.js
CHANGED
|
@@ -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
|
-
|
|
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 (
|
|
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) {
|