create-workframe 0.1.4 → 0.1.5
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/README.md +1 -1
- package/package.json +1 -1
- package/workframe-api/package.json +1 -1
- package/workframe-api/server.py +112 -20
- package/workframe-api/test_billing_provider.py +24 -0
- package/workframe-ui/public/assets/{arc-BskqxLmE.js → arc-CnriPN3G.js} +1 -1
- package/workframe-ui/public/assets/architecture-7EHR7CIX-CFhr7xAe.js +1 -0
- package/workframe-ui/public/assets/{architectureDiagram-3BPJPVTR-B3eGdqvq.js → architectureDiagram-3BPJPVTR-DYYB1Ic2.js} +1 -1
- package/workframe-ui/public/assets/{blockDiagram-GPEHLZMM-CzFZG7uX.js → blockDiagram-GPEHLZMM-Bn-fFOyj.js} +1 -1
- package/workframe-ui/public/assets/{c4Diagram-AAUBKEIU-BS-gGyCH.js → c4Diagram-AAUBKEIU-BPPDtAnD.js} +1 -1
- package/workframe-ui/public/assets/channel-Dok_-T0o.js +1 -0
- package/workframe-ui/public/assets/{chunk-2J33WTMH-Cjvqf7c9.js → chunk-2J33WTMH-Bz2CJiC3.js} +1 -1
- package/workframe-ui/public/assets/{chunk-3OPIFGDE--eUuL8AK.js → chunk-3OPIFGDE-B8aMeE1B.js} +1 -1
- package/workframe-ui/public/assets/{chunk-4BX2VUAB-s9lHUFKL.js → chunk-4BX2VUAB-bLFHQTuT.js} +1 -1
- package/workframe-ui/public/assets/{chunk-55IACEB6-D1McA5nz.js → chunk-55IACEB6-BRxhx-lG.js} +1 -1
- package/workframe-ui/public/assets/{chunk-5ZQYHXKU-DIstLfU2.js → chunk-5ZQYHXKU-BLyOgEJ8.js} +1 -1
- package/workframe-ui/public/assets/{chunk-727SXJPM-Cd0GD2CO.js → chunk-727SXJPM-DiuvBl7G.js} +1 -1
- package/workframe-ui/public/assets/{chunk-AQP2D5EJ-gc5Ra6G4.js → chunk-AQP2D5EJ-BE1_aBdC.js} +1 -1
- package/workframe-ui/public/assets/{chunk-BSJP7CBP-Cg5QfihJ.js → chunk-BSJP7CBP-BicGsmBs.js} +1 -1
- package/workframe-ui/public/assets/{chunk-CSCIHK7Q-D_gobbhY.js → chunk-CSCIHK7Q-C3VTns3d.js} +1 -1
- package/workframe-ui/public/assets/{chunk-FMBD7UC4-B6eLY9_d.js → chunk-FMBD7UC4-DSiXY3bY.js} +1 -1
- package/workframe-ui/public/assets/{chunk-KSCS5N6A-BGroAeW2.js → chunk-KSCS5N6A-Cvw5s3fR.js} +1 -1
- package/workframe-ui/public/assets/{chunk-L5ZTLDWV-34xv7WgT.js → chunk-L5ZTLDWV-jJifGdIQ.js} +1 -1
- package/workframe-ui/public/assets/{chunk-LZXEDZCA-XJBctFZw.js → chunk-LZXEDZCA-Maee1aqo.js} +2 -2
- package/workframe-ui/public/assets/{chunk-ND2GUHAM-nTOZpln8.js → chunk-ND2GUHAM-C77N3VAM.js} +1 -1
- package/workframe-ui/public/assets/{chunk-NZK2D7GU-BBrzcaPH.js → chunk-NZK2D7GU-BY68lrPB.js} +1 -1
- package/workframe-ui/public/assets/{chunk-O5CBEL6O-Cntncx6L.js → chunk-O5CBEL6O-D_c4kWzh.js} +1 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-C3wwLrTa.js +1 -0
- package/workframe-ui/public/assets/chunk-WU5MYG2G-GFFSg2kf.js +1 -0
- package/workframe-ui/public/assets/{chunk-XPW4576I-DSbtd0cg.js → chunk-XPW4576I-DlQgvqBp.js} +1 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-DKbGfT5Z.js +1 -0
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-DKbGfT5Z.js +1 -0
- package/workframe-ui/public/assets/{cose-bilkent-S5V4N54A-lmYstEMQ.js → cose-bilkent-S5V4N54A-CHCOHDSd.js} +1 -1
- package/workframe-ui/public/assets/{dagre-BM42HDAG-Bdkbdul2.js → dagre-BM42HDAG-CKPcSYwU.js} +1 -1
- package/workframe-ui/public/assets/{diagram-2AECGRRQ-Clb9kSXe.js → diagram-2AECGRRQ-C6qe0jP-.js} +1 -1
- package/workframe-ui/public/assets/{diagram-5GNKFQAL-BApg0yec.js → diagram-5GNKFQAL-DhQhrieU.js} +1 -1
- package/workframe-ui/public/assets/{diagram-KO2AKTUF-peZjDRV6.js → diagram-KO2AKTUF-Bqf6Iw1r.js} +1 -1
- package/workframe-ui/public/assets/{diagram-LMA3HP47-DZm_1pjc.js → diagram-LMA3HP47-Bt1ms2D2.js} +1 -1
- package/workframe-ui/public/assets/{diagram-OG6HWLK6-DP_N6fYL.js → diagram-OG6HWLK6-C0Rrxe1i.js} +1 -1
- package/workframe-ui/public/assets/{dist-CqP43hXK.js → dist-BLcLhTn6.js} +1 -1
- package/workframe-ui/public/assets/{erDiagram-TEJ5UH35-Blfs6kLv.js → erDiagram-TEJ5UH35-Cy1GbZVu.js} +1 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-C_PrceHe.js +1 -0
- package/workframe-ui/public/assets/{flowDiagram-I6XJVG4X-CcmMOkwH.js → flowDiagram-I6XJVG4X-DL3ALqDG.js} +1 -1
- package/workframe-ui/public/assets/{ganttDiagram-6RSMTGT7-ByoO3dF7.js → ganttDiagram-6RSMTGT7-CMpwBhXQ.js} +1 -1
- package/workframe-ui/public/assets/{gitGraph-WXDBUCRP-DCyTpmPs.js → gitGraph-WXDBUCRP-C0mwHUXL.js} +1 -1
- package/workframe-ui/public/assets/{gitGraphDiagram-PVQCEYII-CvLYB55b.js → gitGraphDiagram-PVQCEYII-6gzhWaF0.js} +1 -1
- package/workframe-ui/public/assets/{index-DpoUZAxh.css → index-DyO6K0TD.css} +1 -1
- package/workframe-ui/public/assets/index-yvpSUs8T.js +133 -0
- package/workframe-ui/public/assets/{info-J43DQDTF-CfSRIfOI.js → info-J43DQDTF-Bb_wZTxU.js} +1 -1
- package/workframe-ui/public/assets/{infoDiagram-5YYISTIA-DwS44DS6.js → infoDiagram-5YYISTIA-601evYFV.js} +1 -1
- package/workframe-ui/public/assets/{ishikawaDiagram-YF4QCWOH-MRlyodyU.js → ishikawaDiagram-YF4QCWOH-BYtF-wHm.js} +1 -1
- package/workframe-ui/public/assets/{journeyDiagram-JHISSGLW-sq7awk87.js → journeyDiagram-JHISSGLW-BMizyHzC.js} +1 -1
- package/workframe-ui/public/assets/{kanban-definition-UN3LZRKU-CH6HbcWu.js → kanban-definition-UN3LZRKU-CLLJsdnh.js} +1 -1
- package/workframe-ui/public/assets/{line-DRBjFmUW.js → line-BFiSvu-q.js} +1 -1
- package/workframe-ui/public/assets/{linear-BR0LunjE.js → linear-D6HYZ18_.js} +1 -1
- package/workframe-ui/public/assets/{mermaid-parser.core-Cl1GjHkT.js → mermaid-parser.core-Cid5yDBQ.js} +2 -2
- package/workframe-ui/public/assets/{mermaid.core-DsiKK1kE.js → mermaid.core-DqIiju5Z.js} +3 -3
- package/workframe-ui/public/assets/{mindmap-definition-RKZ34NQL-DBvi3OpW.js → mindmap-definition-RKZ34NQL-Bg7xJdsz.js} +1 -1
- package/workframe-ui/public/assets/{packet-YPE3B663-CPDgtUHg.js → packet-YPE3B663-1ebGt86D.js} +1 -1
- package/workframe-ui/public/assets/{pie-LRSECV5Y-BXJIPPDm.js → pie-LRSECV5Y-DJ9wOBC_.js} +1 -1
- package/workframe-ui/public/assets/{pieDiagram-4H26LBE5-CZwLEK-o.js → pieDiagram-4H26LBE5-BmK96Aus.js} +1 -1
- package/workframe-ui/public/assets/{quadrantDiagram-W4KKPZXB-B65bEUIQ.js → quadrantDiagram-W4KKPZXB-ByUqtWPZ.js} +1 -1
- package/workframe-ui/public/assets/{radar-GUYGQ44K-vXHkZzRK.js → radar-GUYGQ44K-DN-Hkt96.js} +1 -1
- package/workframe-ui/public/assets/{requirementDiagram-4Y6WPE33-BGWdvDfG.js → requirementDiagram-4Y6WPE33-ByU2r8gb.js} +1 -1
- package/workframe-ui/public/assets/{sankeyDiagram-5OEKKPKP-BT2oC8dV.js → sankeyDiagram-5OEKKPKP-elyWa0GK.js} +1 -1
- package/workframe-ui/public/assets/{sequenceDiagram-3UESZ5HK-45yj0Wtx.js → sequenceDiagram-3UESZ5HK-CzZwsAiK.js} +1 -1
- package/workframe-ui/public/assets/{src-D-P8U2PB.js → src-5vgsM_dl.js} +1 -1
- package/workframe-ui/public/assets/{stateDiagram-AJRCARHV-SBrBJBZG.js → stateDiagram-AJRCARHV-B0O5w5lJ.js} +1 -1
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-RXZRaSgT.js +1 -0
- package/workframe-ui/public/assets/{timeline-definition-PNZ67QCA-DegmxXXj.js → timeline-definition-PNZ67QCA-oyqa5w5y.js} +1 -1
- package/workframe-ui/public/assets/{treeView-BLDUP644-BVy7CsCj.js → treeView-BLDUP644-MCV12-eP.js} +1 -1
- package/workframe-ui/public/assets/{treemap-LRROVOQU-BD5Kb74J.js → treemap-LRROVOQU-DiA1P9n5.js} +1 -1
- package/workframe-ui/public/assets/{vennDiagram-CIIHVFJN-hwAkNbl3.js → vennDiagram-CIIHVFJN-CO_4x7OR.js} +1 -1
- package/workframe-ui/public/assets/{wardley-L42UT6IY-CBMPT8Y1.js → wardley-L42UT6IY-CmQNv6Xv.js} +1 -1
- package/workframe-ui/public/assets/{wardleyDiagram-YWT4CUSO-DXqihVlE.js → wardleyDiagram-YWT4CUSO-CJxDkbIj.js} +1 -1
- package/workframe-ui/public/assets/{xychartDiagram-2RQKCTM6-Cbb4LBzj.js → xychartDiagram-2RQKCTM6-B02MxgzG.js} +1 -1
- package/workframe-ui/public/index.html +7 -10
- package/workframe-ui/public/assets/architecture-7EHR7CIX-DOxsUI33.js +0 -1
- package/workframe-ui/public/assets/channel-Baa20pIs.js +0 -1
- package/workframe-ui/public/assets/chunk-QZHKN3VN-B7tPxs4H.js +0 -1
- package/workframe-ui/public/assets/chunk-WU5MYG2G-Dvh2By1o.js +0 -1
- package/workframe-ui/public/assets/classDiagram-4FO5ZUOK-BljHyDzF.js +0 -1
- package/workframe-ui/public/assets/classDiagram-v2-Q7XG4LA2-BljHyDzF.js +0 -1
- package/workframe-ui/public/assets/eventmodeling-FCH6USID-C4xwO6dx.js +0 -1
- package/workframe-ui/public/assets/index-BIfRGM8p.js +0 -133
- package/workframe-ui/public/assets/stateDiagram-v2-BHNVJYJU-B3im3So2.js +0 -1
package/README.md
CHANGED
package/package.json
CHANGED
package/workframe-api/server.py
CHANGED
|
@@ -12434,7 +12434,9 @@ def _overlay_chat_llm_env(
|
|
|
12434
12434
|
user = str(user_id or "").strip()
|
|
12435
12435
|
if not user:
|
|
12436
12436
|
return False
|
|
12437
|
-
prov = _llm_billing_provider(hermes_prof, provider)
|
|
12437
|
+
prov = _llm_billing_provider(hermes_prof, provider, user_id=user, workspace_id=workspace_id)
|
|
12438
|
+
if not _profile_llm_proxy_matches_billing(hermes_prof, prov):
|
|
12439
|
+
_ensure_profile_llm_proxy(hermes_prof, prov)
|
|
12438
12440
|
slug = safe_profile_slug(hermes_prof)
|
|
12439
12441
|
turn_run = str(uuid.uuid4())
|
|
12440
12442
|
ready = _try_overlay_turn_provider_env(hermes_prof, user, workspace_id, prov, turn_run)
|
|
@@ -12513,21 +12515,91 @@ def _augment_model_suggestions(
|
|
|
12513
12515
|
return extra + suggestions
|
|
12514
12516
|
|
|
12515
12517
|
|
|
12516
|
-
|
|
12517
|
-
|
|
12518
|
-
|
|
12519
|
-
|
|
12520
|
-
|
|
12521
|
-
|
|
12522
|
-
|
|
12523
|
-
|
|
12524
|
-
|
|
12525
|
-
|
|
12526
|
-
|
|
12527
|
-
|
|
12518
|
+
_INTERNAL_LLM_PROXY_RE = re.compile(r"/internal/llm/([a-z0-9_-]+)/v1", re.I)
|
|
12519
|
+
|
|
12520
|
+
|
|
12521
|
+
def _billing_provider_from_block(base_url: str, cfg_provider: str, hint: str) -> str:
|
|
12522
|
+
"""Pure resolver: the billing provider is the proxy URL segment (the stored fact).
|
|
12523
|
+
|
|
12524
|
+
Order: explicit hint > proxy URL segment > cfg_provider > "openrouter".
|
|
12525
|
+
The model-id prefix (e.g. ``google/`` in ``google/gemini-2.5-flash``) is an
|
|
12526
|
+
OpenRouter vendor namespace, NOT a billing provider, so it is never used here.
|
|
12527
|
+
ponytail: removing model-prefix inference is the root-cause fix for the
|
|
12528
|
+
"provider not recognized" bug where an OpenRouter-only user was billed to google.
|
|
12529
|
+
"""
|
|
12530
|
+
h = str(hint or "").strip().lower()
|
|
12531
|
+
if h and h not in {"custom", "auto"}:
|
|
12532
|
+
return h
|
|
12533
|
+
m = _INTERNAL_LLM_PROXY_RE.search(str(base_url or ""))
|
|
12534
|
+
if m:
|
|
12535
|
+
return m.group(1).lower()
|
|
12536
|
+
cfg = str(cfg_provider or "").strip().lower()
|
|
12537
|
+
if cfg and cfg not in {"custom", "auto"}:
|
|
12538
|
+
return cfg
|
|
12528
12539
|
return "openrouter"
|
|
12529
12540
|
|
|
12530
12541
|
|
|
12542
|
+
def _llm_billing_provider(
|
|
12543
|
+
profile: str,
|
|
12544
|
+
provider_hint: str = "",
|
|
12545
|
+
*,
|
|
12546
|
+
user_id: str = "",
|
|
12547
|
+
workspace_id: str = "",
|
|
12548
|
+
) -> str:
|
|
12549
|
+
"""Map Hermes routing provider (often custom for proxy) to vault/billing provider id."""
|
|
12550
|
+
prof = resolve_hermes_profile(profile)
|
|
12551
|
+
block = _read_model_block(prof)
|
|
12552
|
+
cfg_provider = str(block.get("provider") or "").strip().lower()
|
|
12553
|
+
if not cfg_provider:
|
|
12554
|
+
cfg_provider = str(_read_model_from_config(prof)[0] or "").strip().lower()
|
|
12555
|
+
candidate = _billing_provider_from_block(
|
|
12556
|
+
str(block.get("base_url") or ""), cfg_provider, provider_hint,
|
|
12557
|
+
)
|
|
12558
|
+
user = str(user_id or "").strip()
|
|
12559
|
+
ws = str(workspace_id or "").strip()
|
|
12560
|
+
if user and not _user_can_use_llm(user, ws, candidate):
|
|
12561
|
+
connected = sorted(_user_llm_providers_for_picker(user))
|
|
12562
|
+
if connected:
|
|
12563
|
+
return connected[0]
|
|
12564
|
+
return candidate or "openrouter"
|
|
12565
|
+
|
|
12566
|
+
|
|
12567
|
+
def _profile_llm_proxy_matches_billing(profile: str, billing_provider: str) -> bool:
|
|
12568
|
+
prof = resolve_hermes_profile(profile)
|
|
12569
|
+
base = str(_read_model_block(prof).get("base_url") or "").strip()
|
|
12570
|
+
return bool(base) and base == _llm_proxy_base_url(billing_provider)
|
|
12571
|
+
|
|
12572
|
+
|
|
12573
|
+
def _reconcile_profile_llm_for_user(
|
|
12574
|
+
profile: str,
|
|
12575
|
+
user_id: str,
|
|
12576
|
+
workspace_id: str,
|
|
12577
|
+
*,
|
|
12578
|
+
prefer_provider: str = "",
|
|
12579
|
+
) -> bool:
|
|
12580
|
+
"""Point proxy + MVP model at a provider the acting user can bill."""
|
|
12581
|
+
user = str(user_id or "").strip()
|
|
12582
|
+
if not user:
|
|
12583
|
+
return False
|
|
12584
|
+
prof = resolve_hermes_profile(profile)
|
|
12585
|
+
billing = _llm_billing_provider(prof, user_id=user, workspace_id=workspace_id)
|
|
12586
|
+
prefer = str(prefer_provider or "").strip().lower()
|
|
12587
|
+
if prefer and _user_can_use_llm(user, workspace_id, prefer):
|
|
12588
|
+
billing = prefer
|
|
12589
|
+
elif not _user_can_use_llm(user, workspace_id, billing):
|
|
12590
|
+
connected = sorted(_user_llm_providers_for_picker(user))
|
|
12591
|
+
if not connected:
|
|
12592
|
+
return False
|
|
12593
|
+
billing = connected[0]
|
|
12594
|
+
if _user_can_use_llm(user, workspace_id, billing) and _profile_llm_proxy_matches_billing(prof, billing):
|
|
12595
|
+
return False
|
|
12596
|
+
changed = _apply_mvp_model_for_provider(prof, billing)
|
|
12597
|
+
block = _read_model_block(prof)
|
|
12598
|
+
if _is_runtime_profile_slug(prof) or str(block.get("provider") or "").strip().lower() == "custom":
|
|
12599
|
+
_ensure_profile_llm_proxy(prof, billing)
|
|
12600
|
+
return changed
|
|
12601
|
+
|
|
12602
|
+
|
|
12531
12603
|
def _bootstrap_profile_providers(profile: str, user_id: str = "", workspace_id: str = "") -> bool:
|
|
12532
12604
|
"""Seed profile auth + MVP model config from user, workspace, or primary stack."""
|
|
12533
12605
|
prof = resolve_hermes_profile(profile)
|
|
@@ -12756,7 +12828,9 @@ def profile_chat_session(profile: str, payload: dict[str, Any], user_id: str = "
|
|
|
12756
12828
|
profile, user_id, "", workspace_id,
|
|
12757
12829
|
)
|
|
12758
12830
|
payer = user_id
|
|
12759
|
-
|
|
12831
|
+
if payer:
|
|
12832
|
+
_reconcile_profile_llm_for_user(hermes_prof, payer, workspace_id)
|
|
12833
|
+
llm_provider = _llm_billing_provider(hermes_prof, user_id=payer, workspace_id=workspace_id)
|
|
12760
12834
|
lifecycle = ensure_profile_api(hermes_prof, user_id, workspace_id)
|
|
12761
12835
|
llm_ready = _user_can_use_llm(payer, workspace_id, llm_provider) if payer else False
|
|
12762
12836
|
session_extra = {"llm_ready": llm_ready, "has_llm_provider": llm_ready}
|
|
@@ -13064,7 +13138,9 @@ def profile_chat_activate_room_session(
|
|
|
13064
13138
|
gateway_sid,
|
|
13065
13139
|
)
|
|
13066
13140
|
|
|
13067
|
-
|
|
13141
|
+
if payer:
|
|
13142
|
+
_reconcile_profile_llm_for_user(hermes_prof, payer, workspace_id)
|
|
13143
|
+
llm_provider = _llm_billing_provider(hermes_prof, user_id=payer, workspace_id=workspace_id)
|
|
13068
13144
|
llm_ready = _overlay_chat_llm_env(hermes_prof, user_id, workspace_id, llm_provider)
|
|
13069
13145
|
|
|
13070
13146
|
history = chat_messages(hermes_prof, session_id)
|
|
@@ -13277,7 +13353,9 @@ def profile_chat_message(profile: str, payload: dict[str, Any]) -> dict[str, Any
|
|
|
13277
13353
|
hermes_prof, _template_prof = _resolve_bind_profile_arg(
|
|
13278
13354
|
profile, payer, room_id, workspace_id,
|
|
13279
13355
|
)
|
|
13280
|
-
|
|
13356
|
+
if payer:
|
|
13357
|
+
_reconcile_profile_llm_for_user(hermes_prof, payer, workspace_id)
|
|
13358
|
+
llm_provider = _llm_billing_provider(hermes_prof, user_id=payer, workspace_id=workspace_id)
|
|
13281
13359
|
lifecycle = ensure_profile_api(
|
|
13282
13360
|
hermes_prof,
|
|
13283
13361
|
payer,
|
|
@@ -13432,7 +13510,9 @@ def stream_profile_chat(handler: BaseHTTPRequestHandler, profile: str, payload:
|
|
|
13432
13510
|
raise ValueError("session_id required")
|
|
13433
13511
|
if not text:
|
|
13434
13512
|
raise ValueError("text required")
|
|
13435
|
-
|
|
13513
|
+
if _triggering_user:
|
|
13514
|
+
_reconcile_profile_llm_for_user(prof, _triggering_user, _workspace_id)
|
|
13515
|
+
llm_provider = _llm_billing_provider(prof, user_id=_triggering_user, workspace_id=_workspace_id)
|
|
13436
13516
|
llm_ready = bool(
|
|
13437
13517
|
_triggering_user
|
|
13438
13518
|
and _user_can_use_llm(_triggering_user, _workspace_id, llm_provider)
|
|
@@ -14431,17 +14511,23 @@ def _bootstrap_model_after_llm_connect(
|
|
|
14431
14511
|
if not spec or str(spec.get("category") or "") != "llm":
|
|
14432
14512
|
return
|
|
14433
14513
|
provider_key = str(provider or "").strip().lower()
|
|
14514
|
+
user = str(user_id or "").strip()
|
|
14515
|
+
ws = str(workspace_id or "").strip()
|
|
14434
14516
|
primary = _primary_profile()
|
|
14435
14517
|
if primary:
|
|
14436
14518
|
_, model = _read_model_from_config(primary)
|
|
14437
14519
|
if not str(model or "").strip():
|
|
14438
14520
|
_apply_mvp_model_for_provider(primary, provider_key)
|
|
14521
|
+
elif user:
|
|
14522
|
+
_reconcile_profile_llm_for_user(primary, user, ws, prefer_provider=provider_key)
|
|
14439
14523
|
template = primary or "workframe-agent"
|
|
14440
14524
|
runtime = _runtime_profile_slug(user_id, template)
|
|
14441
14525
|
if _runtime_profile_on_disk(runtime):
|
|
14442
14526
|
_, model = _read_model_from_config(runtime)
|
|
14443
14527
|
if not str(model or "").strip():
|
|
14444
14528
|
_apply_mvp_model_for_provider(runtime, provider_key)
|
|
14529
|
+
elif user:
|
|
14530
|
+
_reconcile_profile_llm_for_user(runtime, user, ws, prefer_provider=provider_key)
|
|
14445
14531
|
|
|
14446
14532
|
|
|
14447
14533
|
# Curated snapshot of commonly-used models per provider. Surfaced in the
|
|
@@ -14504,9 +14590,6 @@ HERMES_MODEL_CATALOG: list[dict[str, str]] = [
|
|
|
14504
14590
|
{"provider": "OpenRouter", "model": "openrouter/nvidia/llama-3.1-nemotron-70b-instruct",
|
|
14505
14591
|
"label": "Nemotron 70B Instruct",
|
|
14506
14592
|
"description": "NVIDIA Nemotron via OpenRouter."},
|
|
14507
|
-
{"provider": "OpenRouter", "model": "openrouter/anthropic/claude-sonnet-4-5",
|
|
14508
|
-
"label": "Claude Sonnet 4.5 (via OR)",
|
|
14509
|
-
"description": "Sonnet through OpenRouter."},
|
|
14510
14593
|
{"provider": "OpenRouter", "model": "openrouter/openai/gpt-4o",
|
|
14511
14594
|
"label": "GPT-4o (via OR)",
|
|
14512
14595
|
"description": "GPT-4o through OpenRouter."},
|
|
@@ -14889,6 +14972,15 @@ def hermes_models(profile: str = "", user_id: str = "", workspace_id: str = "")
|
|
|
14889
14972
|
for row in live
|
|
14890
14973
|
if str(row.get("model") or "") not in seen
|
|
14891
14974
|
] + suggestions
|
|
14975
|
+
seen_models: set[str] = set()
|
|
14976
|
+
deduped: list[dict[str, str]] = []
|
|
14977
|
+
for row in suggestions:
|
|
14978
|
+
mid = str(row.get("model") or "").strip()
|
|
14979
|
+
if not mid or mid in seen_models:
|
|
14980
|
+
continue
|
|
14981
|
+
seen_models.add(mid)
|
|
14982
|
+
deduped.append(row)
|
|
14983
|
+
suggestions = deduped
|
|
14892
14984
|
return {
|
|
14893
14985
|
"ok": True,
|
|
14894
14986
|
"profile": primary_profile,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""ponytail self-check: billing provider source of truth = proxy URL, never model-id prefix.
|
|
2
|
+
|
|
3
|
+
Run: python services/workframe-api/test_billing_provider.py
|
|
4
|
+
No framework, no fixtures. Fails fast if the inference regression returns.
|
|
5
|
+
"""
|
|
6
|
+
import sys
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent))
|
|
10
|
+
|
|
11
|
+
import server # noqa: E402 (module import is side-effect-free; main() is guarded)
|
|
12
|
+
|
|
13
|
+
# The bug case: profile model is google/gemini-2.5-flash but proxy routes via openrouter.
|
|
14
|
+
# The model-id prefix MUST NOT leak as the billing provider.
|
|
15
|
+
assert server._billing_provider_from_block("/internal/llm/openrouter/v1", "custom", "") == "openrouter", \
|
|
16
|
+
"proxy URL segment must win over model-id prefix"
|
|
17
|
+
# Explicit hint honored.
|
|
18
|
+
assert server._billing_provider_from_block("", "", "anthropic") == "anthropic", "hint honored"
|
|
19
|
+
# Empty block defaults to openrouter (no inference).
|
|
20
|
+
assert server._billing_provider_from_block("", "", "") == "openrouter", "empty-block default"
|
|
21
|
+
# cfg_provider honored only when no proxy URL is set.
|
|
22
|
+
assert server._billing_provider_from_block("", "openai", "") == "openai", "cfg_provider honored without proxy"
|
|
23
|
+
|
|
24
|
+
print("billing provider self-check ok")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-
|
|
1
|
+
import{n as e,t}from"./path-BWPyau1x.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BLcLhTn6.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i)if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./chunk-NNHCCRGN-DlpIbxXb.js";import{x as e}from"./mermaid-parser.core-Cid5yDBQ.js";export{e as createArchitectureServices};
|