# Submitting components as Altium 365 Part Requests (web browser) When the central library is a managed **Altium 365 Workspace** and the operator is **not an admin**, the skill's end task can be to submit each finished component as a **Part Request** through the Workspace's web UI, driven by browser automation (Claude-in-Chrome). A librarian then approves each request into the managed library. This runs in the operator's **own Chrome, using their existing Altium 365 login**, so it needs **no API token and no admin rights** — it just does what the engineer would do by hand, for every component in the run. This is the browser alternative to the headless API push (`altium365_push.py`, if a token is ever available) and to the Gitea push. Use whichever matches how the org consumes the library. ## Prerequisites (each run) - **Chrome open** with the Claude-in-Chrome extension enabled, and **site permission granted** for the Workspace domain (e.g. `vecmocon.altium365.com`). - **Signed in** to the Altium 365 Workspace as any member with rights to create Part Requests. - **The component files on the LOCAL machine** — the browser uploads attachments from local disk, so each component's `.SchLib` (with parameters written), `.PcbLib`, and datasheet must exist on the operator's computer. If the skill produced them in the cloud, commit them to the device first (device bridge) into a known folder, and put those local paths in the manifest. - **The manifest** of components to submit this run (below). - **Decisions the operator confirms once**: the default **Assign to** (the librarian/group), the **Component Type** mapping for each typeid, and an optional **Required By** date. ## Per-component field mapping (the Part Request form) | Form field | Value (from the skill's per-part data) | |---|---| | Manufacturer | `Manufacturer` param (e.g. `Taiyo Yuden`) | | Manufacturer Part Numbers | `Manufacturer Part` param (the MPN) | | Description | `Description` param (SOP format, e.g. `CHIP_CAP_1uF_6.3v_±10%_0402_x5r`) | | Component Type | the typeid mapped to the Workspace's matching component type (confirm once per typeid) | | State | leave `Opened: New` | | Required By Date | optional org default | | Assign to | the configured librarian / group | | Parameters → Add | every parameter from the full set (name + value) | | Attachments | the `.SchLib`, `.PcbLib`, and datasheet files | | Parts List → Add | optional: add the MPN as a part choice so the librarian's mapping is pre-seeded | ## The manifest The skill writes one `part_requests.json` per run listing every component it processed, so the browser step can loop without re-deriving anything: ```json {"requests":[ {"manufacturer":"Taiyo Yuden","mpn":"JMK105BJ105KV-F", "description":"CHIP_CAP_1uF_6.3v_±10%_0402_x5r","component_type":"Capacitor", "parameters":{"Value":"1u","Voltage(V)":"6.3","Tolerance":"±10%","...":"..."}, "files":["C:\\...\\JMK105BJ105KV-F.SchLib","C:\\...\\.PcbLib","C:\\...\\.pdf"], "assignee":"","required_by":""} ]} ``` Build it from each component's `params.json` plus the local file paths (after committing files to the device). ## Browser procedure (looped per component) Start the browser session with `tabs_context_mcp`, then for each entry in the manifest: 1. Navigate to **Library → Part Requests → new request**. 2. Fill **Manufacturer**, **Manufacturer Part Numbers**, **Description**. 3. Choose **Component Type**; set **Assign to**; optional **Required By Date**. Leave State as `Opened: New`. 4. **Parameters → Add**: add each parameter name + value. 5. **Attachments** (Choose file / drop): upload the `.SchLib`, `.PcbLib`, and datasheet. 6. Review, then **Save**. Record the auto-assigned **Request Id**. 7. Move to the next entry. ## Standalone Selenium path (token-free at scale) — `scripts/altium365_part_request.py` Live browser-driving costs Claude tokens per component. For a whole library, use the Selenium script instead: it's authored once, then runs on the operator's machine over any number of components with **zero Claude tokens per part**. It attaches to the operator's already-signed-in Chrome (remote-debugging port), so it reuses the Altium 365 session — no credentials handled. Captured selectors (live form at `/partrequestsmanagement/Tasks/Add`; Altium "afs" design system + Selectize.js dropdowns): - Manufacturer → `input#Manufacturer` - Manufacturer Part Numbers → `textarea#ManufacturerPartNumbers` - Description → `textarea#Description` - Component Type / Assign to → Selectize: click the `.selectize-input` after the label, then the `.selectize-dropdown-content .option` whose text matches. - Parameters → afs-table under the "Parameters" label; each "Add" (`a.afs-link`) click adds a `div.afs-table__tr` with two `input.afs-input__control` (name, value). - Attachments → `input#fileupload` (Selenium `send_keys` the local file path(s)). - Save → `button.afs-btn_primary` (text "Save"). Component Type options (must match one exactly): Test Points, Clock&Timing, Memory, Wireless, Transformers, Mechanicals, Capacitors, Transistors, Drivers, Optoelectronics, Power Supply, Audio, Fuses, Switches, Integrated Circuits, Logic, Diodes, Interface, Miscellaneous, Radio&RF, Sensors, Processors, Mechanical, Inductors, LED, Amplifiers, Resistors, Data Converters, Relays, Batteries, Connectors, Crystals & Oscillators. (Map each typeid to one of these when building the manifest — e.g. `CER → Capacitors`.) Run it: ```bash # 1) close Chrome, relaunch on the operator's own profile with a debug port: # chrome.exe --remote-debugging-port=9222 --user-data-dir="%LOCALAPPDATA%\Google\Chrome\User Data" # 2) sign into the Workspace in that Chrome, then: python scripts/altium365_part_request.py --manifest part_requests.json \ --base https://.365.altium.com [--review-first | --no-submit] ``` `--no-submit` fills every form without saving (dry run); `--review-first` pauses after the first form so the operator can eyeball the mapping before the batch submits. The skill writes the `part_requests.json` manifest and commits each component's files to the operator's disk (device bridge) so the local `files` paths resolve. ## Safety and auditing - On the **first component of a run**, fill everything and **stop at Save** for the operator to eyeball the mapping. Once they confirm it looks right, Save it and loop the rest unattended. - **Log every submitted Request Id** (and any component that failed) so the run is auditable and re-runnable — never silently skip a component. - Browser automation follows the live UI. If a field, dropdown option, or a popup doesn't match what's expected, **pause and ask** rather than guessing — a wrong Component Type or a half-filled request is worse than one clarifying question. - Don't trigger native file-dialog blocking: use the extension's file-upload path for attachments, not an OS dialog.