Backup état complet après enregistrement vidéo démo de bout en bout. À utiliser comme point de référence pour la consolidation post-démo. Changements majeurs de la session 18-19 mai : - AIVA-URGENCE : page autonome avec preset URL + auto-focus chain - Workflow Demo_urgence_3_db : merge linux_db + steps AIVA + pause humaine NoMachine - Bypass LLM (static_result / static_text) dans replay_engine pour démos déterministes sans appel Ollama - Fix api_stream:3013 — replay_paused au premier polling /next - dag_execute : lift duration_ms vers top-level pour wait runtime - NPM bypass auth /aiva-urgence/ via location ^~ (proxy_host/10.conf hors git) - scripts/cancel-replays.sh — workaround Stop VWB qui ne purge pas la queue Anchors visuels (468) forcés dans le commit pour garantir restorabilité. DB workflows actuelle + ~12 .bak DB de la journée incluses. Sujets identifiés pour consolidation post-démo (TODO) : 1. Bug VWB recapture anchor ne régénère pas le PNG 2. Léa client accumule état mémoire (restart périodique requis) 3. Stop VWB ne purge pas la queue serveur (lien manquant vers /replay/cancel) 4. Bug coord client mss tronqué 2560x60 → mapping Y cassé 5. delay_before/delay_after ignorés au runtime (fix partiel duration_ms) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
122 lines
4.3 KiB
Python
122 lines
4.3 KiB
Python
"""Ajoute 10 steps Excel à Demo_urgence_2_interop (ord 15-24).
|
|
|
|
Usage :
|
|
python tools/append_excel_steps_interop.py [--dry-run]
|
|
"""
|
|
from __future__ import annotations
|
|
import argparse
|
|
import json
|
|
import secrets
|
|
import sqlite3
|
|
import sys
|
|
import time
|
|
from pathlib import Path
|
|
|
|
DB_PATH = Path(__file__).resolve().parent.parent / "visual_workflow_builder" / "backend" / "instance" / "workflows.db"
|
|
WF_ID = "wf_56bf8fa2d332_1778666923" # Demo_urgence_2_interop
|
|
|
|
# (label, action_type, parameters_dict)
|
|
STEPS = [
|
|
("Win+D", "keyboard_shortcut", {"keys": ["win", "d"]}),
|
|
("Ouvre codage_urgence.xlsx", "double_click_anchor", {"by_text": "codage_urgence"}),
|
|
("Cellule A2", "click_anchor", {"by_text": "A2"}),
|
|
("IPP patient", "type_text", {"text": "25003284", "paste": False}),
|
|
("Tab", "keyboard_shortcut", {"keys": ["tab"]}),
|
|
("Décision T2A", "type_text", {"text": "{{dec.decision_court}}", "paste": False}),
|
|
("Tab", "keyboard_shortcut", {"keys": ["tab"]}),
|
|
("Résumé clinique", "type_text", {"text": "{{resume_patient}}", "paste": False}),
|
|
("Tab", "keyboard_shortcut", {"keys": ["tab"]}),
|
|
("Justification", "type_text", {"text": "{{justification_t2a}}", "paste": False}),
|
|
]
|
|
FIRST_ORD = 15 # le workflow cible a déjà ord 0..14
|
|
|
|
|
|
def new_step_id(ts: int) -> str:
|
|
return f"step_{secrets.token_hex(6)}_{ts}"
|
|
|
|
|
|
def main() -> int:
|
|
p = argparse.ArgumentParser()
|
|
p.add_argument("--dry-run", action="store_true")
|
|
args = p.parse_args()
|
|
|
|
if not DB_PATH.exists():
|
|
print(f"ERREUR : DB introuvable {DB_PATH}", file=sys.stderr)
|
|
return 1
|
|
|
|
conn = sqlite3.connect(DB_PATH)
|
|
conn.row_factory = sqlite3.Row
|
|
cur = conn.cursor()
|
|
|
|
# Garde : workflow existe + ord libre à partir de FIRST_ORD
|
|
wf = cur.execute("SELECT id FROM workflows WHERE id = ?", (WF_ID,)).fetchone()
|
|
if not wf:
|
|
print(f"ERREUR : workflow {WF_ID} introuvable", file=sys.stderr)
|
|
return 2
|
|
max_ord = cur.execute(
|
|
'SELECT COALESCE(MAX("order"), -1) FROM steps WHERE workflow_id = ?',
|
|
(WF_ID,),
|
|
).fetchone()[0]
|
|
if max_ord + 1 != FIRST_ORD:
|
|
print(
|
|
f"ERREUR : ord libre attendu {FIRST_ORD}, trouvé max_ord+1={max_ord + 1}",
|
|
file=sys.stderr,
|
|
)
|
|
return 3
|
|
|
|
ts = int(time.time())
|
|
now_iso = time.strftime("%Y-%m-%d %H:%M:%S")
|
|
rows = []
|
|
for i, (label, atype, params) in enumerate(STEPS):
|
|
rows.append({
|
|
"id": new_step_id(ts + i),
|
|
"workflow_id": WF_ID,
|
|
"action_type": atype,
|
|
"order": FIRST_ORD + i,
|
|
"position_x": None,
|
|
"position_y": None,
|
|
"parameters_json": json.dumps(params, ensure_ascii=False),
|
|
"anchor_id": None,
|
|
"label": label,
|
|
"created_at": now_iso,
|
|
"updated_at": now_iso,
|
|
})
|
|
|
|
print(f"\nWorkflow : {WF_ID}")
|
|
print(f"{'ord':>3} {'action_type':<22} label parameters_json")
|
|
print("-" * 110)
|
|
for r in rows:
|
|
print(f"{r['order']:>3} {r['action_type']:<22} {r['label']:<30} {r['parameters_json']}")
|
|
print()
|
|
|
|
if args.dry_run:
|
|
print("--dry-run : aucune modification de la DB.")
|
|
return 0
|
|
|
|
try:
|
|
cur.execute("BEGIN")
|
|
for r in rows:
|
|
cur.execute(
|
|
"""
|
|
INSERT INTO steps
|
|
(id, workflow_id, action_type, "order", position_x, position_y,
|
|
parameters_json, anchor_id, label, created_at, updated_at)
|
|
VALUES (:id, :workflow_id, :action_type, :order, :position_x, :position_y,
|
|
:parameters_json, :anchor_id, :label, :created_at, :updated_at)
|
|
""",
|
|
r,
|
|
)
|
|
conn.commit()
|
|
print(f"OK — {len(rows)} steps insérés (ord {FIRST_ORD}..{FIRST_ORD + len(rows) - 1})")
|
|
return 0
|
|
except Exception as e:
|
|
conn.rollback()
|
|
print(f"ROLLBACK — {e}", file=sys.stderr)
|
|
return 5
|
|
finally:
|
|
conn.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|