feat(infra): grupo claude-fleet — FleetView TUI + orquestacion de Claudes
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI: - list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals + runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId. - list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables. - wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console (preserva ancho del sidebar), tmux_map_claude_panes. - launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r, mouse on, remain-on-exit off; fija el ancho del sidebar con hooks. - docs/capabilities/claude-fleet.md + entrada en el INDEX. Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes varios de docs e infra de otra sesion, agrupados aqui para no perderlos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
---
|
||||
name: add_xlsx_chart
|
||||
kind: function
|
||||
lang: py
|
||||
domain: infra
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "def add_xlsx_chart(xlsx_path: str, sheet_name: str, chart_type: str, data_range: str, cats_range: str = None, anchor: str = 'H2', title: str = '', x_title: str = '', y_title: str = '') -> dict"
|
||||
description: "Anade un grafico nativo de openpyxl a una hoja EXISTENTE de un libro .xlsx existente, refiriendo rangos de celdas ya escritos. chart_type en {bar, line, pie, scatter} (BarChart/LineChart/PieChart/ScatterChart). data_range y cats_range en notacion Excel tipo 'B1:B10' (se convierten a Reference). anchor = celda destino del chart (ej. 'H2'). Acepta titulo del grafico y de los ejes X/Y. Guarda el libro. Es la pieza que completa el grupo excel para generar hojas con graficos: primero escribir datos (write_xlsx_sheets) y luego anadir el chart. Impura: escribe disco y NO lanza: en fallo (hoja/libro inexistente, chart_type invalido, rango invalido) devuelve {status: 'error', error}."
|
||||
tags: [excel, xlsx, chart, openpyxl, spreadsheet, office, onlyoffice, viz, io, infra]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [openpyxl]
|
||||
params:
|
||||
- name: xlsx_path
|
||||
desc: "Ruta al archivo .xlsx EXISTENTE. Esta funcion NO crea el libro: escribe primero los datos con write_xlsx_sheets/upsert_xlsx_sheet. Vacio o inexistente devuelve {status: 'error'} (no lanza)."
|
||||
- name: sheet_name
|
||||
desc: "Nombre de la hoja (ya existente) donde se ancla el grafico y de la que provienen los rangos. Si no existe, devuelve {status: 'error'} con la lista de hojas disponibles."
|
||||
- name: chart_type
|
||||
desc: "Tipo de grafico. Uno de: 'bar', 'line', 'pie', 'scatter' (case-insensitive, se normaliza). Cualquier otro valor devuelve {status: 'error'} con la lista de validos."
|
||||
- name: data_range
|
||||
desc: "Rango de celdas de los valores a graficar, en notacion Excel tipo 'B1:B10'. Se convierte a openpyxl.chart.Reference (1-indexed). Si abarca la cabecera (fila 1), se toma el nombre de la serie de esa primera celda (titles_from_data). Rango invalido devuelve {status: 'error'}."
|
||||
- name: cats_range
|
||||
desc: "Rango de las categorias/etiquetas del eje X (o labels de pie), tipo 'A2:A10'. None (default) = sin categorias explicitas. Para scatter se usa como valores X (xvalues) de la serie."
|
||||
- name: anchor
|
||||
desc: "Celda destino (esquina superior izquierda) del grafico, p.ej. 'H2'. Default 'H2'. Ancla el chart sin desplazar las celdas de datos."
|
||||
- name: title
|
||||
desc: "Titulo del grafico. Vacio (default) = sin titulo."
|
||||
- name: x_title
|
||||
desc: "Titulo del eje X. Vacio (default) = sin titulo. Ignorado por pie (no tiene ejes)."
|
||||
- name: y_title
|
||||
desc: "Titulo del eje Y. Vacio (default) = sin titulo. Ignorado por pie (no tiene ejes)."
|
||||
output: "Dict. En exito: {status: 'ok', chart_type: <str normalizado>, sheet: <str>, anchor: <str>}. En error: {status: 'error', error: '<mensaje>'}."
|
||||
tested: true
|
||||
tests: ["test_add_bar_chart_reabre_y_verifica", "test_add_line_chart", "test_add_pie_chart", "test_add_scatter_chart", "test_dos_charts_en_la_misma_hoja", "test_chart_type_invalido_devuelve_error", "test_hoja_inexistente_devuelve_error", "test_libro_inexistente_devuelve_error", "test_data_range_invalido_devuelve_error", "test_xlsx_path_vacio_devuelve_error"]
|
||||
test_file_path: "python/functions/infra/add_xlsx_chart_test.py"
|
||||
file_path: "python/functions/infra/add_xlsx_chart.py"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```python
|
||||
import sys, os
|
||||
sys.path.insert(0, os.path.join("python", "functions"))
|
||||
from infra.write_xlsx_sheets import write_xlsx_sheets
|
||||
from infra.add_xlsx_chart import add_xlsx_chart
|
||||
|
||||
# 1) Escribe los datos (cabecera + filas)
|
||||
write_xlsx_sheets("/tmp/ventas_chart.xlsx", {
|
||||
"Ventas": [
|
||||
["Mes", "Unidades"],
|
||||
["Ene", 120],
|
||||
["Feb", 150],
|
||||
["Mar", 90],
|
||||
["Abr", 200],
|
||||
],
|
||||
})
|
||||
|
||||
# 2) Anade un grafico de barras refiriendo los rangos ya escritos
|
||||
res = add_xlsx_chart(
|
||||
xlsx_path="/tmp/ventas_chart.xlsx",
|
||||
sheet_name="Ventas",
|
||||
chart_type="bar",
|
||||
data_range="B1:B5", # incluye la cabecera 'Unidades' -> nombre de la serie
|
||||
cats_range="A2:A5", # meses como categorias del eje X
|
||||
anchor="D2", # esquina superior izquierda del chart
|
||||
title="Unidades por mes",
|
||||
x_title="Mes",
|
||||
y_title="Unidades",
|
||||
)
|
||||
print(res)
|
||||
# {'status': 'ok', 'chart_type': 'bar', 'sheet': 'Ventas', 'anchor': 'D2'}
|
||||
|
||||
# Verificar que el chart quedo en la hoja
|
||||
from openpyxl import load_workbook
|
||||
wb = load_workbook("/tmp/ventas_chart.xlsx")
|
||||
print(len(wb["Ventas"]._charts)) # 1
|
||||
```
|
||||
|
||||
## Cuando usarla
|
||||
|
||||
Usala cuando necesites **generar una hoja de Excel con un grafico** a partir de
|
||||
datos que ya escribiste en el libro: dashboards exportables, reports con
|
||||
visualizacion embebida, resumenes que se abren en Excel/OnlyOffice mostrando el
|
||||
chart. Es el ultimo paso del flujo del grupo `excel`: `write_xlsx_sheets`
|
||||
(o `upsert_xlsx_sheet`) escribe los datos, y esta funcion les anade el grafico
|
||||
refiriendo sus rangos. Llamala una vez por grafico (puedes anadir varios a la
|
||||
misma hoja con distintos `anchor`).
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Impura — escribe en disco.** Reabre el libro, anade el chart y lo GUARDA.
|
||||
No lanza: devuelve `{"status": "error", ...}` ante libro inexistente, hoja
|
||||
inexistente, `chart_type` invalido, rango invalido o openpyxl ausente.
|
||||
- **El libro DEBE existir.** Esta funcion no crea el .xlsx ni escribe datos:
|
||||
los rangos (`data_range`, `cats_range`) deben apuntar a celdas YA escritas.
|
||||
Escribe primero con `write_xlsx_sheets`/`upsert_xlsx_sheet`.
|
||||
- **openpyxl carga el libro entero en memoria** para reabrirlo y reescribirlo.
|
||||
Para libros muy grandes esto consume RAM proporcional al tamano.
|
||||
- **Los `Reference` de openpyxl son 1-indexed** (fila 1, columna 1 = A1). La
|
||||
conversion desde notacion `'B1:B10'` la hace `range_boundaries` internamente;
|
||||
si pasas un rango mal formado, devuelve error en vez de un chart vacio.
|
||||
- **`titles_from_data`**: si `data_range` incluye la fila 1 (cabecera), el
|
||||
nombre de la serie se toma de esa primera celda. Si tu `data_range` empieza en
|
||||
fila 2 (solo datos), la serie queda sin nombre — incluye la cabecera para
|
||||
etiquetarla.
|
||||
- **scatter es distinto**: usa `data_range` como valores Y y `cats_range` como
|
||||
valores X (xvalues) de una unica serie via `Series`. No usa `set_categories`
|
||||
como bar/line/pie. Para scatter, pasa rangos de SOLO datos (sin cabecera) en
|
||||
ambos.
|
||||
- **pie ignora `x_title`/`y_title`** (no tiene ejes). Pasarlos no falla, se
|
||||
ignoran silenciosamente.
|
||||
- **El chart NO se recalcula solo**: openpyxl escribe la definicion del grafico;
|
||||
Excel/LibreOffice lo renderiza al abrir. Si cambias los datos despues, vuelve
|
||||
a llamar a la funcion o edita el rango — el chart referencia celdas, asi que
|
||||
reflejara el valor que tengan al abrir el libro.
|
||||
- **Requiere openpyxl** (ya instalado en `python/.venv`, version 3.1.5).
|
||||
Reference in New Issue
Block a user