@rudderhq/server 0.5.1 → 0.5.2-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bootstrap/create-http-app.d.ts.map +1 -1
- package/dist/bootstrap/create-http-app.js +2 -1
- package/dist/bootstrap/create-http-app.js.map +1 -1
- package/dist/bundled-plugins/plugin-linear/dist/worker.js +128 -7
- package/dist/bundled-plugins/plugin-linear/dist/worker.js.map +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -18
- package/dist/index.js.map +1 -1
- package/dist/middleware/index.d.ts +1 -1
- package/dist/middleware/index.d.ts.map +1 -1
- package/dist/middleware/index.js +1 -1
- package/dist/middleware/index.js.map +1 -1
- package/dist/middleware/logger.d.ts +3 -0
- package/dist/middleware/logger.d.ts.map +1 -1
- package/dist/middleware/logger.js +31 -2
- package/dist/middleware/logger.js.map +1 -1
- package/dist/middleware/logger.test.d.ts +2 -0
- package/dist/middleware/logger.test.d.ts.map +1 -0
- package/dist/middleware/logger.test.js +50 -0
- package/dist/middleware/logger.test.js.map +1 -0
- package/dist/routes/agents.d.ts.map +1 -1
- package/dist/routes/agents.js +28 -6
- package/dist/routes/agents.js.map +1 -1
- package/dist/routes/browser.d.ts.map +1 -1
- package/dist/routes/browser.js +215 -4
- package/dist/routes/browser.js.map +1 -1
- package/dist/routes/instance-settings.d.ts.map +1 -1
- package/dist/routes/instance-settings.js +3 -0
- package/dist/routes/instance-settings.js.map +1 -1
- package/dist/routes/messenger.d.ts.map +1 -1
- package/dist/routes/messenger.js +11 -3
- package/dist/routes/messenger.js.map +1 -1
- package/dist/routes/onboarding.d.ts.map +1 -1
- package/dist/routes/onboarding.js +109 -17
- package/dist/routes/onboarding.js.map +1 -1
- package/dist/routes/orgs.d.ts.map +1 -1
- package/dist/routes/orgs.js +70 -8
- package/dist/routes/orgs.js.map +1 -1
- package/dist/runtime/http-server-shutdown.d.ts +15 -0
- package/dist/runtime/http-server-shutdown.d.ts.map +1 -0
- package/dist/runtime/http-server-shutdown.js +70 -0
- package/dist/runtime/http-server-shutdown.js.map +1 -0
- package/dist/runtime/http-server-shutdown.test.d.ts +2 -0
- package/dist/runtime/http-server-shutdown.test.d.ts.map +1 -0
- package/dist/runtime/http-server-shutdown.test.js +94 -0
- package/dist/runtime/http-server-shutdown.test.js.map +1 -0
- package/dist/services/access.d.ts +2 -2
- package/dist/services/agent-instructions.d.ts.map +1 -1
- package/dist/services/agent-instructions.js +1 -0
- package/dist/services/agent-instructions.js.map +1 -1
- package/dist/services/browser-broker.d.ts +5 -1
- package/dist/services/browser-broker.d.ts.map +1 -1
- package/dist/services/browser-broker.js +55 -4
- package/dist/services/browser-broker.js.map +1 -1
- package/dist/services/browser-broker.test.js +58 -0
- package/dist/services/browser-broker.test.js.map +1 -1
- package/dist/services/chats.d.ts +3 -3
- package/dist/services/integrations/feishu/user-bindings.d.ts +1 -1
- package/dist/services/knowledge-portability/organization-skills.catalog.d.ts +1 -1
- package/dist/services/messenger-saved-views.d.ts +45 -20
- package/dist/services/messenger-saved-views.d.ts.map +1 -1
- package/dist/services/messenger-saved-views.js +260 -67
- package/dist/services/messenger-saved-views.js.map +1 -1
- package/dist/services/messenger.d.ts.map +1 -1
- package/dist/services/messenger.js +4 -3
- package/dist/services/messenger.js.map +1 -1
- package/dist/services/organization-workspace-browser.d.ts +7 -0
- package/dist/services/organization-workspace-browser.d.ts.map +1 -1
- package/dist/services/organization-workspace-browser.js +87 -7
- package/dist/services/organization-workspace-browser.js.map +1 -1
- package/package.json +13 -13
- package/resources/bundled-skills/browser/SKILL.md +172 -41
- package/resources/bundled-skills/browser/agents/openai.yaml +12 -2
- package/resources/bundled-skills/browser/evals/evals.json +41 -0
- package/resources/bundled-skills/browser/references/interaction-guide.md +171 -0
- package/resources/bundled-skills/browser/references/tool-contract.md +192 -68
- package/resources/bundled-skills/rudder-docs/references/cli-reference.md +18 -1
- package/resources/bundled-skills/skill-creator/CHANGELOG.md +26 -0
- package/resources/bundled-skills/skill-creator/LICENSE.txt +202 -0
- package/resources/bundled-skills/skill-creator/SKILL.md +544 -3
- package/resources/bundled-skills/skill-creator/agents/analyzer.md +274 -0
- package/resources/bundled-skills/skill-creator/agents/comparator.md +202 -0
- package/resources/bundled-skills/skill-creator/agents/grader.md +223 -0
- package/resources/bundled-skills/skill-creator/assets/eval_review.html +146 -0
- package/resources/bundled-skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/resources/bundled-skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/resources/bundled-skills/skill-creator/references/compatibility/claudecode.md +29 -0
- package/resources/bundled-skills/skill-creator/references/compatibility/codex.md +69 -0
- package/resources/bundled-skills/skill-creator/references/compatibility/other.md +41 -0
- package/resources/bundled-skills/skill-creator/references/rudder.md +96 -0
- package/resources/bundled-skills/skill-creator/references/schemas.md +430 -0
- package/resources/bundled-skills/skill-creator/scripts/__init__.py +0 -0
- package/resources/bundled-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/resources/bundled-skills/skill-creator/scripts/generate_report.py +335 -0
- package/resources/bundled-skills/skill-creator/scripts/improve_description.py +197 -0
- package/resources/bundled-skills/skill-creator/scripts/model_backends.py +115 -0
- package/resources/bundled-skills/skill-creator/scripts/package_skill.py +136 -0
- package/resources/bundled-skills/skill-creator/scripts/quick_validate.py +103 -0
- package/resources/bundled-skills/skill-creator/scripts/run_eval.py +363 -0
- package/resources/bundled-skills/skill-creator/scripts/run_loop.py +319 -0
- package/resources/bundled-skills/skill-creator/scripts/utils.py +223 -0
- package/skills/browser/SKILL.md +172 -41
- package/skills/browser/agents/openai.yaml +12 -2
- package/skills/browser/evals/evals.json +41 -0
- package/skills/browser/references/interaction-guide.md +171 -0
- package/skills/browser/references/tool-contract.md +192 -68
- package/skills/rudder-docs/references/cli-reference.md +18 -1
- package/skills/skill-creator/CHANGELOG.md +26 -0
- package/skills/skill-creator/LICENSE.txt +202 -0
- package/skills/skill-creator/SKILL.md +544 -3
- package/skills/skill-creator/agents/analyzer.md +274 -0
- package/skills/skill-creator/agents/comparator.md +202 -0
- package/skills/skill-creator/agents/grader.md +223 -0
- package/skills/skill-creator/assets/eval_review.html +146 -0
- package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/skill-creator/references/compatibility/claudecode.md +29 -0
- package/skills/skill-creator/references/compatibility/codex.md +69 -0
- package/skills/skill-creator/references/compatibility/other.md +41 -0
- package/skills/skill-creator/references/rudder.md +96 -0
- package/skills/skill-creator/references/schemas.md +430 -0
- package/skills/skill-creator/scripts/__init__.py +0 -0
- package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/skill-creator/scripts/generate_report.py +335 -0
- package/skills/skill-creator/scripts/improve_description.py +197 -0
- package/skills/skill-creator/scripts/model_backends.py +115 -0
- package/skills/skill-creator/scripts/package_skill.py +136 -0
- package/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/skills/skill-creator/scripts/run_eval.py +363 -0
- package/skills/skill-creator/scripts/run_loop.py +319 -0
- package/skills/skill-creator/scripts/utils.py +223 -0
- package/ui-dist/assets/{abnfDiagram-VRR7QNED-CAAPm9Nj.js → abnfDiagram-VRR7QNED-DLc7ClAF.js} +1 -1
- package/ui-dist/assets/{arc-DOFoNr3M.js → arc-B9ISB5mW.js} +1 -1
- package/ui-dist/assets/{architectureDiagram-ZJ3FMSHR-DRg6yhG8.js → architectureDiagram-ZJ3FMSHR-5zowBbVV.js} +1 -1
- package/ui-dist/assets/{blockDiagram-677ZJIJ3-e3ShzsXT.js → blockDiagram-677ZJIJ3-C0biHGAq.js} +1 -1
- package/ui-dist/assets/{c4Diagram-LMCZKHZV-Csd_18O2.js → c4Diagram-LMCZKHZV-u4oCpAvD.js} +1 -1
- package/ui-dist/assets/channel-B9BQAFDn.js +1 -0
- package/ui-dist/assets/{chunk-2Q5K7J3B-eF77FV1C.js → chunk-2Q5K7J3B-BvM44Y3G.js} +1 -1
- package/ui-dist/assets/{chunk-32BRIVSS-CpMx72B5.js → chunk-32BRIVSS-CQbfzkR_.js} +1 -1
- package/ui-dist/assets/{chunk-5VM5RSS4-Be6WylCu.js → chunk-5VM5RSS4-B33a1mNS.js} +1 -1
- package/ui-dist/assets/{chunk-EX3LRPZG-D-A_TfL-.js → chunk-EX3LRPZG-BdCiha3f.js} +1 -1
- package/ui-dist/assets/{chunk-JWPE2WC7-CdBLDqvo.js → chunk-JWPE2WC7-DTNMfMC9.js} +1 -1
- package/ui-dist/assets/{chunk-MOJQB5TN-DkLjRENV.js → chunk-MOJQB5TN-c0lOAGa1.js} +1 -1
- package/ui-dist/assets/{chunk-RYQCIY6F-57VqTsE9.js → chunk-RYQCIY6F-DS3dEwKK.js} +1 -1
- package/ui-dist/assets/{chunk-V7JOEXUC-DI_m8pt6.js → chunk-V7JOEXUC-4jQJFaAG.js} +1 -1
- package/ui-dist/assets/{chunk-VR4S4FIN-CM_944j4.js → chunk-VR4S4FIN-Cs5XNjhG.js} +1 -1
- package/ui-dist/assets/{chunk-XXDRQBXY--WTAlt82.js → chunk-XXDRQBXY-D7ngbc8f.js} +1 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-BKPnFl2Y.js +1 -0
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-BKPnFl2Y.js +1 -0
- package/ui-dist/assets/{cose-bilkent-JH36ORCC-CR0qu31s.js → cose-bilkent-JH36ORCC-1q6mmBp1.js} +1 -1
- package/ui-dist/assets/{cynefin-VYW2F7L2-f41lF5RD.js → cynefin-VYW2F7L2-t8yI99WT.js} +1 -1
- package/ui-dist/assets/{cynefinDiagram-TSTJHNR4-88wJ2LA8.js → cynefinDiagram-TSTJHNR4-BJF8z1ot.js} +1 -1
- package/ui-dist/assets/{dagre-VKFMJZFB-B1yJCIRh.js → dagre-VKFMJZFB-DBMtPdDi.js} +1 -1
- package/ui-dist/assets/{diagram-FQU43EPY-C0iYYFUe.js → diagram-FQU43EPY-BW1cV08t.js} +1 -1
- package/ui-dist/assets/{diagram-G47NLZAW-Cp6S0siK.js → diagram-G47NLZAW-DhwFKMkK.js} +1 -1
- package/ui-dist/assets/{diagram-NH7WQ7WH-CmZb5OSk.js → diagram-NH7WQ7WH-BbtnvhAE.js} +1 -1
- package/ui-dist/assets/{diagram-OA4YK3LP-9rFYGY7H.js → diagram-OA4YK3LP-BNUrV8Uf.js} +1 -1
- package/ui-dist/assets/{diagram-WEI45ONY-Og8vyDQh.js → diagram-WEI45ONY-DSHgjKh-.js} +1 -1
- package/ui-dist/assets/{ebnfDiagram-CCIWWBDH--5sMape2.js → ebnfDiagram-CCIWWBDH-BhvcX5k_.js} +1 -1
- package/ui-dist/assets/{erDiagram-Q63AITRT-DG10Bza-.js → erDiagram-Q63AITRT-BB5qlCUl.js} +1 -1
- package/ui-dist/assets/{flowDiagram-23GEKE2U-BW-aZfEk.js → flowDiagram-23GEKE2U-D52CQxkF.js} +1 -1
- package/ui-dist/assets/{ganttDiagram-NO4QXBWP-DcA7on8t.js → ganttDiagram-NO4QXBWP-BRJluXTY.js} +1 -1
- package/ui-dist/assets/{gitGraphDiagram-IHSO6WYX-ygGufg32.js → gitGraphDiagram-IHSO6WYX-Ci37w2rd.js} +1 -1
- package/ui-dist/assets/{graph-BXl6uBoM.js → graph-B3oLyKo8.js} +1 -1
- package/ui-dist/assets/{index-BM-SJNCx.js → index-BFfcvskP.js} +1 -1
- package/ui-dist/assets/{index-CssgLJwf.js → index-BQyVJzm5.js} +582 -543
- package/ui-dist/assets/{index-uKIvv9n9.js → index-BUYnNl4X.js} +1 -1
- package/ui-dist/assets/index-BaAPxkqh.css +1 -0
- package/ui-dist/assets/{index-DxXOCTVe.js → index-Bi8rkXAt.js} +1 -1
- package/ui-dist/assets/{index-DoiNhQrY.js → index-BtaMMtrx.js} +1 -1
- package/ui-dist/assets/{index-GdN-7KLt.js → index-CMHGH6Ig.js} +1 -1
- package/ui-dist/assets/{index-B58ems-F.js → index-CRvK1hVa.js} +1 -1
- package/ui-dist/assets/{index-DTlR8bJV.js → index-D3V5dOpZ.js} +1 -1
- package/ui-dist/assets/{index-9bXlV2sq.js → index-DGxgT-vs.js} +1 -1
- package/ui-dist/assets/{index-BmTNDbzy.js → index-DNRSLbBv.js} +1 -1
- package/ui-dist/assets/{index-CRLl2Ck7.js → index-Dm1qKNK3.js} +1 -1
- package/ui-dist/assets/{index-fkDP349f.js → index-KXhgZp0M.js} +1 -1
- package/ui-dist/assets/{index-Dl6nXXNc.js → index-aEV7UyJI.js} +1 -1
- package/ui-dist/assets/{index-ZA8lPH2n.js → index-gNfdxaL_.js} +1 -1
- package/ui-dist/assets/{index-Dug5GX1J.js → index-lFScKWNi.js} +1 -1
- package/ui-dist/assets/{index-CqmU1PxY.js → index-t5ekUQSC.js} +1 -1
- package/ui-dist/assets/{index-DOVMMhyj.js → index-u_Naonif.js} +1 -1
- package/ui-dist/assets/{index-CCDynlok.js → index-wLT_pklf.js} +1 -1
- package/ui-dist/assets/{infoDiagram-FWYZ7A6U-27INMkBm.js → infoDiagram-FWYZ7A6U-CiSa6UqO.js} +1 -1
- package/ui-dist/assets/{ishikawaDiagram-FXEZZL3T-Bp6XQ1_r.js → ishikawaDiagram-FXEZZL3T-BG8fdYii.js} +1 -1
- package/ui-dist/assets/{journeyDiagram-5HDEW3XC-9vaIwdZ3.js → journeyDiagram-5HDEW3XC-P0SmNi5K.js} +1 -1
- package/ui-dist/assets/{kanban-definition-HUTT4EX6-DjsMaR6l.js → kanban-definition-HUTT4EX6-bcBMmd2f.js} +1 -1
- package/ui-dist/assets/{layout-C0oWcIiC.js → layout-De1WFa12.js} +1 -1
- package/ui-dist/assets/{linear-DNbmenmQ.js → linear-DfawTapb.js} +1 -1
- package/ui-dist/assets/{map-B1s9kpcR.js → map-Cos50Fg1.js} +1 -1
- package/ui-dist/assets/{mermaid.core-DsYT9DxL.js → mermaid.core-CfATbZhh.js} +4 -4
- package/ui-dist/assets/{mindmap-definition-LN4V7U3C-vVHeRI83.js → mindmap-definition-LN4V7U3C-kkJ3RazO.js} +1 -1
- package/ui-dist/assets/{pegDiagram-2B236MQR-ohrgWLo_.js → pegDiagram-2B236MQR-xLFEe0pr.js} +1 -1
- package/ui-dist/assets/{pieDiagram-ENE6RG2P-B0EqPrjn.js → pieDiagram-ENE6RG2P-DRxKmqBN.js} +1 -1
- package/ui-dist/assets/{quadrantDiagram-ABIIQ3AL-D44iYm0o.js → quadrantDiagram-ABIIQ3AL-C3JX8tIm.js} +1 -1
- package/ui-dist/assets/{railroadDiagram-RFXS5EU6-BQU5bpbU.js → railroadDiagram-RFXS5EU6-Bnb7quMk.js} +1 -1
- package/ui-dist/assets/{requirementDiagram-TGXJPOKE-DGJciRxB.js → requirementDiagram-TGXJPOKE-CnKvG8M4.js} +1 -1
- package/ui-dist/assets/{sankeyDiagram-HTMAVEWB-NMXZW_Qb.js → sankeyDiagram-HTMAVEWB-B2v6M2b7.js} +1 -1
- package/ui-dist/assets/{sequenceDiagram-DBY2YBRQ-8uWY67Bb.js → sequenceDiagram-DBY2YBRQ-DHSuM1Sl.js} +1 -1
- package/ui-dist/assets/{sizeCapture-X5ZJPWSS-BnUUR-On.js → sizeCapture-X5ZJPWSS-DjACjUD7.js} +1 -1
- package/ui-dist/assets/{stateDiagram-2N3HPSRC-B37bcKMy.js → stateDiagram-2N3HPSRC-D-dQiH6y.js} +1 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-y22jWP_O.js +1 -0
- package/ui-dist/assets/{swimlanes-5IMT3BWC-Bi2ZzUMi.js → swimlanes-5IMT3BWC-LhFeuGXm.js} +2 -2
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-Gi07kkaw.js +8 -0
- package/ui-dist/assets/{timeline-definition-FHXFAJF6-CkWauU5D.js → timeline-definition-FHXFAJF6-CxHGii0e.js} +1 -1
- package/ui-dist/assets/{vennDiagram-L72KCM5P-BrmBXmnk.js → vennDiagram-L72KCM5P-vP83_x2-.js} +1 -1
- package/ui-dist/assets/{wardleyDiagram-EHGQE667-kO5cojc6.js → wardleyDiagram-EHGQE667-DWcdC5N6.js} +1 -1
- package/ui-dist/assets/{xychartDiagram-FW5EYKEG-CUBDaCDm.js → xychartDiagram-FW5EYKEG-wxi_332O.js} +1 -1
- package/ui-dist/index.html +2 -2
- package/ui-dist/assets/channel-BFLsBJOK.js +0 -1
- package/ui-dist/assets/classDiagram-OUVF2IWQ-Dah6C4Dl.js +0 -1
- package/ui-dist/assets/classDiagram-v2-EOCWNBFH-Dah6C4Dl.js +0 -1
- package/ui-dist/assets/index-BcdA9dZc.css +0 -1
- package/ui-dist/assets/stateDiagram-v2-6OUMAXLB-p6H0vL7N.js +0 -1
- package/ui-dist/assets/swimlanesDiagram-G3AALYLV-BX6FiLF9.js +0 -8
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Run the eval + improve loop until all pass or max iterations reached."""
|
|
3
|
+
|
|
4
|
+
from __future__ import annotations
|
|
5
|
+
|
|
6
|
+
import argparse
|
|
7
|
+
import json
|
|
8
|
+
import random
|
|
9
|
+
import sys
|
|
10
|
+
import tempfile
|
|
11
|
+
import time
|
|
12
|
+
import webbrowser
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
|
|
15
|
+
if __package__ in (None, ""):
|
|
16
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
17
|
+
|
|
18
|
+
from scripts.generate_report import generate_html
|
|
19
|
+
from scripts.improve_description import improve_description
|
|
20
|
+
from scripts.model_backends import detect_backend
|
|
21
|
+
from scripts.run_eval import find_project_root, run_eval
|
|
22
|
+
from scripts.utils import parse_skill_md
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def split_eval_set(eval_set: list[dict], holdout: float, seed: int = 42) -> tuple[list[dict], list[dict]]:
|
|
26
|
+
random.seed(seed)
|
|
27
|
+
trigger = [item for item in eval_set if item["should_trigger"]]
|
|
28
|
+
no_trigger = [item for item in eval_set if not item["should_trigger"]]
|
|
29
|
+
random.shuffle(trigger)
|
|
30
|
+
random.shuffle(no_trigger)
|
|
31
|
+
n_trigger_test = max(1, int(len(trigger) * holdout))
|
|
32
|
+
n_no_trigger_test = max(1, int(len(no_trigger) * holdout))
|
|
33
|
+
test_set = trigger[:n_trigger_test] + no_trigger[:n_no_trigger_test]
|
|
34
|
+
train_set = trigger[n_trigger_test:] + no_trigger[n_no_trigger_test:]
|
|
35
|
+
return train_set, test_set
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def run_loop(
|
|
39
|
+
*,
|
|
40
|
+
eval_set: list[dict],
|
|
41
|
+
skill_path: Path,
|
|
42
|
+
description_override: str | None,
|
|
43
|
+
num_workers: int,
|
|
44
|
+
timeout: int,
|
|
45
|
+
max_iterations: int,
|
|
46
|
+
runs_per_query: int,
|
|
47
|
+
trigger_threshold: float,
|
|
48
|
+
holdout: float,
|
|
49
|
+
model: str | None,
|
|
50
|
+
backend: str,
|
|
51
|
+
verbose: bool,
|
|
52
|
+
live_report_path: Path | None = None,
|
|
53
|
+
log_dir: Path | None = None,
|
|
54
|
+
) -> dict:
|
|
55
|
+
project_root = find_project_root()
|
|
56
|
+
name, original_description, content = parse_skill_md(skill_path)
|
|
57
|
+
current_description = description_override or original_description
|
|
58
|
+
backend = detect_backend(backend)
|
|
59
|
+
|
|
60
|
+
if holdout > 0:
|
|
61
|
+
train_set, test_set = split_eval_set(eval_set, holdout)
|
|
62
|
+
if verbose:
|
|
63
|
+
print(f"Split: {len(train_set)} train, {len(test_set)} test (holdout={holdout})", file=sys.stderr)
|
|
64
|
+
else:
|
|
65
|
+
train_set = eval_set
|
|
66
|
+
test_set = []
|
|
67
|
+
|
|
68
|
+
history = []
|
|
69
|
+
exit_reason = "unknown"
|
|
70
|
+
|
|
71
|
+
for iteration in range(1, max_iterations + 1):
|
|
72
|
+
if verbose:
|
|
73
|
+
print(f"\n{'=' * 60}", file=sys.stderr)
|
|
74
|
+
print(f"Iteration {iteration}/{max_iterations}", file=sys.stderr)
|
|
75
|
+
print(f"Backend: {backend}", file=sys.stderr)
|
|
76
|
+
print(f"Description: {current_description}", file=sys.stderr)
|
|
77
|
+
print(f"{'=' * 60}", file=sys.stderr)
|
|
78
|
+
|
|
79
|
+
all_queries = train_set + test_set
|
|
80
|
+
t0 = time.time()
|
|
81
|
+
all_results = run_eval(
|
|
82
|
+
eval_set=all_queries,
|
|
83
|
+
skill_name=name,
|
|
84
|
+
description=current_description,
|
|
85
|
+
num_workers=num_workers,
|
|
86
|
+
timeout=timeout,
|
|
87
|
+
project_root=project_root,
|
|
88
|
+
runs_per_query=runs_per_query,
|
|
89
|
+
trigger_threshold=trigger_threshold,
|
|
90
|
+
model=model,
|
|
91
|
+
backend=backend,
|
|
92
|
+
)
|
|
93
|
+
eval_elapsed = time.time() - t0
|
|
94
|
+
|
|
95
|
+
train_queries = {item["query"] for item in train_set}
|
|
96
|
+
train_result_list = [item for item in all_results["results"] if item["query"] in train_queries]
|
|
97
|
+
test_result_list = [item for item in all_results["results"] if item["query"] not in train_queries]
|
|
98
|
+
|
|
99
|
+
train_passed = sum(1 for item in train_result_list if item["pass"])
|
|
100
|
+
train_total = len(train_result_list)
|
|
101
|
+
train_summary = {"passed": train_passed, "failed": train_total - train_passed, "total": train_total}
|
|
102
|
+
train_results = {"results": train_result_list, "summary": train_summary}
|
|
103
|
+
|
|
104
|
+
if test_set:
|
|
105
|
+
test_passed = sum(1 for item in test_result_list if item["pass"])
|
|
106
|
+
test_total = len(test_result_list)
|
|
107
|
+
test_summary = {"passed": test_passed, "failed": test_total - test_passed, "total": test_total}
|
|
108
|
+
test_results = {"results": test_result_list, "summary": test_summary}
|
|
109
|
+
else:
|
|
110
|
+
test_summary = None
|
|
111
|
+
test_results = None
|
|
112
|
+
|
|
113
|
+
history.append({
|
|
114
|
+
"iteration": iteration,
|
|
115
|
+
"description": current_description,
|
|
116
|
+
"train_passed": train_summary["passed"],
|
|
117
|
+
"train_failed": train_summary["failed"],
|
|
118
|
+
"train_total": train_summary["total"],
|
|
119
|
+
"train_results": train_results["results"],
|
|
120
|
+
"test_passed": test_summary["passed"] if test_summary else None,
|
|
121
|
+
"test_failed": test_summary["failed"] if test_summary else None,
|
|
122
|
+
"test_total": test_summary["total"] if test_summary else None,
|
|
123
|
+
"test_results": test_results["results"] if test_results else None,
|
|
124
|
+
"passed": train_summary["passed"],
|
|
125
|
+
"failed": train_summary["failed"],
|
|
126
|
+
"total": train_summary["total"],
|
|
127
|
+
"results": train_results["results"],
|
|
128
|
+
})
|
|
129
|
+
|
|
130
|
+
if live_report_path:
|
|
131
|
+
partial_output = {
|
|
132
|
+
"backend": backend,
|
|
133
|
+
"original_description": original_description,
|
|
134
|
+
"best_description": current_description,
|
|
135
|
+
"best_score": "in progress",
|
|
136
|
+
"iterations_run": len(history),
|
|
137
|
+
"holdout": holdout,
|
|
138
|
+
"train_size": len(train_set),
|
|
139
|
+
"test_size": len(test_set),
|
|
140
|
+
"history": history,
|
|
141
|
+
}
|
|
142
|
+
live_report_path.write_text(generate_html(partial_output, auto_refresh=True, skill_name=name))
|
|
143
|
+
|
|
144
|
+
if verbose:
|
|
145
|
+
def print_eval_stats(label: str, results: list[dict], elapsed: float):
|
|
146
|
+
pos = [item for item in results if item["should_trigger"]]
|
|
147
|
+
neg = [item for item in results if not item["should_trigger"]]
|
|
148
|
+
tp = sum(item["triggers"] for item in pos)
|
|
149
|
+
pos_runs = sum(item["runs"] for item in pos)
|
|
150
|
+
fn = pos_runs - tp
|
|
151
|
+
fp = sum(item["triggers"] for item in neg)
|
|
152
|
+
neg_runs = sum(item["runs"] for item in neg)
|
|
153
|
+
tn = neg_runs - fp
|
|
154
|
+
total = tp + tn + fp + fn
|
|
155
|
+
precision = tp / (tp + fp) if (tp + fp) > 0 else 1.0
|
|
156
|
+
recall = tp / (tp + fn) if (tp + fn) > 0 else 1.0
|
|
157
|
+
accuracy = (tp + tn) / total if total > 0 else 0.0
|
|
158
|
+
print(
|
|
159
|
+
f"{label}: {tp + tn}/{total} correct, precision={precision:.0%} "
|
|
160
|
+
f"recall={recall:.0%} accuracy={accuracy:.0%} ({elapsed:.1f}s)",
|
|
161
|
+
file=sys.stderr,
|
|
162
|
+
)
|
|
163
|
+
for item in results:
|
|
164
|
+
status = "PASS" if item["pass"] else "FAIL"
|
|
165
|
+
rate_str = f"{item['triggers']}/{item['runs']}"
|
|
166
|
+
print(f" [{status}] rate={rate_str} expected={item['should_trigger']}: {item['query'][:60]}", file=sys.stderr)
|
|
167
|
+
|
|
168
|
+
print_eval_stats("Train", train_results["results"], eval_elapsed)
|
|
169
|
+
if test_summary:
|
|
170
|
+
print_eval_stats("Test ", test_results["results"], 0)
|
|
171
|
+
|
|
172
|
+
if train_summary["failed"] == 0:
|
|
173
|
+
exit_reason = f"all_passed (iteration {iteration})"
|
|
174
|
+
if verbose:
|
|
175
|
+
print(f"\nAll train queries passed on iteration {iteration}.", file=sys.stderr)
|
|
176
|
+
break
|
|
177
|
+
|
|
178
|
+
if iteration == max_iterations:
|
|
179
|
+
exit_reason = f"max_iterations ({max_iterations})"
|
|
180
|
+
if verbose:
|
|
181
|
+
print(f"\nMax iterations reached ({max_iterations}).", file=sys.stderr)
|
|
182
|
+
break
|
|
183
|
+
|
|
184
|
+
if verbose:
|
|
185
|
+
print("\nImproving description...", file=sys.stderr)
|
|
186
|
+
|
|
187
|
+
t0 = time.time()
|
|
188
|
+
blinded_history = [
|
|
189
|
+
{k: v for k, v in item.items() if not k.startswith("test_")}
|
|
190
|
+
for item in history
|
|
191
|
+
]
|
|
192
|
+
new_description = improve_description(
|
|
193
|
+
backend=backend,
|
|
194
|
+
skill_name=name,
|
|
195
|
+
skill_content=content,
|
|
196
|
+
current_description=current_description,
|
|
197
|
+
eval_results=train_results,
|
|
198
|
+
history=blinded_history,
|
|
199
|
+
model=model,
|
|
200
|
+
log_dir=log_dir,
|
|
201
|
+
iteration=iteration,
|
|
202
|
+
)
|
|
203
|
+
improve_elapsed = time.time() - t0
|
|
204
|
+
|
|
205
|
+
if verbose:
|
|
206
|
+
print(f"Proposed ({improve_elapsed:.1f}s): {new_description}", file=sys.stderr)
|
|
207
|
+
|
|
208
|
+
current_description = new_description
|
|
209
|
+
|
|
210
|
+
if test_set:
|
|
211
|
+
best = max(history, key=lambda item: item["test_passed"] or 0)
|
|
212
|
+
best_score = f"{best['test_passed']}/{best['test_total']}"
|
|
213
|
+
else:
|
|
214
|
+
best = max(history, key=lambda item: item["train_passed"])
|
|
215
|
+
best_score = f"{best['train_passed']}/{best['train_total']}"
|
|
216
|
+
|
|
217
|
+
if verbose:
|
|
218
|
+
print(f"\nExit reason: {exit_reason}", file=sys.stderr)
|
|
219
|
+
print(f"Best score: {best_score} (iteration {best['iteration']})", file=sys.stderr)
|
|
220
|
+
|
|
221
|
+
return {
|
|
222
|
+
"backend": backend,
|
|
223
|
+
"exit_reason": exit_reason,
|
|
224
|
+
"original_description": original_description,
|
|
225
|
+
"best_description": best["description"],
|
|
226
|
+
"best_score": best_score,
|
|
227
|
+
"best_train_score": f"{best['train_passed']}/{best['train_total']}",
|
|
228
|
+
"best_test_score": f"{best['test_passed']}/{best['test_total']}" if test_set else None,
|
|
229
|
+
"final_description": current_description,
|
|
230
|
+
"iterations_run": len(history),
|
|
231
|
+
"holdout": holdout,
|
|
232
|
+
"train_size": len(train_set),
|
|
233
|
+
"test_size": len(test_set),
|
|
234
|
+
"history": history,
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def main():
|
|
239
|
+
parser = argparse.ArgumentParser(description="Run eval + improve loop")
|
|
240
|
+
parser.add_argument("--eval-set", required=True, help="Path to eval set JSON file")
|
|
241
|
+
parser.add_argument("--skill-path", required=True, help="Path to skill directory")
|
|
242
|
+
parser.add_argument("--description", default=None, help="Override starting description")
|
|
243
|
+
parser.add_argument("--num-workers", type=int, default=10, help="Number of parallel workers")
|
|
244
|
+
parser.add_argument("--timeout", type=int, default=60, help="Timeout per query in seconds")
|
|
245
|
+
parser.add_argument("--max-iterations", type=int, default=5, help="Max improvement iterations")
|
|
246
|
+
parser.add_argument("--runs-per-query", type=int, default=3, help="Number of runs per query")
|
|
247
|
+
parser.add_argument("--trigger-threshold", type=float, default=0.5, help="Trigger rate threshold")
|
|
248
|
+
parser.add_argument("--holdout", type=float, default=0.4, help="Fraction of eval set to hold out for testing (0 to disable)")
|
|
249
|
+
parser.add_argument("--model", default=None, help="Optional backend model identifier")
|
|
250
|
+
parser.add_argument("--backend", default="auto", choices=["auto", "claude", "codex"], help="Optimization backend")
|
|
251
|
+
parser.add_argument("--verbose", action="store_true", help="Print progress to stderr")
|
|
252
|
+
parser.add_argument("--report", default="auto", help="Generate HTML report at this path (default: 'auto', 'none' to disable)")
|
|
253
|
+
parser.add_argument("--results-dir", default=None, help="Save outputs to a timestamped subdirectory here")
|
|
254
|
+
args = parser.parse_args()
|
|
255
|
+
|
|
256
|
+
eval_set = json.loads(Path(args.eval_set).read_text())
|
|
257
|
+
skill_path = Path(args.skill_path)
|
|
258
|
+
|
|
259
|
+
if not (skill_path / "SKILL.md").exists():
|
|
260
|
+
print(f"Error: No SKILL.md found at {skill_path}", file=sys.stderr)
|
|
261
|
+
sys.exit(1)
|
|
262
|
+
|
|
263
|
+
name, _, _ = parse_skill_md(skill_path)
|
|
264
|
+
|
|
265
|
+
if args.report != "none":
|
|
266
|
+
if args.report == "auto":
|
|
267
|
+
timestamp = time.strftime("%Y%m%d_%H%M%S")
|
|
268
|
+
live_report_path = Path(tempfile.gettempdir()) / f"skill_description_report_{skill_path.name}_{timestamp}.html"
|
|
269
|
+
else:
|
|
270
|
+
live_report_path = Path(args.report)
|
|
271
|
+
live_report_path.write_text("<html><body><h1>Starting optimization loop...</h1><meta http-equiv='refresh' content='5'></body></html>")
|
|
272
|
+
webbrowser.open(str(live_report_path))
|
|
273
|
+
else:
|
|
274
|
+
live_report_path = None
|
|
275
|
+
|
|
276
|
+
if args.results_dir:
|
|
277
|
+
timestamp = time.strftime("%Y-%m-%d_%H%M%S")
|
|
278
|
+
results_dir = Path(args.results_dir) / timestamp
|
|
279
|
+
results_dir.mkdir(parents=True, exist_ok=True)
|
|
280
|
+
else:
|
|
281
|
+
results_dir = None
|
|
282
|
+
|
|
283
|
+
log_dir = results_dir / "logs" if results_dir else None
|
|
284
|
+
|
|
285
|
+
output = run_loop(
|
|
286
|
+
eval_set=eval_set,
|
|
287
|
+
skill_path=skill_path,
|
|
288
|
+
description_override=args.description,
|
|
289
|
+
num_workers=args.num_workers,
|
|
290
|
+
timeout=args.timeout,
|
|
291
|
+
max_iterations=args.max_iterations,
|
|
292
|
+
runs_per_query=args.runs_per_query,
|
|
293
|
+
trigger_threshold=args.trigger_threshold,
|
|
294
|
+
holdout=args.holdout,
|
|
295
|
+
model=args.model,
|
|
296
|
+
backend=args.backend,
|
|
297
|
+
verbose=args.verbose,
|
|
298
|
+
live_report_path=live_report_path,
|
|
299
|
+
log_dir=log_dir,
|
|
300
|
+
)
|
|
301
|
+
|
|
302
|
+
json_output = json.dumps(output, indent=2)
|
|
303
|
+
print(json_output)
|
|
304
|
+
if results_dir:
|
|
305
|
+
(results_dir / "results.json").write_text(json_output)
|
|
306
|
+
|
|
307
|
+
if live_report_path:
|
|
308
|
+
live_report_path.write_text(generate_html(output, auto_refresh=False, skill_name=name))
|
|
309
|
+
print(f"\nReport: {live_report_path}", file=sys.stderr)
|
|
310
|
+
|
|
311
|
+
if results_dir and live_report_path:
|
|
312
|
+
(results_dir / "report.html").write_text(generate_html(output, auto_refresh=False, skill_name=name))
|
|
313
|
+
|
|
314
|
+
if results_dir:
|
|
315
|
+
print(f"Results saved to: {results_dir}", file=sys.stderr)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
if __name__ == "__main__":
|
|
319
|
+
main()
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
"""Shared utilities for skill-creator scripts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
FRONTMATTER_PATTERN = re.compile(r"^---\s*\n(.*?)\n---\s*(?:\n|$)", re.DOTALL)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def extract_frontmatter_text(content: str) -> str:
|
|
13
|
+
"""Return the raw YAML frontmatter text from a SKILL.md file."""
|
|
14
|
+
match = FRONTMATTER_PATTERN.match(content)
|
|
15
|
+
if not match:
|
|
16
|
+
raise ValueError("SKILL.md missing frontmatter (expected opening and closing ---)")
|
|
17
|
+
return match.group(1)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _count_indent(line: str) -> int:
|
|
21
|
+
return len(line) - len(line.lstrip(" "))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _parse_scalar(value: str):
|
|
25
|
+
value = value.strip()
|
|
26
|
+
if not value:
|
|
27
|
+
return ""
|
|
28
|
+
|
|
29
|
+
if value[0] == value[-1] and value[0] in {'"', "'"}:
|
|
30
|
+
return value[1:-1]
|
|
31
|
+
|
|
32
|
+
lowered = value.lower()
|
|
33
|
+
if lowered in {"true", "false"}:
|
|
34
|
+
return lowered == "true"
|
|
35
|
+
if lowered in {"null", "~"}:
|
|
36
|
+
return None
|
|
37
|
+
|
|
38
|
+
if re.fullmatch(r"-?\d+", value):
|
|
39
|
+
return int(value)
|
|
40
|
+
if re.fullmatch(r"-?\d+\.\d+", value):
|
|
41
|
+
return float(value)
|
|
42
|
+
|
|
43
|
+
if value.startswith("[") and value.endswith("]"):
|
|
44
|
+
inner = value[1:-1].strip()
|
|
45
|
+
if not inner:
|
|
46
|
+
return []
|
|
47
|
+
return [_parse_scalar(part.strip()) for part in inner.split(",")]
|
|
48
|
+
|
|
49
|
+
return value
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _fold_lines(lines: list[str]) -> str:
|
|
53
|
+
paragraphs: list[list[str]] = [[]]
|
|
54
|
+
for line in lines:
|
|
55
|
+
if line == "":
|
|
56
|
+
if paragraphs[-1]:
|
|
57
|
+
paragraphs.append([])
|
|
58
|
+
continue
|
|
59
|
+
paragraphs[-1].append(line)
|
|
60
|
+
|
|
61
|
+
folded = [" ".join(paragraph).strip() for paragraph in paragraphs if paragraph]
|
|
62
|
+
return "\n\n".join(part for part in folded if part)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _parse_block_scalar(lines: list[str], start: int, indent: int, style: str):
|
|
66
|
+
collected: list[str] = []
|
|
67
|
+
index = start
|
|
68
|
+
while index < len(lines):
|
|
69
|
+
raw = lines[index]
|
|
70
|
+
if not raw.strip():
|
|
71
|
+
collected.append("")
|
|
72
|
+
index += 1
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
current_indent = _count_indent(raw)
|
|
76
|
+
if current_indent < indent:
|
|
77
|
+
break
|
|
78
|
+
collected.append(raw[indent:])
|
|
79
|
+
index += 1
|
|
80
|
+
|
|
81
|
+
if style.startswith("|"):
|
|
82
|
+
value = "\n".join(collected)
|
|
83
|
+
else:
|
|
84
|
+
value = _fold_lines(collected)
|
|
85
|
+
return value, index
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _looks_like_mapping_entry(text: str) -> bool:
|
|
89
|
+
if text.startswith("- "):
|
|
90
|
+
return False
|
|
91
|
+
return bool(re.match(r"^[A-Za-z0-9_-]+:\s*.*$", text))
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _next_nonempty_index(lines: list[str], start: int, min_indent: int):
|
|
95
|
+
index = start
|
|
96
|
+
while index < len(lines):
|
|
97
|
+
raw = lines[index]
|
|
98
|
+
if not raw.strip():
|
|
99
|
+
index += 1
|
|
100
|
+
continue
|
|
101
|
+
indent = _count_indent(raw)
|
|
102
|
+
if indent < min_indent:
|
|
103
|
+
return None
|
|
104
|
+
return index
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _parse_list(lines: list[str], start: int, indent: int):
|
|
109
|
+
items = []
|
|
110
|
+
index = start
|
|
111
|
+
while index < len(lines):
|
|
112
|
+
raw = lines[index]
|
|
113
|
+
if not raw.strip():
|
|
114
|
+
index += 1
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
current_indent = _count_indent(raw)
|
|
118
|
+
if current_indent < indent:
|
|
119
|
+
break
|
|
120
|
+
if current_indent != indent or not raw[indent:].startswith("- "):
|
|
121
|
+
raise ValueError(f"Invalid list entry near line: {raw}")
|
|
122
|
+
|
|
123
|
+
remainder = raw[indent + 2 :].strip()
|
|
124
|
+
index += 1
|
|
125
|
+
|
|
126
|
+
if remainder:
|
|
127
|
+
items.append(_parse_scalar(remainder))
|
|
128
|
+
continue
|
|
129
|
+
|
|
130
|
+
next_index = _next_nonempty_index(lines, index, indent + 2)
|
|
131
|
+
if next_index is None:
|
|
132
|
+
items.append("")
|
|
133
|
+
continue
|
|
134
|
+
|
|
135
|
+
nested_indent = _count_indent(lines[next_index])
|
|
136
|
+
nested_text = lines[next_index][nested_indent:]
|
|
137
|
+
if nested_text.startswith("- "):
|
|
138
|
+
value, index = _parse_list(lines, next_index, nested_indent)
|
|
139
|
+
elif _looks_like_mapping_entry(nested_text):
|
|
140
|
+
value, index = _parse_mapping(lines, next_index, nested_indent)
|
|
141
|
+
else:
|
|
142
|
+
value, index = _parse_block_scalar(lines, next_index, nested_indent, ">")
|
|
143
|
+
items.append(value)
|
|
144
|
+
|
|
145
|
+
return items, index
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def _parse_mapping(lines: list[str], start: int, indent: int):
|
|
149
|
+
mapping = {}
|
|
150
|
+
index = start
|
|
151
|
+
|
|
152
|
+
while index < len(lines):
|
|
153
|
+
raw = lines[index]
|
|
154
|
+
if not raw.strip():
|
|
155
|
+
index += 1
|
|
156
|
+
continue
|
|
157
|
+
|
|
158
|
+
current_indent = _count_indent(raw)
|
|
159
|
+
if current_indent < indent:
|
|
160
|
+
break
|
|
161
|
+
if current_indent != indent:
|
|
162
|
+
raise ValueError(f"Unexpected indentation near line: {raw}")
|
|
163
|
+
|
|
164
|
+
text = raw[indent:]
|
|
165
|
+
if text.startswith("- "):
|
|
166
|
+
raise ValueError(f"Unexpected list item near line: {raw}")
|
|
167
|
+
if ":" not in text:
|
|
168
|
+
raise ValueError(f"Invalid mapping entry near line: {raw}")
|
|
169
|
+
|
|
170
|
+
key, remainder = text.split(":", 1)
|
|
171
|
+
key = key.strip()
|
|
172
|
+
remainder = remainder.strip()
|
|
173
|
+
index += 1
|
|
174
|
+
|
|
175
|
+
if remainder in {"|", ">", "|-", ">-"}:
|
|
176
|
+
value, index = _parse_block_scalar(lines, index, indent + 2, remainder)
|
|
177
|
+
elif remainder:
|
|
178
|
+
value = _parse_scalar(remainder)
|
|
179
|
+
else:
|
|
180
|
+
next_index = _next_nonempty_index(lines, index, indent + 2)
|
|
181
|
+
if next_index is None:
|
|
182
|
+
value = ""
|
|
183
|
+
else:
|
|
184
|
+
nested_indent = _count_indent(lines[next_index])
|
|
185
|
+
nested_text = lines[next_index][nested_indent:]
|
|
186
|
+
if nested_text.startswith("- "):
|
|
187
|
+
value, index = _parse_list(lines, next_index, nested_indent)
|
|
188
|
+
elif _looks_like_mapping_entry(nested_text):
|
|
189
|
+
value, index = _parse_mapping(lines, next_index, nested_indent)
|
|
190
|
+
else:
|
|
191
|
+
value, index = _parse_block_scalar(lines, next_index, nested_indent, ">")
|
|
192
|
+
mapping[key] = value
|
|
193
|
+
|
|
194
|
+
return mapping, index
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def parse_frontmatter(frontmatter_text: str) -> dict:
|
|
198
|
+
"""Parse a small YAML subset used by SKILL.md frontmatter without PyYAML."""
|
|
199
|
+
lines = frontmatter_text.splitlines()
|
|
200
|
+
mapping, index = _parse_mapping(lines, 0, 0)
|
|
201
|
+
|
|
202
|
+
trailing = [line for line in lines[index:] if line.strip()]
|
|
203
|
+
if trailing:
|
|
204
|
+
raise ValueError(f"Unexpected trailing content in frontmatter: {trailing[0]}")
|
|
205
|
+
return mapping
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def load_skill_frontmatter(skill_path: Path) -> tuple[dict, str]:
|
|
209
|
+
"""Load and parse the frontmatter from a skill directory."""
|
|
210
|
+
content = (skill_path / "SKILL.md").read_text()
|
|
211
|
+
frontmatter_text = extract_frontmatter_text(content)
|
|
212
|
+
frontmatter = parse_frontmatter(frontmatter_text)
|
|
213
|
+
if not isinstance(frontmatter, dict):
|
|
214
|
+
raise ValueError("Frontmatter must be a mapping")
|
|
215
|
+
return frontmatter, content
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def parse_skill_md(skill_path: Path) -> tuple[str, str, str]:
|
|
219
|
+
"""Parse a SKILL.md file, returning (name, description, full_content)."""
|
|
220
|
+
frontmatter, content = load_skill_frontmatter(skill_path)
|
|
221
|
+
name = frontmatter.get("name", "")
|
|
222
|
+
description = frontmatter.get("description", "")
|
|
223
|
+
return str(name or ""), str(description or ""), content
|
package/ui-dist/assets/{abnfDiagram-VRR7QNED-CAAPm9Nj.js → abnfDiagram-VRR7QNED-DLc7ClAF.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-c0lOAGa1.js";import{p as f}from"./chunk-JWPE2WC7-DTNMfMC9.js";import{_ as n,l as o}from"./mermaid.core-CfATbZhh.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-t8yI99WT.js";import"./index-BQyVJzm5.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{G as ln,H as un,I as N,J as I,K as J,L as an,M as y,N as tn,O as j,P as _,Q as rn,R as o,S as on,T as sn,V as fn}from"./mermaid.core-
|
|
1
|
+
import{G as ln,H as un,I as N,J as I,K as J,L as an,M as y,N as tn,O as j,P as _,Q as rn,R as o,S as on,T as sn,V as fn}from"./mermaid.core-CfATbZhh.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,q,O,v,R,K,u){var D=q-l,i=O-h,n=K-v,d=u-R,a=d*D-n*i;if(!(a*a<y))return a=(n*(h-R)-d*(l-v))/a,[l+a*D,h+a*i]}function W(l,h,q,O,v,R,K){var u=l-q,D=h-O,i=(K?R:-R)/j(u*u+D*D),n=i*D,d=-i*u,a=l+n,s=h+d,f=q+n,c=O+d,L=(a+f)/2,t=(s+c)/2,m=f-a,g=c-s,A=m*m+g*g,T=v-R,P=a*c-f*s,E=(g<0?-1:1)*j(on(0,T*T*A-P*P)),G=(P*g-m*E)/A,H=(-P*m-g*E)/A,w=(P*g+m*E)/A,p=(-P*m+g*E)/A,x=G-L,e=H-t,r=w-L,M=p-t;return x*x+e*e>r*r+M*M&&(G=w,H=p),{cx:G,cy:H,x01:-n,y01:-d,x11:G*(v/T-1),y11:H*(v/T-1)}}function hn(){var l=cn,h=yn,q=J(0),O=null,v=gn,R=dn,K=mn,u=null,D=ln(i);function i(){var n,d,a=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-an,c=R.apply(this,arguments)-an,L=rn(c-f),t=c>f;if(u||(u=n=D()),s<a&&(d=s,s=a,a=d),!(s>y))u.moveTo(0,0);else if(L>tn-y)u.moveTo(s*N(f),s*I(f)),u.arc(0,0,s,f,c,!t),a>y&&(u.moveTo(a*N(c),a*I(c)),u.arc(0,0,a,c,f,t));else{var m=f,g=c,A=f,T=c,P=L,E=L,G=K.apply(this,arguments)/2,H=G>y&&(O?+O.apply(this,arguments):j(a*a+s*s)),w=_(rn(s-a)/2,+q.apply(this,arguments)),p=w,x=w,e,r;if(H>y){var M=sn(H/a*I(G)),z=sn(H/s*I(G));(P-=M*2)>y?(M*=t?1:-1,A+=M,T-=M):(P=0,A=T=(f+c)/2),(E-=z*2)>y?(z*=t?1:-1,m+=z,g-=z):(E=0,m=g=(f+c)/2)}var Q=s*N(m),V=s*I(m),B=a*N(T),C=a*I(T);if(w>y){var F=s*N(g),U=s*I(g),X=a*N(A),Y=a*I(A),S;if(L<un)if(S=pn(Q,V,X,Y,F,U,B,C)){var Z=Q-S[0],$=V-S[1],k=F-S[0],b=U-S[1],nn=1/I(fn((Z*k+$*b)/(j(Z*Z+$*$)*j(k*k+b*b)))/2),en=j(S[0]*S[0]+S[1]*S[1]);p=_(w,(a-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}E>y?x>y?(e=W(X,Y,Q,V,s,x,t),r=W(F,U,B,C,s,x,t),u.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?u.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(u.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),u.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),u.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(u.moveTo(Q,V),u.arc(0,0,s,m,g,!t)):u.moveTo(Q,V),!(a>y)||!(P>y)?u.lineTo(B,C):p>y?(e=W(B,C,F,U,a,-p,t),r=W(Q,V,X,Y,a,-p,t),u.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?u.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(u.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),u.arc(0,0,a,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),u.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):u.arc(0,0,a,T,A,t)}if(u.closePath(),n)return u=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +R.apply(this,arguments))/2-un/2;return[N(d)*n,I(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:J(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:J(+n),i):h},i.cornerRadius=function(n){return arguments.length?(q=typeof n=="function"?n:J(+n),i):q},i.padRadius=function(n){return arguments.length?(O=n==null?null:typeof n=="function"?n:J(+n),i):O},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:J(+n),i):v},i.endAngle=function(n){return arguments.length?(R=typeof n=="function"?n:J(+n),i):R},i.padAngle=function(n){return arguments.length?(K=typeof n=="function"?n:J(+n),i):K},i.context=function(n){return arguments.length?(u=n??null,i):u},i}export{hn as d};
|