From 7fc1ae0fa734975ccb13aaad11c9015779e792ce Mon Sep 17 00:00:00 2001 From: datasheet-extractor Date: Tue, 7 Jul 2026 07:40:38 +0000 Subject: [PATCH] Sync datasheet-extractor skill (SKILL.md, scripts, assets, references, config; token blanked) --- SKILL.md | 148 ++++++++++++++++++++++++++++++ assets/template/Type_ID.xlsx | Bin 0 -> 16764 bytes assets/template/VERSION | 1 + assets/template/template.xlsx | Bin 0 -> 25393 bytes assets/vecmocon-logo.png | Bin 0 -> 12111 bytes config/gitea.env | 10 ++ references/taxonomy.md | 167 ++++++++++++++++++++++++++++++++++ scripts/append_parameter.py | 27 ++++++ scripts/fill_templates.py | 100 ++++++++++++++++++++ scripts/push_to_gitea.sh | 38 ++++++++ 10 files changed, 491 insertions(+) create mode 100644 SKILL.md create mode 100644 assets/template/Type_ID.xlsx create mode 100644 assets/template/VERSION create mode 100644 assets/template/template.xlsx create mode 100644 assets/vecmocon-logo.png create mode 100644 config/gitea.env create mode 100644 references/taxonomy.md create mode 100644 scripts/append_parameter.py create mode 100644 scripts/fill_templates.py create mode 100644 scripts/push_to_gitea.sh diff --git a/SKILL.md b/SKILL.md new file mode 100644 index 0000000..373ac5d --- /dev/null +++ b/SKILL.md @@ -0,0 +1,148 @@ +--- +name: datasheet-extractor +description: >- + Extract key parameters from component datasheet PDFs into the Vecmocon master + template (18 component types incl. resistors, capacitors, inductors, diodes, + transistors, ICs, protection, power modules, connectors, sensors, and more). + Column A = MPN_make_typeid (make = first word of manufacturer, typeid from the + taxonomy). Writes one Excel file per type with a Meta sheet holding the template + version, assembles a per-part DFS folder (datasheet, footprint, symbol), and pushes + design files to the Gitea DFS repo, Excel outputs to the Parameters repo, and skill + files plus templates to the Skill_Assets repo. Also appends new parameters to a + template as a new version. Use WHENEVER the user uploads component datasheets and + asks to extract parameters, build the parameter sheets or component library, or push + datasheets to Gitea. ALWAYS trigger when the user types "\datasheet". +--- + +# Datasheet Extractor + +Read component datasheets, fill the customer's master template, assemble each part's +design-file folder, and publish everything to three Gitea repos. Be careful and honest: +put every value in the right column and unit, and flag what a datasheet does not state. + +## Inputs + +- **Datasheet PDFs**, one per part. The filename is the part's MPN (search that exact + number inside a series datasheet to read the right variant). +- No project/version is needed — repos use a **flat layout**. + +## The identifier: `MPN_make_typeid` + +Column A of every sheet (header `MPN_make_type`) and each DFS folder name is: + +``` +__ e.g. BAT46WJ_Nexperia_SCH +``` + +- **make** = the **first word of the manufacturer** name (Texas Instruments → `Texas`, + Nexperia → `Nexperia`, STMicroelectronics → `STMicroelectronics`). +- **typeid** = the Type ID for the part's subclass, from the taxonomy in + `references/taxonomy.md` (full source `assets/template/Type_ID.xlsx`). e.g. Schottky → + `SCH`, TVS → `TVS`, MOSFET → `MOS`, LDO → `LDO`, Common-mode choke → `CMC`. + +## Workflow + +1. **Read each datasheet.** Get MPN (from filename), manufacturer, and the parameters. +2. **Classify** to one of the 18 **types** (= template sheet names) and to a **subclass** + from `references/taxonomy.md`; record its **typeid**. The subclass name goes in the + `Class` column where the sheet has one. +3. **Extract values** into that type's columns (headers come from + `assets/template/template.xlsx`). Convert to each header's unit; leave blank if the + datasheet doesn't state it (an honest blank beats a guess). +4. **Build the Excel outputs** with `scripts/fill_templates.py` — one `.xlsx` per + type present, column A = `MPN_make_typeid`, plus a **Meta** sheet holding the template + version. (See Producing outputs.) +5. **Assemble each part's DFS folder** `MPN_make_typeid/` containing `MPN_data` (the + datasheet), `MPN_fp` (footprint), `MPN_sym` (symbol). See Footprint & symbol. +6. **Push to the three Gitea repos** (flat): DFS folders → **DFS**, Excel outputs → + **Parameters**, skill files + templates → **Skill_Assets**. See Pushing to Gitea. + +## Producing outputs + +Collect what you extracted into `parts.json` (keys match template headers; `typeid` and +`subclass` from the taxonomy; `manufacturer` used for the make tag): + +```json +{"parts":[ + {"type":"Diode","mpn":"BAT46WJ","manufacturer":"Nexperia","typeid":"SCH","subclass":"Schottky", + "values":{"Description":"100 V 250 mA Schottky, SOD323F","Forward Voltage(V)":"0.71","Package":"SOD323F"}} +]} +``` + +```bash +python scripts/fill_templates.py parts.json \ + --template assets/template/template.xlsx --dest +``` + +Produces one `.xlsx` per type present (only types with parts), each with a **Meta** +sheet (Template Version, date, type, part count). Deliver these files to the user, and +push them to the Parameters repo. + +## Footprint & symbol (for the DFS folder) + +For each part, the DFS folder needs `MPN_fp` (footprint) and `MPN_sym` (symbol) beside +`MPN_data` (the datasheet). Get them like this, in order: + +1. **Search the web** for the part's footprint and schematic symbol by MPN (e.g. SnapEDA, + Ultra Librarian, Component Search Engine, the manufacturer's CAD models). If found, + **cross-check** the footprint's pad/pin count and dimensions against the datasheet's + package drawing before using it. +2. **If not found, generate** the footprint/symbol yourself from the datasheet's package + and pinout **only if you can do so reliably**, then cross-check with the user before + trusting it. +3. **If neither is possible**, still create the folder with the datasheet, and **tell the + user that the footprint and/or symbol needs a manual build** for that MPN (leave a + clearly-named placeholder or omit and list it). + +Keep the datasheet's extension on `MPN_data` (e.g. `BAT46WJ_data.pdf`). Name footprint/ +symbol files `MPN_fp` / `MPN_sym` with whatever extension the source/format uses. + +## Pushing to Gitea + +Connection + repos are pre-configured in `config/gitea.env` (host, user, token, and the +three repos), so runs need no per-session token. Layout is **flat** (no project/version). +Use `scripts/push_to_gitea.sh` (git over HTTPS), once per repo: + +```bash +# 1) design files -> DFS repo (staging dir holds MPN_make_typeid/ folders) +bash scripts/push_to_gitea.sh --repo "$DFS_REPO" --src --message "Add datasheets/fp/sym" +# 2) Excel outputs -> Parameters repo +bash scripts/push_to_gitea.sh --repo "$PARAMS_REPO" --src --message "Update parameters" +# 3) skill files + templates -> Skill_Assets repo +bash scripts/push_to_gitea.sh --repo "$SKILL_ASSETS_REPO" --src --message "Sync skill assets" +``` + +`$DFS_REPO`, `$PARAMS_REPO`, `$SKILL_ASSETS_REPO` come from `config/gitea.env`. The +script clones the repo, copies the source contents in (flat), commits, and pushes; the +repos must already exist. If the host is unreachable (e.g. Cowork without the domain +allowlisted) it fails clearly and leaves the staged files for a manual push. + +**Push the skill files organised** to Skill_Assets: keep the skill's own structure +(`SKILL.md`, `scripts/`, `assets/`, `references/`, `config/`) — but do **not** push the +real token. Before syncing skill assets, blank the `GIT_TOKEN` line in the copy you push, +or push everything except `config/gitea.env`. + +## Updating a template (new parameter) + +When the user wants a new parameter on a type, **append it at the end** of that type's +sheet and bump the version: + +```bash +python scripts/append_parameter.py --type Diode --param "Reverse Recovery Time(ns)" \ + --template assets/template/template.xlsx +``` + +This adds the column at the end and increments `assets/template/VERSION` (v1 → v2 → …). +Then **push the updated `assets/template/template.xlsx` + `VERSION` to the Skill_Assets +repo** so the new template version is archived. New outputs will record the new version in +their Meta sheet automatically. + +## Resources + +- `assets/template/template.xlsx` — master template, one sheet per type (source of headers). +- `assets/template/Type_ID.xlsx` + `references/taxonomy.md` — Class → Subclass → Type ID. +- `assets/template/VERSION` — current template version (integer; Meta sheet shows `vN`). +- `scripts/fill_templates.py` — build per-type Excel outputs (+ Meta sheet). +- `scripts/push_to_gitea.sh` — push a folder's contents to a Gitea repo (flat). +- `scripts/append_parameter.py` — append a parameter to a template + bump version. +- `config/gitea.env` — host, user, token, and the DFS / Parameters / Skill_Assets repos (**secret**). diff --git a/assets/template/Type_ID.xlsx b/assets/template/Type_ID.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..2c0c1f7f539d3d7ff31345d568b07a243e02de38 GIT binary patch literal 16764 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 F_doD~gRcMp literal 0 HcmV?d00001 diff --git a/assets/vecmocon-logo.png b/assets/vecmocon-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..4a293b5f4557d444431289995c7b1f1d0cd87244 GIT binary patch literal 12111 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.xlsx containing the filled type sheet +plus a Meta sheet (template version, date). Column A ("MPN_make_type") is set to +__, where make = first word of the manufacturer and typeid comes +from the taxonomy (Type_ID.xlsx), supplied per part as "typeid". + +parts.json: +{ + "parts": [ + {"type": "Diode", "mpn": "BAT46WJ", "manufacturer": "Nexperia", + "typeid": "SCH", "subclass": "Schottky", + "values": {"Description": "...", "Forward Voltage(V)": "0.71", ...}} + ] +} +Usage: python fill_templates.py parts.json --template --dest [--version v1] +""" +import argparse, json, os, re, datetime +import openpyxl +from openpyxl.styles import Font, PatternFill, Alignment, Border, Side + +GREEN="B6D7A8"; GRAY="BFBFBF" +def norm(s): return re.sub(r'[^a-z0-9]', '', str(s).lower()) +ALIAS={"induactanceuh":"inductanceuh"} # template header typo -> value key + +def make_tag(manufacturer): + w = re.split(r'\s+', str(manufacturer).strip()) + first = w[0] if w and w[0] else "NA" + return re.sub(r'[^A-Za-z0-9]', '', first) or "NA" + +def style_header(cell): + cell.font=Font(name="Calibri", bold=True); cell.fill=PatternFill("solid", fgColor=GREEN) + s=Side(style="thin", color=GRAY); cell.border=Border(left=s,right=s,top=s,bottom=s) + cell.alignment=Alignment(horizontal="center", vertical="center", wrap_text=True) + +def main(): + ap=argparse.ArgumentParser() + ap.add_argument("parts_json"); ap.add_argument("--template", required=True) + ap.add_argument("--dest", required=True); ap.add_argument("--version", default=None) + a=ap.parse_args() + data=json.load(open(a.parts_json, encoding="utf-8")) + version=a.version + if not version: + vf=os.path.join(os.path.dirname(a.template), "VERSION") + version="v"+open(vf).read().strip() if os.path.exists(vf) else "v1" + os.makedirs(a.dest, exist_ok=True) + master=openpyxl.load_workbook(a.template) + by={} + for p in data.get("parts", []): + by.setdefault(p["type"], []).append(p) + + for ctype, parts in by.items(): + if ctype not in master.sheetnames: + print(f"! no template sheet for type '{ctype}' - skipping"); continue + msheet=master[ctype] + headers=[msheet.cell(1,c).value for c in range(1, msheet.max_column+1)] + out=openpyxl.Workbook(); ws=out.active; ws.title=ctype[:31] + for c,h in enumerate(headers, start=1): + ws.cell(1,c,h); style_header(ws.cell(1,c)) + ws.row_dimensions[1].height=30 + r=2 + for p in parts: + vals={norm(k):v for k,v in p.get("values", {}).items()} + make=p.get("make") or make_tag(p.get("manufacturer","")) + tid=p.get("typeid","NA") + colA=f'{p.get("mpn","")}_{make}_{tid}' + for c,h in enumerate(headers, start=1): + key=norm(h); key=ALIAS.get(key,key) + if c==1: + ws.cell(r,c,colA) + elif key=="class": + ws.cell(r,c,p.get("subclass","")) + elif key=="manufacturer": + ws.cell(r,c,p.get("manufacturer", vals.get("manufacturer",""))) + else: + ws.cell(r,c,vals.get(key,"")) + r+=1 + # column widths + from openpyxl.utils import get_column_letter + for c,h in enumerate(headers, start=1): + w=32 if norm(h)=="description" else (24 if c==1 else max(11,min(18,len(str(h))+2))) + ws.column_dimensions[get_column_letter(c)].width=w + ws.freeze_panes="A2" + # Meta sheet + meta=out.create_sheet("Meta") + rows=[("Template Version", version), + ("Generated", datetime.date.today().isoformat()), + ("Component Type", ctype), + ("Parts in file", len(parts)), + ("Source", "datasheet-extractor skill")] + for i,(k,v) in enumerate(rows, start=1): + meta.cell(i,1,k).font=Font(bold=True); meta.cell(i,2,v) + meta.column_dimensions["A"].width=20; meta.column_dimensions["B"].width=40 + fn=re.sub(r'\s+','_',ctype)+".xlsx" + out.save(os.path.join(a.dest, fn)) + print(f"{ctype}: {len(parts)} row(s) -> {fn} (template {version})") + +if __name__=="__main__": + main() diff --git a/scripts/push_to_gitea.sh b/scripts/push_to_gitea.sh new file mode 100644 index 0000000..118985e --- /dev/null +++ b/scripts/push_to_gitea.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +# Push the CONTENTS of a source dir to a Gitea repo (flat, at repo root or a subdir). +# Connection (GIT_HOST/GIT_USER/GIT_TOKEN) comes from env or config/gitea.env. +# Usage: bash push_to_gitea.sh --repo --src [--subdir ] [--message "msg"] +set -euo pipefail +HERE="$(cd "$(dirname "$0")" && pwd)" +CFG="$HERE/../config/gitea.env" +if [[ -f "$CFG" ]]; then + while IFS='=' read -r k v; do + [[ "$k" =~ ^[A-Z_]+$ ]] || continue + case "$k" in GIT_HOST|GIT_USER|GIT_TOKEN) + [[ -z "${!k:-}" ]] && export "$k=$v" ;; esac + done < "$CFG" +fi +HOST="${GIT_HOST:-}" USER_="${GIT_USER:-}" TOKEN="${GIT_TOKEN:-}" +REPO="" SRC="" SUBDIR="" MSG="" +while [[ $# -gt 0 ]]; do case "$1" in + --repo) REPO="$2"; shift 2;; --src) SRC="$2"; shift 2;; + --subdir) SUBDIR="$2"; shift 2;; --message) MSG="$2"; shift 2;; + *) echo "unknown arg: $1" >&2; exit 2;; esac; done +[[ -z "$REPO" || -z "$SRC" || -z "$HOST" || -z "$TOKEN" ]] && { echo "need --repo, --src, and GIT_HOST/GIT_TOKEN" >&2; exit 2; } +[[ -d "$SRC" ]] || { echo "ERROR: src not found: $SRC" >&2; exit 2; } +[[ -z "$MSG" ]] && MSG="Update from datasheet-extractor" +HOST="${HOST#http://}"; HOST="${HOST#https://}"; HOST="${HOST%/}" +CRED="${USER_:+$USER_:}${TOKEN}" +URL="https://${CRED}@${HOST}/${REPO}.git" +scrub(){ sed -e "s/${TOKEN}/***/g"; } +WORK="$(mktemp -d)" +git clone "$URL" "$WORK" 2>&1 | scrub || { echo "ERROR: clone failed (repo must exist + host reachable + token scope)"; exit 3; } +cd "$WORK"; git checkout -B main >/dev/null 2>&1 || true +DEST="$WORK${SUBDIR:+/$SUBDIR}"; mkdir -p "$DEST" +cp -r "$SRC/." "$DEST/" +git config user.email "datasheet-bot@local"; git config user.name "datasheet-extractor" +git add -A +if git diff --cached --quiet; then echo "Nothing new for $REPO."; else + git commit -m "$MSG" >/dev/null; git push -u origin main 2>&1 | scrub +fi +echo "Pushed to https://${HOST}/${REPO}${SUBDIR:+/$SUBDIR} ($(find "$SRC" -type f | wc -l | tr -d ' ') file(s))"