happyskills 0.47.0 → 0.47.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 +9 -0
- package/package.json +1 -1
- package/src/api/client.js +6 -1
- package/src/api/repos.js +6 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.47.1] - 2026-05-22
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Fix `search --with-rerank` silently dropping every rerank field from the API response. The HTTP client's default `{ data: ... }` envelope unwrap was discarding `mode`, `match_notice`, `workspace_match`, and (when opted-in) `rerank_digests`, `rerank_system_prompt`, `rerank_prompt_version`, `rerank_response_schema` from `POST /repos:search`. The CLI's envelope emission saw `digests.length === 0` and fell through to "no protocol envelope" → the agent rendered the baseline ranking instead of running the LLM rerank. With this fix, `dispatch_search()` opts out of the auto-unwrap via a new `unwrap: false` option on `client.request()` and the caller now receives the full envelope. Verified end-to-end against production: natural-language query returns `next_step.action == "rank_digests_inline"` with 50 digests + the 1519-char system prompt + the strict json_schema; slug-shape query still emits `next_step: null` (no false-positive protocol fire). The bug had been latent since `0.47.0`'s introduction of `--with-rerank` because the existing rendering code in `search.js` already had a defensive fallback for both response shapes (`Array.isArray(response) ? response : response?.data`), but the rerank path requires the top-level fields specifically.
|
|
14
|
+
- Plain `search --json` (without `--with-rerank`) now correctly carries `data.mode` (e.g. `'semantic'` / `'fuzzy_slug'` / `'fuzzy_scoped'`) in the JSON output. Previously `mode` was always `null` because the client auto-unwrap silently dropped it. The human-readable output also gains a `[mode]` annotation next to the query header, and the yellow `match_notice` warning ("No strong matches found…") now shows up on weak-result searches — both were already coded but never received their inputs.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
- `client.request()` (`cli/src/api/client.js`) gains an `unwrap` option (default `true`, matching the existing behavior). Set `unwrap: false` to receive the raw response body instead of the auto-unwrapped `data.data`. Required for endpoints (currently only `POST /repos:search`) that emit metadata fields at the top level of the response alongside the `data` payload. Existing callers are unaffected because the default preserves current behavior.
|
|
18
|
+
|
|
10
19
|
## [0.47.0] - 2026-05-21
|
|
11
20
|
|
|
12
21
|
### Added
|
package/package.json
CHANGED
package/src/api/client.js
CHANGED
|
@@ -7,7 +7,7 @@ const { load_token } = require('../auth/token_store')
|
|
|
7
7
|
const get_base_url = () => process.env.HAPPYSKILLS_API_URL || API_URL
|
|
8
8
|
|
|
9
9
|
const request = (method, path, options = {}) => catch_errors(`API ${method} ${path} failed`, async () => {
|
|
10
|
-
const { body, auth = true, raw_response = false, headers: extra_headers = {} } = options
|
|
10
|
+
const { body, auth = true, raw_response = false, unwrap = true, headers: extra_headers = {} } = options
|
|
11
11
|
const url = `${get_base_url()}${path}`
|
|
12
12
|
const headers = { ...extra_headers }
|
|
13
13
|
|
|
@@ -64,6 +64,11 @@ const request = (method, path, options = {}) => catch_errors(`API ${method} ${pa
|
|
|
64
64
|
throw new ApiError(err_msg, res.status, err_code)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
// Auto-unwrap `{ data: ... }` envelope by default. Callers that need the
|
|
68
|
+
// full response (e.g. endpoints that emit top-level metadata fields
|
|
69
|
+
// alongside `data` — see `dispatch_search` for `/repos:search`'s
|
|
70
|
+
// `mode` / `rerank_digests` / `match_notice` fields) pass `unwrap: false`.
|
|
71
|
+
if (!unwrap) return data
|
|
67
72
|
return data?.data !== undefined ? data.data : data
|
|
68
73
|
})
|
|
69
74
|
|
package/src/api/repos.js
CHANGED
|
@@ -149,7 +149,12 @@ const dispatch_search = (query, options = {}) => catch_errors('Search failed', a
|
|
|
149
149
|
// protocol. Server returns digests + system prompt + json_schema only
|
|
150
150
|
// when this is true AND the dispatcher routes to mode='semantic'.
|
|
151
151
|
if (options.with_rerank_digests) body.with_rerank_digests = true
|
|
152
|
-
|
|
152
|
+
// `/repos:search` returns top-level metadata alongside `data` —
|
|
153
|
+
// `mode`, `match_notice`, `workspace_match`, and (when opted-in)
|
|
154
|
+
// `rerank_digests`, `rerank_system_prompt`, `rerank_prompt_version`,
|
|
155
|
+
// `rerank_response_schema`. The client's default unwrap would drop these
|
|
156
|
+
// fields entirely. Opt out so the caller sees the full envelope.
|
|
157
|
+
const [errors, data] = await client.post('/repos:search', body, { auth: true, unwrap: false })
|
|
153
158
|
if (errors) throw errors[errors.length - 1]
|
|
154
159
|
return data
|
|
155
160
|
})
|