Files
silo/pkg/calc/Addons.xcu
Forbes afb382b68d feat: LibreOffice Calc extension, ODS library, AI description, audit design
Calc extension (pkg/calc/):
- Python UNO ProtocolHandler with 8 toolbar commands
- SiloClient HTTP client adapted from FreeCAD workbench
- Pull BOM/Project: populates sheets with 28-col format, hidden property
  columns, row hash tracking, auto project tagging
- Push: row classification, create/update items, conflict detection
- Completion wizard: 3-step category/description/fields with PN conflict
  resolution dialog
- OpenRouter AI integration: generate standardized descriptions from seller
  text, configurable model/instructions, review dialog
- Settings: JSON persistence, env var fallbacks, OpenRouter fields
- 31 unit tests (no UNO/network required)

Go ODS library (internal/ods/):
- Pure Go ODS read/write (ZIP of XML, no headless LibreOffice)
- Writer, reader, 10 round-trip tests

Server ODS endpoints (internal/api/ods.go):
- GET /api/items/export.ods, template.ods, POST import.ods
- GET /api/items/{pn}/bom/export.ods
- GET /api/projects/{code}/sheet.ods
- POST /api/sheets/diff

Documentation:
- docs/CALC_EXTENSION.md: extension progress report
- docs/COMPONENT_AUDIT.md: web audit tool design with weighted scoring,
  assembly computed fields, batch AI assistance plan
2026-02-01 10:06:20 -06:00

236 lines
8.9 KiB
XML

<?xml version="1.0" encoding="UTF-8"?>
<oor:component-data xmlns:oor="http://openoffice.org/2001/registry"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
oor:name="Addons" oor:package="org.openoffice.Office">
<!-- Toolbar definition -->
<node oor:name="AddonUI">
<node oor:name="OfficeToolBar">
<node oor:name="io.kindredsystems.silo.calc.toolbar" oor:op="replace">
<node oor:name="m01" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloLogin</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Login</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m02" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPullBOM</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Pull BOM</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m03" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPullProject</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Pull Project</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m04" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPush</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Push</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m05" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloAddItem</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Add Item</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m06" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloRefresh</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Refresh</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m07" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloSettings</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Settings</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="m08" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloAIDescription</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">AI Describe</value>
</prop>
<prop oor:name="Target" oor:type="xs:string">
<value>_self</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
</node>
</node>
<!-- Menu entries under Tools menu -->
<node oor:name="AddonMenu">
<node oor:name="io.kindredsystems.silo.calc.menu.login" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloLogin</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Login</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.pullbom" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPullBOM</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Pull BOM</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.pullproject" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPullProject</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Pull Project Items</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.push" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloPush</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Push Changes</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.additem" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloAddItem</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Add Item</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.refresh" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloRefresh</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Refresh</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.settings" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloSettings</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: Settings</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
<node oor:name="io.kindredsystems.silo.calc.menu.aidescription" oor:op="replace">
<prop oor:name="URL" oor:type="xs:string">
<value>io.kindredsystems.silo.calc:SiloAIDescription</value>
</prop>
<prop oor:name="Title" oor:type="xs:string">
<value xml:lang="en">Silo: AI Describe</value>
</prop>
<prop oor:name="Context" oor:type="xs:string">
<value>com.sun.star.sheet.SpreadsheetDocument</value>
</prop>
</node>
</node>
</node>
</oor:component-data>