Conversation
Introduce a +brainstem MATLAB package implementing the BrainSTEM API client and helpers: BrainstemClient, load_model, get_token, delete_model, numerous load_<model>.m convenience wrappers, and private helper functions (build_url, build_query_string, apply_field_filters, parse_api_error). Add comprehensive unit and integration tests (+brainstem/BrainstemTests.m) and update README and tutorial. Remove legacy top-level files replaced by the new package structure.
Rename and refactor core BrainSTEM API helpers and update tests accordingly. load_model/delete_model/save_model were renamed to load/delete/save and callers updated to use brainstem.* namespaced functions. get_token was reworked to use the device authorization flow with a fallback manual PAT flow, persist tokens to prefdir, and simplified signature; token save/update logic was added. load* helpers now accept empty settings (load_settings is invoked lazily), expose limit/offset/load_all pagination args, omit Authorization header for public requests, and surface unified error IDs (e.g. 'BrainSTEM:load'/'BrainSTEM:delete'). Unit tests were updated to match API changes and client token_type handling (PAT-only flow). Miscellaneous: inputParser validation tweaks, minor I/O/text improvements, and function renames in the +brainstem package files.
Revise the device authorization flow to match the server's newer API: use resp.device_code and resp.verification_uri_complete, open the verification URI as a char, and poll POST /api/auth/device/token/ with {device_code} instead of GET with state. Improve polling request options and response handling (handle success, expired_token, access_denied and other errors; treat authorization_pending as continued polling). Also handle the fallback manual PAT flow by saving the token when provided and return early. Misc: adjust weboptions naming and small control-flow cleanup.
Introduce private helpers to remove duplicated loader boilerplate and improve settings/token handling. Added brainstem_convenience_load to centralize common parsing/filter mapping for load_* functions and updated numerous load_* files to delegate to it. Added brainstem_get_settings to resolve URL/token from BRAINSTEM_URL/BRAINSTEM_TOKEN, cached credentials, or interactive flow; load_settings is now a deprecated wrapper. Added brainstem_normalize_list_response to normalize API list responses into struct arrays and integrated normalization into load/pagination. Add defensive checks and improvements: UUID validation for load/delete, guard against empty id deletes, default weboptions Timeout and error handling. Minor fixes: get_app_from_model maps 'group' → 'auth', updated tests to match new settings shape and examples/docs updated. These changes reduce duplication, make authentication more predictable, and make API responses more consistent.
There was a problem hiding this comment.
Pull request overview
This PR introduces “MATLAB API tool v2” by replacing the legacy standalone MATLAB functions with a +brainstem package API and a BrainstemClient class that centralizes auth/settings and provides convenience loaders, plus updated docs/tutorials.
Changes:
- Added
BrainstemClientand a new+brainstempackage (load/save/delete/get_token+ convenience loaders) with token caching and device-flow authentication. - Refactored URL/query building and response normalization into shared private helpers.
- Updated
README.md,Contents.m, andbrainstem_api_tutorial.m; removed the legacy v1 functions.
Reviewed changes
Copilot reviewed 43 out of 43 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
BrainstemClient.m |
New client wrapper around brainstem.* functions with auth retry/refresh logic. |
+brainstem/load.m |
Core loader with filtering/sorting/include, paging, and optional auto-pagination. |
+brainstem/save.m |
Core create/update (POST/PUT/PATCH) helper with validation and error parsing. |
+brainstem/delete.m |
Core delete helper by UUID with 204 handling. |
+brainstem/get_token.m |
Device authorization flow with fallback to manual PAT entry + token caching. |
+brainstem/private/* |
Shared helpers for settings resolution, URL/query building, response normalization, and error parsing. |
+brainstem/load_*.m |
Convenience loaders delegating to shared helper with model-specific defaults. |
+brainstem/BrainstemTests.m |
New matlab.unittest coverage (offline/network/authenticated). |
README.md |
Updated v2 usage docs, auth guidance, and API surface overview. |
brainstem_api_tutorial.m |
Updated tutorial to demonstrate client-based workflows and new options. |
Contents.m |
New package index/entry points summary for MATLAB. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| % Detect the data key dynamically: it is the response field whose | ||
| % value is a struct array (i.e. not the scalar metadata fields). | ||
| metadata_keys = {'count','next','previous'}; | ||
| all_keys = fieldnames(output); | ||
| data_keys = all_keys(~ismember(all_keys, metadata_keys)); | ||
| if ~isempty(data_keys) | ||
| model_key = data_keys{1}; % e.g. 'sessions', 'dataacquisitions' | ||
| else | ||
| model_key = ''; | ||
| end |
There was a problem hiding this comment.
Auto-pagination selects the first non-metadata fieldname as the data key. When include[] is used, responses may contain multiple data arrays (e.g., sessions + behaviors + manipulations), and alphabetical field order can cause the wrong key to be appended, dropping/under-fetching the primary model. Prefer deriving the primary key from the requested model (e.g., sessions for model=session) and/or appending all non-metadata keys that are present in both pages.
Add brainstem.logout to remove cached tokens and document it in Contents/README. Require a non-empty token for brainstem.save and brainstem.delete to fail early. Improve brainstem_build_query_string to handle both N×2 and flat 1×(2N) filter layouts and preserve string/number formatting. Ensure brainstem_build_url normalizes trailing slashes and handles empty ids. Enhance brainstem_parse_api_error to prefer JSON validation bodies (showing field-level errors) while still including HTTP status when present. Make BrainstemClient honor BRAINSTEM_URL when no explicit url is provided. Add comprehensive unit tests covering these behaviors.
Allow brainstem.logout to accept name-value form (brainstem.logout('url', url)) and validate inputs; use BRAINSTEM_URL env var as default. Normalize the on-disk authentication table schema in get_token/save_token_: add missing columns ('usernames', 'saved_at'), canonicalize column order, and build new rows consistently so older auth files are upgraded. Improve save feedback to print the auth file path. Add BrainstemClient.logout to clear the client's in-memory token and remove the saved token for the client's URL. Update unit tests (BrainstemTests) to match the new table schema and add a test for the name-value logout form.
No description provided.