forge-openclaw-plugin 0.2.101 → 0.2.102
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/assets/{activity-page-CpjuNSHw.js → activity-page-CgF7K2ww.js} +1 -1
- package/dist/assets/ai-surface-workspace-xtB5RFQu.js +1 -0
- package/dist/assets/atlas-panel-B3dPHCmZ.js +1 -0
- package/dist/assets/{board-BkDRaMp6.js → board-DqHzdCPQ.js} +1 -1
- package/dist/assets/{calendar-page-DNNt6lfz.js → calendar-page-C1Wfd2Fy.js} +1 -1
- package/dist/assets/{calendar-rules-DNJFNsxi.js → calendar-rules-CaZXtlxt.js} +1 -1
- package/dist/assets/calendar-week-toolbar-BZ_-X3Wb.js +1 -0
- package/dist/assets/{charts-P7EVhIog.js → charts-FcU0F3XV.js} +8 -8
- package/dist/assets/{companion-sync-lab-page-KxEDigM6.js → companion-sync-lab-page-NgeK-O-P.js} +1 -1
- package/dist/assets/daily-metrics-dashboard-BMyL0Qr4.js +1 -0
- package/dist/assets/{entity-note-count-link-DrhjJZ4i.js → entity-note-count-link-BrS1-O0o.js} +1 -1
- package/dist/assets/entity-notes-surface-CBylYDwy.js +1 -0
- package/dist/assets/{execution-board-D07gOocB.js → execution-board-CpO2ch6v.js} +1 -1
- package/dist/assets/faceted-token-search-D7xPWfOl.js +1 -0
- package/dist/assets/flagship-signal-deck-BEFKOhvx.js +1 -0
- package/dist/assets/{floating-action-menu-Fs_ZiUMo.js → floating-action-menu-zzC2r0Ob.js} +1 -1
- package/dist/assets/{forms-BFlTgZ3W.js → forms-CmLAyGqz.js} +1 -1
- package/dist/assets/{goal-detail-page-CqLiNz4f.js → goal-detail-page-JK_Nva8e.js} +1 -1
- package/dist/assets/goals-page-yeoJ06Vw.js +1 -0
- package/dist/assets/{graph-D6JLqDbD.js → graph-BTa79qum.js} +14 -14
- package/dist/assets/{habits-page-BJxagdzx.js → habits-page-Dx5EhkJi.js} +1 -1
- package/dist/assets/index-BHIKoiZ6.js +19 -0
- package/dist/assets/index-H8R-ABM3.css +1 -0
- package/dist/assets/insight-flow-dialog-BtIQXXsS.js +1 -0
- package/dist/assets/{insights-page-D6rOa7uk.js → insights-page-CujrosD_.js} +1 -1
- package/dist/assets/{kanban-page-XQ7Se6dH.js → kanban-page-Q9NuIz5w.js} +1 -1
- package/dist/assets/knowledge-graph-page-DaJmlvvM.js +1 -0
- package/dist/assets/{life-force-page-Dy0JTS2G.js → life-force-page-BGDkKfbJ.js} +1 -1
- package/dist/assets/{life-force-workspace-OfyB9HJM.js → life-force-workspace-CLVexVnb.js} +1 -1
- package/dist/assets/{maps-ClgJoCjz.js → maps-CF1RagUX.js} +1 -1
- package/dist/assets/metric-tile-4iMd_WnJ.js +1 -0
- package/dist/assets/{motion-BeD44FeG.js → motion-CfdU2F35.js} +1 -1
- package/dist/assets/movement-page-ClaoTNuX.js +1 -0
- package/dist/assets/note-markdown-CsGQhQXF.js +3 -0
- package/dist/assets/note-tags-input-DdZi93tj.js +1 -0
- package/dist/assets/notes-page-DYI8s3NN.js +1 -0
- package/dist/assets/{open-in-graph-button-IXe9SGth.js → open-in-graph-button-C0TGev7c.js} +1 -1
- package/dist/assets/orbit-map-DVXkfQdd.js +1 -0
- package/dist/assets/overview-page-BwMlFQKX.js +1 -0
- package/dist/assets/page-hero-oFHaAjtL.js +1 -0
- package/dist/assets/pill-cluster-7UZd_lHp.js +1 -0
- package/dist/assets/{preference-entity-handoff-button-5PzUn42S.js → preference-entity-handoff-button-DOKV9bZc.js} +1 -1
- package/dist/assets/preferences-page-BrKEkmfD.js +1 -0
- package/dist/assets/{project-collections-xPz2mlRr.js → project-collections-CZagCmeH.js} +1 -1
- package/dist/assets/{project-detail-page-BXK5-4xW.js → project-detail-page-DogvVNEn.js} +1 -1
- package/dist/assets/{project-management-hierarchy-page-DtRpMABw.js → project-management-hierarchy-page-Dr7hW9PW.js} +1 -1
- package/dist/assets/{project-management-section-nav-P3ixzPa-.js → project-management-section-nav-BLdAgTge.js} +1 -1
- package/dist/assets/{projects-page-C5ViRuf4.js → projects-page-UKrby_5-.js} +1 -1
- package/dist/assets/psyche-behaviors-page-BeVlXvbj.js +5 -0
- package/dist/assets/psyche-flashcards-page-CqAWCO4E.js +1 -0
- package/dist/assets/psyche-goal-map-page-IyNnbk_W.js +1 -0
- package/dist/assets/psyche-graph-IkUQRaDK.js +1 -0
- package/dist/assets/{psyche-metrics-page-CuR9oqEy.js → psyche-metrics-page-uai0a7Lx.js} +1 -1
- package/dist/assets/psyche-mode-guide-page-C7p-ABiF.js +1 -0
- package/dist/assets/psyche-modes-page-CLQ5V3w0.js +1 -0
- package/dist/assets/psyche-page-NQBHkkpU.js +1 -0
- package/dist/assets/psyche-patterns-page-BkRiNpI_.js +5 -0
- package/dist/assets/psyche-questionnaire-builder-page-Du-7HwPC.js +1 -0
- package/dist/assets/psyche-questionnaire-detail-page-C5-yf8MF.js +1 -0
- package/dist/assets/psyche-questionnaire-run-detail-page-CoSH5O6R.js +1 -0
- package/dist/assets/psyche-questionnaire-run-page-ChI7c1wy.js +1 -0
- package/dist/assets/psyche-questionnaires-page-xUcJJzbI.js +1 -0
- package/dist/assets/psyche-report-detail-page-BPrZCFZS.js +3 -0
- package/dist/assets/psyche-reports-page-D2EXJmm6.js +1 -0
- package/dist/assets/{psyche-schemas-HFmg37Wj.js → psyche-schemas-RcZYaokx.js} +1 -1
- package/dist/assets/psyche-schemas-beliefs-page-h0ooZ1lp.js +9 -0
- package/dist/assets/psyche-screen-time-page-_3-4LikV.js +1 -0
- package/dist/assets/psyche-self-observation-page-BdbCsgR5.js +1 -0
- package/dist/assets/psyche-values-page-DuUVki5e.js +5 -0
- package/dist/assets/report-chain-fields-BBMz0sGI.js +1 -0
- package/dist/assets/{rewards-page-DmC4R_Ps.js → rewards-page-PZFPa6rR.js} +1 -1
- package/dist/assets/{scheduling-rules-editor-D02s70hr.js → scheduling-rules-editor-B9KNKsQz.js} +1 -1
- package/dist/assets/schema-badge-D93RcG36.js +1 -0
- package/dist/assets/schema-visuals-CvC9a3i6.js +1 -0
- package/dist/assets/select-menu-Cdq7foRu.js +1 -0
- package/dist/assets/{settings-agents-page-C_v_hMJF.js → settings-agents-page-DPx2F6wf.js} +3 -3
- package/dist/assets/{settings-bin-page-DY5bg81n.js → settings-bin-page-COwP3gjo.js} +1 -1
- package/dist/assets/settings-calendar-page-C-ghE0YT.js +5 -0
- package/dist/assets/{settings-data-page-CHRQFU9H.js → settings-data-page-CBubzKBw.js} +1 -1
- package/dist/assets/{settings-logs-page-B04pUwEv.js → settings-logs-page-uOuXMeBm.js} +1 -1
- package/dist/assets/{settings-mobile-page-D9kTlYDS.js → settings-mobile-page-C5rfj8_r.js} +1 -1
- package/dist/assets/settings-models-page-DijmUWdU.js +1 -0
- package/dist/assets/{settings-page-DYDTFlnv.js → settings-page-B4u5TR5g.js} +1 -1
- package/dist/assets/{settings-rewards-page-cl4vqqO_.js → settings-rewards-page-COiTwkMH.js} +1 -1
- package/dist/assets/{settings-section-nav-DSOuht_F.js → settings-section-nav-Dc4IeVBt.js} +1 -1
- package/dist/assets/{settings-users-page-BU79JB_T.js → settings-users-page-DEGa5DNn.js} +1 -1
- package/dist/assets/settings-wiki-page-Cvsiz5_e.js +1 -0
- package/dist/assets/{sleep-page-D8NbdhyS.js → sleep-page-BnSOwkEU.js} +1 -1
- package/dist/assets/{sports-page-CV4Cnzwn.js → sports-page-l1RqXzA_.js} +1 -1
- package/dist/assets/{state-B-4sS1xO.js → state-VYvD1QVP.js} +1 -1
- package/dist/assets/{strategies-page-C4qvXnql.js → strategies-page-DEnPlpAs.js} +1 -1
- package/dist/assets/{strategy-detail-page-DJLo5rfy.js → strategy-detail-page-Ls8bxKeH.js} +1 -1
- package/dist/assets/strategy-dialog-DMyRKrWf.js +1 -0
- package/dist/assets/surface-Bfz_sLX6.js +1 -0
- package/dist/assets/{table-WfAPUppN.js → table-C0VTeqw0.js} +1 -1
- package/dist/assets/task-detail-page-CgrYgQLD.js +1 -0
- package/dist/assets/{timebox-planning-dialog-DB6FLqmI.js → timebox-planning-dialog-Ww0NGLLo.js} +1 -1
- package/dist/assets/today-page-CIuFHMi1.js +1 -0
- package/dist/assets/training-load-page-BIwc648i.js +1 -0
- package/dist/assets/{ui-C13Nbgas.js → ui-CsEkP2V8.js} +4 -4
- package/dist/assets/use-psyche-focus-target-qxT5Oy_z.js +1 -0
- package/dist/assets/{vendor-DHkYh85p.js → vendor-kIz9EZnX.js} +237 -222
- package/dist/assets/{vitals-page-qre17Nw8.js → vitals-page-Dz1Jt5H8.js} +1 -1
- package/dist/assets/{weekly-review-page-Cz4vkRcx.js → weekly-review-page-BFpBe1kI.js} +1 -1
- package/dist/assets/weight-loss-page-BgMoBpBt.js +5 -0
- package/dist/assets/{wiki-article-markdown-DdiR2TJE.js → wiki-article-markdown-gsPTXTg1.js} +1 -1
- package/dist/assets/{wiki-editor-page-DqwoqVFb.js → wiki-editor-page-BpAZHooY.js} +7 -7
- package/dist/assets/{wiki-ingest-history-page--evBLbOw.js → wiki-ingest-history-page-C-ig8O22.js} +1 -1
- package/dist/assets/{wiki-ingest-modal--ohzFnj2.js → wiki-ingest-modal-BK4eQgqs.js} +1 -1
- package/dist/assets/{wiki-page-B_VJFBPA.js → wiki-page-CMTZ60Zt.js} +1 -1
- package/dist/assets/workbench-flow-page-BIpWUcLJ.js +5 -0
- package/dist/assets/workbench-page-CtCjYSRe.js +1 -0
- package/dist/assets/workout-detail-page-DD9IGN6l.js +2 -0
- package/dist/index.html +9 -9
- package/dist/openclaw/local-runtime.js +41 -14
- package/dist/server/server/migrations/067_weight_loss_daily_active_overrides.sql +13 -0
- package/dist/server/server/src/app.js +103 -30
- package/dist/server/server/src/health-weight-loss.js +457 -55
- package/dist/server/server/src/health.js +12 -4
- package/dist/server/server/src/movement.js +84 -1
- package/dist/server/server/src/openapi.js +123 -18
- package/dist/server/server/src/repositories/model-settings.js +12 -9
- package/dist/server/server/src/repositories/settings.js +19 -5
- package/dist/server/src/components/ui/info-tooltip.js +6 -6
- package/dist/server/src/lib/api.js +14 -4
- package/dist/server/src/lib/theme-system.js +8 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -3
- package/server/migrations/067_weight_loss_daily_active_overrides.sql +13 -0
- package/skills/forge-openclaw/SKILL.md +13 -0
- package/skills/forge-openclaw/entity_conversation_playbooks.md +7 -1
- package/dist/assets/ai-surface-workspace-DEAFZruS.js +0 -1
- package/dist/assets/atlas-panel-CdVNPotj.js +0 -1
- package/dist/assets/calendar-week-toolbar-BbPwYeN0.js +0 -1
- package/dist/assets/daily-metrics-dashboard-B3cqJgDt.js +0 -1
- package/dist/assets/entity-notes-surface-CkcRsKJQ.js +0 -1
- package/dist/assets/faceted-token-search-BxRRcM3q.js +0 -1
- package/dist/assets/flagship-signal-deck-cmy82b8_.js +0 -1
- package/dist/assets/goals-page-BTk7mg_T.js +0 -1
- package/dist/assets/index-CF4J4R9L.js +0 -19
- package/dist/assets/index-CZbuZQjw.css +0 -1
- package/dist/assets/insight-flow-dialog-8f3D0GuC.js +0 -1
- package/dist/assets/knowledge-graph-page-BtAg8iv3.js +0 -1
- package/dist/assets/metric-tile-DKpo-8xw.js +0 -1
- package/dist/assets/movement-page-Bg_T_Stx.js +0 -1
- package/dist/assets/note-markdown-N-uxD3Xt.js +0 -3
- package/dist/assets/note-tags-input-Cdu7wiw6.js +0 -1
- package/dist/assets/notes-page-CKXnF_KU.js +0 -1
- package/dist/assets/orbit-map-Dzi6KliQ.js +0 -1
- package/dist/assets/overview-page-1miYqaVS.js +0 -1
- package/dist/assets/page-hero-DRy5b2MU.js +0 -1
- package/dist/assets/pill-cluster-C9QczVJ2.js +0 -1
- package/dist/assets/preferences-page-DtNaF5Q3.js +0 -1
- package/dist/assets/psyche-behaviors-page-Dco46sC4.js +0 -5
- package/dist/assets/psyche-flashcards-page-ZcoEB8gV.js +0 -1
- package/dist/assets/psyche-goal-map-page-CLBAQOI0.js +0 -1
- package/dist/assets/psyche-graph-k4tX2tdp.js +0 -1
- package/dist/assets/psyche-mode-guide-page-hIVXcCnE.js +0 -1
- package/dist/assets/psyche-modes-page-0lYtBlhO.js +0 -1
- package/dist/assets/psyche-page-VZ9k9ISp.js +0 -1
- package/dist/assets/psyche-patterns-page-gx5nmdGq.js +0 -5
- package/dist/assets/psyche-questionnaire-builder-page-Bn0TOISd.js +0 -1
- package/dist/assets/psyche-questionnaire-detail-page-CmVzSd_s.js +0 -1
- package/dist/assets/psyche-questionnaire-run-detail-page-BsMbmXCG.js +0 -1
- package/dist/assets/psyche-questionnaire-run-page-CgkRL2vi.js +0 -1
- package/dist/assets/psyche-questionnaires-page-D7V8uLXM.js +0 -1
- package/dist/assets/psyche-report-detail-page-OlFq57eL.js +0 -3
- package/dist/assets/psyche-reports-page-dVUZjna1.js +0 -1
- package/dist/assets/psyche-schemas-beliefs-page-BCgc8FUd.js +0 -9
- package/dist/assets/psyche-screen-time-page-B_6BT_WN.js +0 -1
- package/dist/assets/psyche-self-observation-page-CEG5mluK.js +0 -1
- package/dist/assets/psyche-values-page-DRbRfEd6.js +0 -5
- package/dist/assets/report-chain-fields-CALCV3V5.js +0 -1
- package/dist/assets/schema-badge-BZO-qNhO.js +0 -1
- package/dist/assets/schema-visuals-D6nxjbYC.js +0 -1
- package/dist/assets/select-menu-fYyreSdQ.js +0 -1
- package/dist/assets/settings-calendar-page-D1CzE6cg.js +0 -5
- package/dist/assets/settings-models-page-D26270R2.js +0 -1
- package/dist/assets/settings-wiki-page-DwAUlyA3.js +0 -1
- package/dist/assets/strategy-dialog-D3AuUlVz.js +0 -1
- package/dist/assets/task-detail-page-z-9u9rF0.js +0 -1
- package/dist/assets/today-page-BKlu6gx5.js +0 -1
- package/dist/assets/training-load-page-CyJQqo_3.js +0 -1
- package/dist/assets/use-psyche-focus-target-C1C_XjYG.js +0 -1
- package/dist/assets/weight-loss-page-BQrnOI0y.js +0 -1
- package/dist/assets/workbench-flow-page-Du62mtJU.js +0 -5
- package/dist/assets/workbench-page-4MKr3iRm.js +0 -1
- package/dist/assets/workout-detail-page-DfUbYYw1.js +0 -2
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e,b4 as j,aK as b}from"./vendor-DHkYh85p.js";import{I as u,T as x,B as v}from"./index-CF4J4R9L.js";function h(i){return`${i}_${Math.random().toString(36).slice(2,10)}`}function w(){return{id:h("emotion"),emotionDefinitionId:null,label:"",intensity:55,note:""}}function N(){return{id:h("thought"),text:"",parentMode:"",criticMode:"",beliefId:null}}function f(){return{id:h("behavior"),text:"",mode:"",behaviorId:null}}function I(){return{id:h("timeline"),stage:"",modeId:null,label:"",note:""}}function o({title:i,description:l,onAdd:n,addLabel:d}){return e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-base font-medium text-white",children:i}),e.jsx("div",{className:"mt-1 text-sm leading-6 text-white/56",children:l})]}),e.jsxs(v,{type:"button",variant:"secondary",size:"sm",onClick:n,children:[e.jsx(j,{className:"size-4"}),d]})]})}function c({onClick:i}){return e.jsx("button",{type:"button",className:"rounded-full bg-white/[0.06] p-2 text-white/55 transition hover:bg-white/[0.12] hover:text-white",onClick:i,"aria-label":"Remove row",children:e.jsx(b,{className:"size-4"})})}function A({title:i,description:l,addLabel:n,items:d,onChange:s,placeholder:a}){return e.jsxs("div",{className:"grid gap-3",children:[e.jsx(o,{title:i,description:l,addLabel:n,onAdd:()=>s([...d,""])}),e.jsx("div",{className:"grid gap-3",children:d.map((t,r)=>e.jsxs("div",{className:"flex items-start gap-3 rounded-[22px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsx(u,{value:t,onChange:g=>s(d.map((p,m)=>m===r?g.target.value:p)),placeholder:a}),e.jsx(c,{onClick:()=>s(d.filter((g,p)=>p!==r))})]},`${i}-${r}`))})]})}function E({items:i,onChange:l,definitions:n}){return e.jsxs("div",{className:"grid gap-3",children:[e.jsx(o,{title:"What emotions were present?",description:"Add one emotion at a time, set the intensity, and note what stood out.",addLabel:"Add emotion",onAdd:()=>l([...i,w()])}),e.jsx("div",{className:"grid gap-3",children:i.map(d=>e.jsxs("div",{className:"grid gap-4 rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"grid flex-1 gap-4 md:grid-cols-[minmax(0,1fr)_9rem]",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Emotion"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:d.emotionDefinitionId??"",onChange:s=>{const a=n.find(t=>t.id===s.target.value);l(i.map(t=>t.id===d.id?{...t,emotionDefinitionId:s.target.value||null,label:(a==null?void 0:a.label)??t.label}:t))},children:[e.jsx("option",{value:"",children:"Choose or type your own"}),n.map(s=>e.jsx("option",{value:s.id,children:s.label},s.id))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Intensity"}),e.jsxs("div",{className:"rounded-[18px] border border-white/8 bg-white/[0.03] px-4 py-3",children:[e.jsx("input",{type:"range",min:0,max:100,value:d.intensity,onChange:s=>l(i.map(a=>a.id===d.id?{...a,intensity:Number(s.target.value)}:a))}),e.jsxs("div",{className:"mt-2 text-sm text-white/52",children:[d.intensity,"%"]})]})]})]}),e.jsx(c,{onClick:()=>l(i.filter(s=>s.id!==d.id))})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"If the preset is not right, how would you name it?"}),e.jsx(u,{value:d.label,onChange:s=>l(i.map(a=>a.id===d.id?{...a,label:s.target.value}:a)),placeholder:"Tight sadness, panic, shame, relief..."})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"What was notable about this emotion?"}),e.jsx(x,{value:d.note,onChange:s=>l(i.map(a=>a.id===d.id?{...a,note:s.target.value}:a)),placeholder:"Short note about what made this emotion stand out."})]})]},d.id))})]})}function T({items:i,onChange:l,beliefs:n,modes:d}){return e.jsxs("div",{className:"grid gap-3",children:[e.jsx(o,{title:"What did your mind start saying?",description:"Capture the thought itself first, then optionally link a belief or mode influence.",addLabel:"Add thought",onAdd:()=>l([...i,N()])}),e.jsx("div",{className:"grid gap-3",children:i.map(s=>e.jsxs("div",{className:"grid gap-4 rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("label",{className:"grid flex-1 gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Thought"}),e.jsx(x,{value:s.text,onChange:a=>l(i.map(t=>t.id===s.id?{...t,text:a.target.value}:t)),placeholder:"What sentence, image, or conclusion showed up?"})]}),e.jsx(c,{onClick:()=>l(i.filter(a=>a.id!==s.id))})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-3",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Parent mode influence"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.parentMode,onChange:a=>l(i.map(t=>t.id===s.id?{...t,parentMode:a.target.value}:t)),children:[e.jsx("option",{value:"",children:"None"}),d.map(a=>e.jsx("option",{value:a.title,children:a.title},a.id))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Critic mode influence"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.criticMode,onChange:a=>l(i.map(t=>t.id===s.id?{...t,criticMode:a.target.value}:t)),children:[e.jsx("option",{value:"",children:"None"}),d.map(a=>e.jsx("option",{value:a.title,children:a.title},a.id))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Linked belief"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.beliefId??"",onChange:a=>l(i.map(t=>t.id===s.id?{...t,beliefId:a.target.value||null}:t)),children:[e.jsx("option",{value:"",children:"None"}),n.map(a=>e.jsx("option",{value:a.id,children:a.statement},a.id))]})]})]})]},s.id))})]})}function B({items:i,onChange:l,behaviors:n,modes:d}){return e.jsxs("div",{className:"grid gap-3",children:[e.jsx(o,{title:"What did you do, or want to do?",description:"Capture the move itself, then optionally link an existing behavior and the mode context around it.",addLabel:"Add behavior",onAdd:()=>l([...i,f()])}),e.jsx("div",{className:"grid gap-3",children:i.map(s=>e.jsxs("div",{className:"grid gap-4 rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("label",{className:"grid flex-1 gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Behavior or urge"}),e.jsx(x,{value:s.text,onChange:a=>l(i.map(t=>t.id===s.id?{...t,text:a.target.value}:t)),placeholder:"What did you do, or what move did you feel pulled toward?"})]}),e.jsx(c,{onClick:()=>l(i.filter(a=>a.id!==s.id))})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Linked existing behavior"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.behaviorId??"",onChange:a=>{const t=n.find(r=>r.id===a.target.value);l(i.map(r=>r.id===s.id?{...r,behaviorId:a.target.value||null,text:t&&!r.text?t.title:r.text}:r))},children:[e.jsx("option",{value:"",children:"None"}),n.map(a=>e.jsx("option",{value:a.id,children:a.title},a.id))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Mode or urge context"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.mode,onChange:a=>l(i.map(t=>t.id===s.id?{...t,mode:a.target.value}:t)),children:[e.jsx("option",{value:"",children:"None"}),d.map(a=>e.jsx("option",{value:a.title,children:a.title},a.id))]})]})]})]},s.id))})]})}function L({items:i,onChange:l,modes:n,stages:d}){return e.jsxs("div",{className:"grid gap-3",children:[e.jsx(o,{title:"How did your state shift through the chain?",description:"Build the mode timeline one moment at a time instead of typing parser syntax.",addLabel:"Add timeline moment",onAdd:()=>l([...i,I()])}),e.jsx("div",{className:"grid gap-3",children:i.map(s=>e.jsxs("div",{className:"grid gap-4 rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"grid flex-1 gap-4 md:grid-cols-3",children:[e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Stage"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.stage,onChange:a=>l(i.map(t=>t.id===s.id?{...t,stage:a.target.value}:t)),children:[e.jsx("option",{value:"",children:"Choose stage"}),d.map(a=>e.jsx("option",{value:a,children:a},a))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Mode"}),e.jsxs("select",{className:"rounded-[18px] border border-white/8 bg-white/6 px-4 py-3 text-sm text-white",value:s.modeId??"",onChange:a=>{const t=n.find(r=>r.id===a.target.value);l(i.map(r=>r.id===s.id?{...r,modeId:a.target.value||null,label:t&&!r.label?t.title:r.label}:r))},children:[e.jsx("option",{value:"",children:"Choose mode"}),n.map(a=>e.jsx("option",{value:a.id,children:a.title},a.id))]})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"Moment label"}),e.jsx(u,{value:s.label,onChange:a=>l(i.map(t=>t.id===s.id?{...t,label:a.target.value}:t)),placeholder:"What was happening in this moment?"})]})]}),e.jsx(c,{onClick:()=>l(i.filter(a=>a.id!==s.id))})]}),e.jsxs("label",{className:"grid gap-2",children:[e.jsx("span",{className:"text-sm text-white/62",children:"What was important about this shift?"}),e.jsx(x,{value:s.note,onChange:a=>l(i.map(t=>t.id===s.id?{...t,note:a.target.value}:t)),placeholder:"Short note about how the mode showed up or what it was protecting."})]})]},s.id))})]})}export{B,E,L as M,A as S,T};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{j as e}from"./vendor-DHkYh85p.js";import{Z as l}from"./index-CF4J4R9L.js";import{a as m,b as o}from"./schema-visuals-D6nxjbYC.js";function d({label:s,schemaType:a,compact:n=!1,showType:t=!1,className:i}){const r=o(a);return e.jsxs("span",{className:l("inline-flex max-w-full min-w-0 items-center gap-2 rounded-full border px-3 py-1.5 text-sm leading-tight shadow-[inset_0_1px_0_rgba(255,255,255,0.04)]",n?"min-h-8":"min-h-9",r.badgeTone,i),children:[t?e.jsx("span",{className:"text-[11px] uppercase tracking-[0.16em] text-white/58",children:m(a)}):null,e.jsx("span",{className:"min-w-0 break-words whitespace-normal",children:s})]})}export{d as S};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const o={maladaptive:"Maladaptive schema",adaptive:"Adaptive schema"},d={maladaptive:"A recurring pressure pattern that can distort how you interpret situations or respond.",adaptive:"A stable healthy belief pattern you want to strengthen and rely on."},l={disconnection_rejection:"Disconnection & rejection",impaired_autonomy:"Autonomy & competence",other_directedness:"Boundaries & mutuality",overvigilance_inhibition:"Standards & inhibition",healthy_selfhood:"Healthy selfhood"};function c(e){return o[e]}function g(e){return d[e]}function s(e){return l[e]??e.replaceAll("_"," ")}function b(e){return e==="adaptive"?{sectionTone:"border-emerald-400/14 bg-[linear-gradient(180deg,rgba(26,53,48,0.72),rgba(10,18,30,0.92))]",sectionEyebrow:"text-emerald-200/84",cardTone:"border-emerald-400/14 bg-[linear-gradient(180deg,rgba(28,63,56,0.44),rgba(14,24,36,0.92))]",badgeTone:"border-emerald-300/18 bg-[linear-gradient(135deg,rgba(16,185,129,0.18),rgba(56,189,248,0.12))] text-emerald-50",subtleBadgeTone:"border-emerald-300/12 bg-[rgba(16,185,129,0.1)] text-emerald-100/88",countLabel:"support links",linkSummary:"linked strengthening belief",emptyCopy:"No adaptive schema is linked yet. Add one when you want to capture the healthier pattern you are building from."}:{sectionTone:"border-fuchsia-400/14 bg-[linear-gradient(180deg,rgba(44,28,58,0.72),rgba(10,18,30,0.92))]",sectionEyebrow:"text-fuchsia-200/84",cardTone:"border-violet-400/14 bg-[linear-gradient(180deg,rgba(48,33,68,0.44),rgba(14,18,34,0.92))]",badgeTone:"border-rose-300/18 bg-[linear-gradient(135deg,rgba(244,63,94,0.16),rgba(168,85,247,0.12))] text-rose-50",subtleBadgeTone:"border-rose-300/12 bg-[rgba(244,63,94,0.1)] text-rose-100/88",countLabel:"linked records",linkSummary:"linked belief",emptyCopy:"No maladaptive schema is linked yet. Add one when you want to capture the recurring old pattern clearly."}}function n(e){return e.trim().toLowerCase()}function i(e,a){const t=n(a);return[e.id,e.slug,e.title].some(r=>n(r)===t)}function u(e,a){return a.find(t=>i(t,e))??null}function m(e,a){const t=e.filter(r=>!i(a,r));return t.length===e.length?[...t,a.id]:t}export{c as a,b,g as c,u as f,s as g,m as t};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as n,j as e,cx as v,bl as j}from"./vendor-DHkYh85p.js";import{Z as i}from"./index-CF4J4R9L.js";function k({label:u,value:o,options:d,onChange:f,className:p,triggerClassName:w,menuClassName:g}){const[a,c]=n.useState(!1),m=n.useRef(null),h=n.useRef(null),b=n.useId(),r=n.useMemo(()=>d.find(t=>t.value===o)??d[0],[d,o]);return n.useEffect(()=>{if(!a)return;const t=x=>{var l;(l=m.current)!=null&&l.contains(x.target)||c(!1)},s=x=>{var l;x.key==="Escape"&&(c(!1),(l=h.current)==null||l.focus())};return document.addEventListener("pointerdown",t),document.addEventListener("keydown",s),()=>{document.removeEventListener("pointerdown",t),document.removeEventListener("keydown",s)}},[a]),e.jsxs("div",{className:i("relative",p),ref:m,children:[e.jsx("div",{className:"mb-1.5 text-[11px] font-medium uppercase tracking-[0.18em] text-white/42",children:u}),e.jsxs("button",{ref:h,type:"button",className:i("flex min-h-11 w-full min-w-[15rem] items-center justify-between gap-3 rounded-[18px] border border-white/8 bg-[linear-gradient(180deg,rgba(255,255,255,0.08),rgba(255,255,255,0.03))] px-4 py-2.5 text-left shadow-[0_16px_32px_rgba(15,23,42,0.18)] transition hover:border-white/14 hover:bg-[linear-gradient(180deg,rgba(255,255,255,0.11),rgba(255,255,255,0.05))] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[rgba(192,193,255,0.45)]",w),"aria-haspopup":"listbox","aria-expanded":a,"aria-controls":b,onClick:()=>c(t=>!t),children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-white",children:(r==null?void 0:r.label)??o}),r!=null&&r.description?e.jsx("div",{className:"truncate text-xs text-white/48",children:r.description}):null]}),e.jsx(v,{className:i("size-4 shrink-0 text-white/48 transition",a&&"rotate-180 text-white/72")})]}),a?e.jsx("div",{id:b,role:"listbox","aria-label":u,className:i("absolute left-0 top-[calc(100%+0.6rem)] z-30 w-full overflow-hidden rounded-[22px] border border-white/8 bg-[linear-gradient(180deg,rgba(20,28,42,0.98),rgba(12,17,30,0.98))] p-2 shadow-[0_28px_64px_rgba(3,8,18,0.42)] backdrop-blur-xl",g),children:e.jsx("div",{className:"grid gap-1",children:d.map(t=>{const s=t.value===o;return e.jsxs("button",{type:"button",role:"option","aria-selected":s,className:i("flex w-full items-start justify-between gap-3 rounded-[16px] px-3 py-2.5 text-left transition",s?"bg-[rgba(192,193,255,0.14)] text-white":"text-white/74 hover:bg-white/[0.06] hover:text-white"),onClick:()=>{f(t.value),c(!1)},children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-sm font-medium",children:t.label}),t.description?e.jsx("div",{className:"mt-0.5 text-xs text-white/44",children:t.description}):null]}),e.jsx(j,{className:i("mt-0.5 size-4 shrink-0 transition",s?"text-white":"opacity-0")})]},t.value)})})}):null]})}export{k as S};
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import{j as e,cb as Me,df as Ee,aN as ur,bn as be,r as l,dh as pr,bF as Re,ce as mr,d6 as Pe,c2 as fr,cY as xr,c7 as vr,aV as Te}from"./vendor-DHkYh85p.js";import{j as ar,k as Q,i as Ue}from"./state-B-4sS1xO.js";import{C as Ge,dY as br,dZ as Qe,d_ as wr,d$ as yr,dj as He,e0 as Cr,F as D,j as jr,I as B,c as b,B as k,aq as Fr,n as De,Q as $e,a9 as Nr,e1 as Sr,e2 as kr,e3 as Ur,e4 as Ir,e5 as Mr,e6 as Er,e7 as Or,e8 as Ar,e9 as Lr,S as Rr,E as Ye,i as Gr,dx as Dr,b$ as _r,ea as Pr,eb as zr,ec as Tr}from"./index-CF4J4R9L.js";import{S as $r}from"./settings-section-nav-DSOuht_F.js";import{P as qr}from"./page-hero-DRy5b2MU.js";import{r as Vr,b as Kr,w as Wr}from"./calendar-display-preferences-Cid-2RnL.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";const Xe=[{title:"Before you connect anything",description:"Forge mirrors provider events into Forge. Writable providers can also publish work blocks plus owned timeboxes into one shared Forge write target, while Exchange Online stays read-only for now.",bullets:["Google uses a localhost Authorization Code + PKCE flow. Each user signs in with their own Google account on the same machine running Forge, while Forge stores that user's refresh token on the server for background sync.","Calendars On This Mac uses EventKit to access the calendars already configured in Calendar.app on the host machine, including iCloud, Google, Exchange, and other accounts the Mac is already syncing.","Apple Calendar starts from https://caldav.icloud.com and autodiscovers the real principal plus calendar collections for you.","Exchange Online uses Microsoft Graph with a guided local public-client Microsoft sign-in flow and mirrors the calendars you select into Forge.","Custom CalDAV uses one account-level base URL, then Forge discovers the writable calendars before you choose what to mirror.","Read-only .ics feeds are not enough for writable-provider flows because Forge needs write access for work blocks and task timeboxes."],icon:Me,links:[]},{title:"Calendars On This Mac setup",description:"Use this path when the Mac already has the needed accounts connected in Calendar.app and Forge should sync them through EventKit instead of reconnecting each provider manually.",bullets:["Open Forge on the same Mac whose Calendar.app already contains the accounts you want to mirror.","Choose Calendars On This Mac in Forge settings.","Grant Calendar full access when macOS prompts for it, or re-enable it later in System Settings -> Privacy & Security -> Calendars.","Let Forge discover the available host calendar sources and pick the source account you want to sync.","Choose which calendars Forge should mirror. If Forge already has a write target on another writable connection, this new connection can reuse it instead of creating another Forge calendar.","If Forge already syncs the same account through Google, Apple, CalDAV, or Microsoft, the macOS-local connection replaces the older remote one instead of keeping two visible copies."],icon:Me,links:[]},{title:"Google Calendar setup",description:"Use one Google Cloud desktop-app OAuth client for local Forge, register the exact localhost callback URI, and let Forge complete the Authorization Code + PKCE exchange on the backend.",bullets:["Open Google Cloud credentials and create or reuse one OAuth client for Forge as a Desktop app.","Enable the Calendar API for the same project.","Register Forge's exact callback URI. In local Forge, the default callback is http://127.0.0.1:4317/api/v1/calendar/oauth/google/callback.","Open Forge on localhost on the same machine that is running Forge. If Forge is opened remotely from a phone or a Tailscale route while the callback is localhost, Google will redirect to localhost on that device and the flow will fail.","The user signs in with their own Google account and grants Forge access. They do not create their own Google OAuth client during this step.","Forge will discover the calendars, let you choose which calendars to mirror, and create or reuse Forge as the write calendar."],icon:Ee,links:[{label:"Google Cloud credentials",href:"https://console.cloud.google.com/apis/credentials"},{label:"Calendar API quickstart",href:"https://developers.google.com/workspace/calendar/api/quickstart"}]},{title:"Apple Calendar setup",description:"Apple does not require you to paste raw calendar collection URLs into Forge. Start with your Apple ID email, an app-specific password, and the iCloud CalDAV base URL.",bullets:["Create an Apple app-specific password for third-party calendar access.","Open Forge settings and choose Apple Calendar.","Enter the Apple ID email and the app-specific password. Forge uses https://caldav.icloud.com for autodiscovery.","After discovery, choose which calendars Forge should mirror.","If a calendar named Forge already exists, Forge will preselect it as the write calendar. Otherwise you can ask Forge to create it for you."],icon:ur,links:[{label:"Apple app-specific passwords",href:"https://support.apple.com/en-us/102654"},{label:"Use iCloud Calendar with third-party apps",href:"https://support.apple.com/guide/icloud/set-up-calendar-mmfc0f2442/icloud"}]},{title:"Exchange Online setup",description:"Use Microsoft Graph for Microsoft 365 or Exchange Online calendars. In self-hosted local Forge, the user first saves a Microsoft public client ID, tenant, and redirect URI in Settings -> Calendar, then completes a guided local sign-in flow with PKCE. The connection is still read-only in Forge today.",bullets:["Open Microsoft Entra App registrations and create or reuse an app for this local Forge instance.","Choose a supported account type that matches your self-hosted use case. Use a broad multi-account setup when Forge should work with normal personal or organizational Microsoft sign-ins.","Enable mobile and desktop or public client flow support for that app registration.","Add Forge's callback URI to the redirect URI list. The default local callback is http://127.0.0.1:4317/api/v1/calendar/oauth/microsoft/callback.","Add delegated Graph permissions for User.Read and Calendars.Read, then grant or request consent as required by the tenant.","Open Forge Settings -> Calendar and save the Microsoft client ID, tenant value, and redirect URI in the Exchange Online setup card.","Use Test Microsoft configuration to confirm Forge can launch the local sign-in flow.","Click Sign in with Microsoft, complete the popup flow, and then choose which Exchange Online calendars Forge should mirror."],icon:Ee,links:[{label:"Microsoft Graph permissions",href:"https://learn.microsoft.com/en-us/graph/permissions-reference"},{label:"Microsoft identity platform",href:"https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-auth-code-flow"},{label:"Microsoft Graph calendar overview",href:"https://learn.microsoft.com/en-us/graph/api/resources/calendar?view=graph-rest-1.0"}]},{title:"Custom CalDAV setup",description:"Use this path for Nextcloud, Fastmail, Baikal, DAViCal, and other CalDAV-compatible providers that expose an account-level base URL.",bullets:["Confirm the provider supports CalDAV, not just an .ics export.","Gather the account-level CalDAV server URL, username, and password or app password.","Open Forge settings and choose Custom CalDAV.","Forge discovers the available calendars from that base URL before anything is saved.","Choose which calendars to mirror and either select an existing Forge calendar or let Forge create one automatically."],icon:Me,links:[]}];function Br(t){if(!t)return Xe;const c=t==="google"?"Google Calendar setup":t==="macos_local"?"Calendars On This Mac setup":t==="apple"?"Apple Calendar setup":t==="microsoft"?"Exchange Online setup":"Custom CalDAV setup";return Xe.filter(p=>p.title==="Before you connect anything"||p.title===c)}function Qr({section:t,compact:c}){const p=t.icon;return e.jsxs(Ge,{className:c?"grid gap-3 rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(18,28,38,0.98),rgba(11,17,28,0.98))] p-4":"grid gap-4 rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(18,28,38,0.98),rgba(11,17,28,0.98))]",children:[e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:"rounded-[18px] bg-[var(--primary)]/14 p-3 text-[var(--primary)]",children:e.jsx(p,{className:c?"size-4":"size-5"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:c?"font-medium text-white":"font-display text-[1.15rem] text-white",children:t.title}),e.jsx("p",{className:c?"mt-1.5 text-sm leading-6 text-white/62":"mt-2 max-w-3xl text-sm leading-6 text-white/62",children:t.description})]})]}),e.jsx("div",{className:c?"grid gap-1.5":"grid gap-2",children:t.bullets.map(w=>e.jsx("div",{className:c?"rounded-[16px] bg-white/[0.04] px-3 py-2.5 text-sm leading-6 text-white/70":"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/72",children:w},w))}),t.links.length>0?e.jsx("div",{className:"flex flex-wrap gap-2",children:t.links.map(w=>e.jsxs("a",{href:w.href,target:"_blank",rel:"noreferrer",className:"inline-flex min-h-10 items-center gap-2 rounded-full border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white/74 transition hover:bg-white/[0.08] hover:text-white",children:[e.jsx(be,{className:"size-3.5"}),w.label]},w.href))}):null]})}function Hr({provider:t,compact:c=!1}){const p=Br(t);return e.jsx("div",{className:"grid gap-4",children:p.map(w=>e.jsx(Qr,{section:w,compact:c},w.title))})}const Ze="/api/v1/calendar/oauth/microsoft/callback",Yr=/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/,Je=1e3,_e={google:{label:"Primary Google",serverUrl:""},apple:{label:"Primary Apple",serverUrl:"https://caldav.icloud.com"},microsoft:{label:"Primary Exchange Online",serverUrl:""},macos_local:{label:"Calendars On This Mac",serverUrl:"forge-macos-local://eventkit/"},caldav:{label:"Primary CalDAV",serverUrl:"https://caldav.example.com"}};function ze(t){return{provider:t,label:_e[t].label,serverUrl:_e[t].serverUrl,username:"",password:"",selectedCalendarUrls:[],forgeCalendarUrl:null,createForgeCalendar:!1,sourceId:null,replaceConnectionIds:[]}}function oe(t,c){const p=c.trim();return p.length>0?p:_e[t].label}function Le(t){return{clientId:t.clientId,tenantId:t.tenantId,redirectUri:t.redirectUri}}function Ie(t){return{clientId:t.storedClientId??"",clientSecret:t.storedClientSecret??""}}function Xr(t){return t.replace(/\s*No GOOGLE_CLIENT_SECRET is used in this local PKCE flow\./gi,"").replace(/\s{2,}/g," ").trim()}function er(){return["Google OAuth credentials are not set for this Forge install.","- Save a Google desktop-app client ID and client secret below for this Forge install.","- Or rely on the packaged or environment defaults for the Forge runtime."].join(`
|
|
2
|
-
`)}function rr(t,c){return[t,"- Open Forge from a local browser on the host running Forge.",`- Use one of these local addresses: ${c.join(", ")}.`].join(`
|
|
3
|
-
`)}function nr(t){return{clientId:(t.clientId??"").trim(),clientSecret:(t.clientSecret??"").trim()}}function Zr(t,c){return t.clientId.trim()===c.clientId.trim()&&t.clientSecret.trim()===c.clientSecret.trim()}function Jr(t){const c=nr(t),p={},w=c.clientId.length>0,A=c.clientSecret.length>0;if(w!==A){const q="When overriding Google OAuth credentials, save the client ID and client secret together, or clear both to use the bundled defaults.";w||(p.clientId=q),A||(p.clientSecret=q)}return{normalized:c,issues:p,isValid:Object.keys(p).length===0}}function qe(t){return{clientId:t.clientId.trim(),tenantId:t.tenantId.trim()||"common",redirectUri:t.redirectUri.trim()}}function et(t){const c=qe(t),p={};if(c.clientId?Yr.test(c.clientId)||(p.clientId="Use the Microsoft app registration client ID GUID."):p.clientId="Microsoft client ID is required.",!c.redirectUri)p.redirectUri="Redirect URI is required.";else try{const w=new URL(c.redirectUri);w.protocol!=="http:"&&w.protocol!=="https:"?p.redirectUri="Redirect URI must use http or https.":w.pathname!==Ze&&(p.redirectUri=`Redirect URI must end with ${Ze}.`)}catch{p.redirectUri="Redirect URI must be a full URL."}return{normalized:c,issues:p,isValid:Object.keys(p).length===0}}function rt(t,c){return t.clientId.trim()===c.clientId.trim()&&t.tenantId.trim()===c.tenantId.trim()&&t.redirectUri.trim()===c.redirectUri.trim()}function Ve(t){return t==="127.0.0.1"||t==="localhost"}function tt(t){return t.endsWith(".ts.net")}function st(t){t.allowedOrigins.filter(w=>{try{return Ve(new URL(w).hostname)}catch{return!1}});const c=(()=>{try{return new URL(t.redirectUri).hostname}catch{return""}})();let p="";try{p=new URL(t.currentOrigin).hostname}catch{p=""}return tt(p)&&Ve(c)?`Google sign-in has to start from a local browser on the host running Forge. Forge is currently open through Tailscale at ${t.currentOrigin}, but Google sends the callback to localhost on the device that opens the popup. On a phone or another computer, that callback goes to that device instead of the Forge host.`:t.isLocalOnly?"Google sign-in has to start from a local browser on the host running Forge. Google sends the callback to localhost, so if Forge is opened remotely, the callback goes to the other device instead of the Forge host.":`Google sign-in is only enabled from the configured Forge host for this deployment. Open Forge on ${t.appBaseUrl}. Current browser origin: ${t.currentOrigin}.`}function at({open:t,onOpenChange:c,initialProvider:p="google",initialStepId:w,googleSetup:A,microsoftSetup:q,onCalendarSettingsChanged:H,existingConnections:ge=[],onSubmit:Y,pending:N=!1}){const we=ar(),[n,V]=l.useState(()=>ze(p)),[ye,m]=l.useState(null),[v,_]=l.useState(null),[U,ae]=l.useState("not_determined"),[C,P]=l.useState(null),[g,y]=l.useState(null),[u,X]=l.useState(null),[h,ue]=l.useState(A),[I,K]=l.useState(()=>Ie(A)),[z,le]=l.useState(()=>Ie(A)),[Oe,ne]=l.useState(!1),[Z,F]=l.useState(null),[T,pe]=l.useState(q),[S,ce]=l.useState(()=>Le(q)),[Ce,ie]=l.useState(()=>Le(q)),[me,L]=l.useState(null),M=l.useRef(null),fe=(r=[])=>{const a=new Set(r);return ge.find(i=>{var o;return a.has(i.id)?!1:typeof((o=i.config)==null?void 0:o.forgeCalendarUrl)=="string"&&i.config.forgeCalendarUrl.trim().length>0})??null},R=l.useMemo(()=>n.provider==="microsoft"?null:fe(n.replaceConnectionIds),[n.provider,n.replaceConnectionIds,ge]),E=R?R.accountLabel&&R.accountLabel.trim().length>0?`${R.label} · ${R.accountLabel}`:R.label:null,je=r=>(we.setQueryData(["forge-settings"],r),r.settings),s=()=>{y(null),M.current=null},d=()=>{X(null),M.current=null},f=r=>{_(r);const a=r.calendars.filter(o=>o.selectedByDefault).map(o=>o.url),i=r.calendars.find(o=>o.isForgeCandidate);V(o=>{const j=fe(o.replaceConnectionIds);return{...o,selectedCalendarUrls:o.selectedCalendarUrls.length>0?o.selectedCalendarUrls.filter(se=>r.calendars.some(Ne=>Ne.url===se)):a,forgeCalendarUrl:o.provider==="microsoft"||j?null:(i==null?void 0:i.url)??o.forgeCalendarUrl??null,createForgeCalendar:o.provider==="microsoft"||j?!1:o.createForgeCalendar&&!i}}),m(null)};l.useEffect(()=>{var r;if(!t){(r=M.current)==null||r.close(),M.current=null;return}m(null),_(null),V(ze(p)),s(),d(),P(null),ae("not_determined"),ne(!1),F(null),L(null)},[p,t]),l.useEffect(()=>{!t||n.provider!=="macos_local"||G.mutateAsync()},[n.provider,t]),l.useEffect(()=>{if(!t||!v||n.provider==="microsoft"||R||n.forgeCalendarUrl||n.createForgeCalendar)return;const r=v.calendars.find(a=>a.isForgeCandidate);r&&V(a=>a.provider==="microsoft"||a.forgeCalendarUrl||a.createForgeCalendar||fe(a.replaceConnectionIds)?a:{...a,forgeCalendarUrl:r.url})},[v,n.createForgeCalendar,n.forgeCalendarUrl,n.provider,t,R]),l.useEffect(()=>{if(!t)return;ue(A);const r=Ie(A);K(r),le(r),ne(!1),F(null)},[A,t]),l.useEffect(()=>{if(!t)return;pe(q);const r=Le(q);ce(r),ie(r),L(null)},[q,t]),l.useEffect(()=>{if(!t||!g||g.status!=="pending")return;const r=new URL(h.redirectUri).origin;let a=!1;const i=()=>{a||(a=!0,cr(g.sessionId).finally(()=>{a=!1}))},o=he=>{var Se,ke;he.origin===r&&(((Se=he.data)==null?void 0:Se.type)!=="forge:google-calendar-auth"||((ke=he.data)==null?void 0:ke.sessionId)!==g.sessionId||i())},j=()=>{i()},se=()=>{document.visibilityState==="visible"&&i()},Ne=window.setInterval(i,Je);return window.addEventListener("message",o),window.addEventListener("focus",j),document.addEventListener("visibilitychange",se),()=>{window.removeEventListener("message",o),window.removeEventListener("focus",j),document.removeEventListener("visibilitychange",se),window.clearInterval(Ne)}},[h.redirectUri,g,t]),l.useEffect(()=>{if(!t||!u||u.status!=="pending")return;const r=new URL(T.redirectUri).origin;let a=!1;const i=()=>{a||(a=!0,dr(u.sessionId).finally(()=>{a=!1}))},o=he=>{var Se,ke;he.origin===r&&(((Se=he.data)==null?void 0:Se.type)!=="forge:microsoft-calendar-auth"||((ke=he.data)==null?void 0:ke.sessionId)!==u.sessionId||i())},j=()=>{i()},se=()=>{document.visibilityState==="visible"&&i()},Ne=window.setInterval(i,Je);return window.addEventListener("message",o),window.addEventListener("focus",j),document.addEventListener("visibilitychange",se),()=>{window.removeEventListener("message",o),window.removeEventListener("focus",j),document.removeEventListener("visibilitychange",se),window.clearInterval(Ne)}},[T.redirectUri,u,t]);const x=Q({mutationFn:()=>n.provider==="macos_local"?br().then(({discovery:r})=>{P(r),ae(r.status);const a=r.sources.find(i=>i.sourceId===n.sourceId)??r.sources[0]??null;return a&&(f({provider:"macos_local",accountLabel:a.accountLabel,serverUrl:n.serverUrl,principalUrl:null,homeUrl:null,calendars:a.calendars}),V(i=>({...i,sourceId:a.sourceId}))),{discovery:null}}):n.provider==="apple"?Qe({provider:"apple",username:n.username,password:n.password}):Qe({provider:"caldav",serverUrl:n.serverUrl,username:n.username,password:n.password}),onSuccess:({discovery:r})=>{r&&f(r)},onError:r=>{_(null),m(r instanceof Error?r.message:"Forge could not discover calendars with these credentials.")}}),G=Q({mutationFn:wr,onSuccess:({status:r})=>{ae(r),r!=="full_access"&&(P(null),_(null))}}),J=Q({mutationFn:yr,onSuccess:({granted:r,status:a,message:i})=>{if(ae(a),r){m(null);return}m(i??"Forge could not obtain Calendar access from macOS yet. Open System Settings > Privacy & Security > Calendars, allow Forge, then return here and click Check access.")},onError:r=>{m(r instanceof Error?r.message:"Forge could not request Calendar access from macOS.")}});l.useEffect(()=>{!t||n.provider!=="macos_local"||U!=="full_access"||C!==null||x.isPending||x.mutateAsync()},[x,n.provider,C,U,t]);const ee=Q({mutationFn:async r=>{const a=qe(r),i=await He({calendarProviders:{microsoft:a}});return{normalized:a,settings:je(i)}},onSuccess:async({settings:r})=>{pe(r.calendarProviders.microsoft);const a=Le(r.calendarProviders.microsoft);ie(a),ce(a),L("Microsoft settings saved. Start the guided Microsoft sign-in when you are ready."),H==null||H()},onError:r=>{L(r instanceof Error?r.message:"Forge could not save the Microsoft settings.")}}),$=Q({mutationFn:async r=>{const a=nr(r),i=await He({calendarProviders:{google:a}});return{normalized:a,settings:je(i)}},onSuccess:async({normalized:r,settings:a})=>{ue(a.calendarProviders.google);const i=Ie(a.calendarProviders.google);le(i),K(i),ne(!1),F(r.clientId||r.clientSecret?"Google OAuth credentials saved on the Forge server for this install.":"Google OAuth override cleared. Forge will use the packaged or environment default again."),H==null||H()},onError:r=>{F(r instanceof Error?r.message:"Forge could not save the Google OAuth credentials.")}}),re=Q({mutationFn:r=>{const a=qe(r);return Cr(a)},onSuccess:({result:r})=>{L(r.message)},onError:r=>{L(r instanceof Error?r.message:"Forge could not validate the Microsoft configuration.")}}),O=l.useMemo(()=>et(S),[S]),W=l.useMemo(()=>Jr(I),[I]),te=!Zr(I,z),xe=!rt(S,Ce),de=typeof window>"u"?"":window.location.origin,Ke=l.useMemo(()=>{try{return new URL(h.redirectUri).origin}catch{return""}},[h.redirectUri]),Ae=de.length>0&&h.allowedOrigins.includes(de)&&(!h.isLocalOnly||Ve(new URL(de).hostname)),Fe=de&&!Ae?st({currentOrigin:de,appBaseUrl:h.appBaseUrl,redirectUri:h.redirectUri,allowedOrigins:h.allowedOrigins,isLocalOnly:h.isLocalOnly}):null,ir=h.isReadyForPairing?null:Xr(h.setupMessage)||er(),or=Fe?rr(Fe,h.allowedOrigins):null,lr=r=>{if(ye)return ye;if(n.provider==="google"&&(r==="credentials"||r==="discovery")){if(te)return"Save the Google OAuth credential change before starting sign-in.";const a=[or,ir].filter(i=>!!i);if(a.length>0)return a.join(`
|
|
4
|
-
|
|
5
|
-
`)}if(n.provider==="microsoft"&&r==="credentials"){if(xe)return"Save these Microsoft settings before starting sign-in.";if(!xe&&!Ce.clientId&&!me)return T.setupMessage}if(n.provider==="macos_local"&&(r==="credentials"||r==="discovery")&&U!=="full_access")return U==="unavailable"?"This provider is only available on macOS, because Forge uses EventKit to access the host machine's calendar store.":"Grant Calendar full access for Forge on this Mac before discovering host calendars."},cr=async(r,a)=>{try{const{session:i}=await Ur(r);if(y(i),i.status==="authorized"&&i.discovery){f(i.discovery),m(null);return}if(i.status==="error"||i.status==="expired"){m(i.error??"Google sign-in did not complete. Start the guided sign-in again.");return}a!=null&&a.afterPopupClose}catch(i){m(i instanceof Error?i.message:"Forge could not confirm the Google sign-in session.")}},dr=async(r,a)=>{try{const{session:i}=await Ir(r);if(X(i),i.status==="authorized"&&i.discovery){f(i.discovery),m(null);return}if(i.status==="error"||i.status==="expired"){m(i.error??"Microsoft sign-in did not complete. Start the guided sign-in again.");return}a!=null&&a.afterPopupClose}catch(i){m(i instanceof Error?i.message:"Forge could not confirm the Microsoft sign-in session.")}},We=async()=>{var r;try{if(Fe)throw new Error(rr(Fe,h.allowedOrigins));if(!h.isReadyForPairing)throw new Error(er());m(null),_(null);const{session:a}=await Sr({label:oe("google",n.label),browserOrigin:de||void 0});if(!a.authUrl)throw new Error("Forge could not prepare the Google sign-in URL.");if(y(a),(r=M.current)==null||r.close(),M.current=window.open(a.authUrl,"forge-google-calendar-auth","popup=yes,width=520,height=720,resizable=yes,scrollbars=yes"),!M.current)throw new Error("The Google sign-in popup was blocked. Allow popups for Forge and try again.");M.current.focus()}catch(a){s(),m(a instanceof Error?a.message:"Forge could not start the Google sign-in flow.")}},Be=async()=>{var r;try{if(!O.isValid)throw new Error("Enter a valid Microsoft client ID and redirect URI before starting sign-in.");if(xe)throw new Error("Save the Microsoft settings in this guided flow before starting sign-in.");if(ee.isPending)throw new Error("Wait for Forge to finish saving the Microsoft settings before starting sign-in.");m(null),L(null),_(null);const{session:a}=await kr({label:oe("microsoft",n.label)});if(!a.authUrl)throw new Error("Forge could not prepare the Microsoft sign-in URL.");if(X(a),(r=M.current)==null||r.close(),M.current=window.open(a.authUrl,"forge-microsoft-calendar-auth","popup=yes,width=520,height=720,resizable=yes,scrollbars=yes"),!M.current)throw new Error("The Microsoft sign-in popup was blocked. Allow popups for Forge and try again.");M.current.focus()}catch(a){d(),m(a instanceof Error?a.message:"Forge could not start the Microsoft sign-in flow.")}},hr=l.useMemo(()=>[{id:"provider",eyebrow:"Connection",title:"Choose the calendar provider Forge should connect to",description:"macOS local uses EventKit to access the calendars already configured on this Mac, Apple uses autodiscovery from caldav.icloud.com, Google uses a localhost Authorization Code + PKCE flow, Exchange Online uses guided Microsoft sign-in in read-only mode, and custom CalDAV stays available for everything else.",render:(r,a)=>e.jsxs("div",{className:"grid gap-5",children:[e.jsx(D,{label:"Provider",description:"Each setup path is guided. Forge discovers calendars before anything is saved.",children:e.jsx(jr,{value:r.provider,onChange:i=>{_(null),P(null),m(null),L(null),s(),d(),a(ze(i))},options:[{value:"google",label:"Google Calendar",description:"Use Google sign-in with Authorization Code + PKCE, let Forge exchange the code on the backend, and store a per-user refresh token server-side."},{value:"apple",label:"Apple Calendar",description:"Start from https://caldav.icloud.com and autodiscover calendars with your app password."},{value:"microsoft",label:"Exchange Online",description:"Save the Microsoft app registration fields in Settings, then sign in with Microsoft and mirror selected Exchange Online calendars in read-only mode."},{value:"macos_local",label:"Calendars On This Mac",description:"Use EventKit to access the calendars already configured in Calendar.app on this host machine and avoid reconnecting those same accounts manually."},{value:"caldav",label:"Custom CalDAV",description:"Use a CalDAV base URL for Nextcloud, Fastmail, Baikal, and other compatible providers."}]})}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center gap-3 text-white",children:[e.jsx(pr,{className:"size-4 text-[var(--primary)]"}),e.jsx("div",{className:"font-medium",children:"Dedicated write calendar"})]}),e.jsx("p",{className:"mt-3 text-sm leading-6 text-white/60",children:r.provider==="microsoft"?"Exchange Online is read-only for now. Forge mirrors selected calendars into Forge, but it does not publish work blocks or owned timeboxes back to Microsoft.":e.jsxs(e.Fragment,{children:["Forge writes work blocks and owned timeboxes into a dedicated calendar named"," ",e.jsx("span",{className:"font-medium text-white",children:"Forge"}),"."]})})]}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-center gap-3 text-white",children:[e.jsx(Ee,{className:"size-4 text-[var(--primary)]"}),e.jsx("div",{className:"font-medium",children:"Discovery first"})]}),e.jsx("p",{className:"mt-3 text-sm leading-6 text-white/60",children:r.provider==="google"?"Forge opens a Google sign-in popup, exchanges the authorization code on the backend, stores a per-user refresh token, and then discovers the writable calendars for that account.":r.provider==="macos_local"?"Forge asks macOS for Calendar access, discovers the host calendars grouped by account source, and replaces overlapping remote connections instead of keeping two copies.":r.provider==="microsoft"?"Forge starts a Microsoft sign-in popup, then discovers the calendars available to that account before you choose what to mirror.":"Forge discovers the actual calendar collections before you choose which ones to mirror and which one should receive owned timeboxes."})]})]}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.03] p-4",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Setup guide"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"These are the exact setup steps for the selected provider. They stay inside this guided flow so Settings can stay focused on connection health and actions."}),e.jsx("div",{className:"mt-4",children:e.jsx(Hr,{provider:r.provider,compact:!0})})]})]})},{id:"credentials",eyebrow:"Credentials",title:n.provider==="google"?"Sign in with Google":n.provider==="macos_local"?"Use the calendars already configured on this Mac":n.provider==="apple"?"Provide the Apple account email and app-specific password":n.provider==="microsoft"?"Sign in with Microsoft":"Provide the custom CalDAV base URL and credentials",description:n.provider==="google"?"Review the Google desktop OAuth client, save a local override only if you need one, then start the popup and let Forge finish the PKCE exchange on the backend.":n.provider==="macos_local"?"Forge requests Calendar access through EventKit, discovers sources from Calendar.app, then lets you choose which host calendars to mirror and where Forge should write.":n.provider==="apple"?"Apple discovery starts from https://caldav.icloud.com, so you only need the Apple ID email and app password here.":n.provider==="microsoft"?"Forge uses the Microsoft client ID, tenant, and redirect URI saved in Settings -> Calendar, then runs a guided popup sign-in.":"Forge stores the secrets securely, then discovers the available calendars before anything is saved.",render:(r,a)=>{var i;return e.jsxs("div",{className:"grid gap-4",children:[e.jsx(D,{label:"Connection label",description:"This is the readable label Forge shows in settings and the calendar health cards.",children:e.jsx(B,{value:r.label,onChange:o=>a({label:o.target.value}),placeholder:_e[r.provider].label})}),r.provider==="macos_local"?e.jsx("div",{className:"grid gap-4",children:e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(20,32,48,0.98),rgba(11,18,30,0.98))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"macOS Calendar access"}),e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-6 text-white/60",children:"Forge uses EventKit to read and write the calendars already configured in Calendar.app on this Mac. Grant Calendar full access, then discover the available account sources."})]}),e.jsx(b,{className:U==="full_access"?"bg-emerald-500/16 text-emerald-100":"bg-white/[0.08] text-white/72",children:U==="full_access"?"Full access":U.replaceAll("_"," ")})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-3",children:[e.jsxs(k,{type:"button",onClick:()=>void J.mutateAsync(),pending:J.isPending,pendingLabel:"Waiting for macOS",children:[e.jsx(Ee,{className:"size-4"}),"Request Calendar access"]}),e.jsxs(k,{type:"button",variant:"secondary",onClick:()=>void G.mutateAsync(),pending:G.isPending,pendingLabel:"Checking",children:[e.jsx(Re,{className:"size-4"}),"Check access"]}),e.jsxs(k,{type:"button",onClick:()=>void x.mutateAsync(),disabled:U!=="full_access",pending:x.isPending,pendingLabel:"Discovering",children:[e.jsx(Re,{className:"size-4"}),"Discover host calendars"]})]}),(i=C==null?void 0:C.sources)!=null&&i.length?e.jsxs("div",{className:"mt-5 grid gap-3",children:[e.jsx("div",{className:"text-sm font-medium text-white",children:"Host calendar sources"}),C.sources.map(o=>{const j=r.sourceId===o.sourceId;return e.jsxs("button",{type:"button",className:`rounded-[20px] border px-4 py-3 text-left transition ${j?"border-[var(--primary)]/40 bg-[var(--primary)]/12 text-white":"border-white/8 bg-white/[0.04] text-white/72 hover:bg-white/[0.07]"}`,onClick:()=>{a({sourceId:o.sourceId}),f({provider:"macos_local",accountLabel:o.accountLabel,serverUrl:r.serverUrl,principalUrl:null,homeUrl:null,calendars:o.calendars})},children:[e.jsx("div",{className:"font-medium",children:o.accountLabel||o.sourceTitle}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[o.sourceType," · ",o.calendars.length," ","calendars"]})]},o.sourceId)})]}):null]})}):r.provider==="google"?e.jsx("div",{className:"grid gap-4",children:e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(20,32,48,0.98),rgba(11,18,30,0.98))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"How Google sign-in works"}),e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-6 text-white/60",children:"Start the popup from the host running Forge. Google returns to Forge on localhost, Forge completes the PKCE exchange on the backend, then Forge discovers the calendars for that account."})]}),e.jsx(b,{className:"bg-emerald-500/16 text-emerald-100",children:"Auth code + PKCE"})]}),e.jsxs("div",{className:"mt-4 rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/68",children:[e.jsxs("div",{children:["Forge runtime:"," ",e.jsx("span",{className:"font-medium text-white",children:h.appBaseUrl})]}),e.jsxs("div",{className:"break-all",children:["Redirect URI:"," ",e.jsx("span",{className:"font-medium text-white",children:h.redirectUri})]}),e.jsxs("div",{className:"break-all",children:["Redirect origin:"," ",e.jsx("span",{className:"font-medium text-white",children:Ke||"Unavailable"})]}),e.jsxs("div",{children:["Allowed local browser origins:"," ",e.jsx("span",{className:"font-medium text-white",children:h.allowedOrigins.join(", ")})]}),e.jsxs("div",{className:"break-all",children:["Detected browser origin:"," ",e.jsx("span",{className:"font-medium text-white",children:de||"Unavailable"})]})]}),e.jsx("div",{className:"mt-4 rounded-[18px] bg-white/[0.04] p-4",children:Oe?e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"Google OAuth override"}),e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-6 text-white/60",children:"Save both the client ID and client secret only when this Forge install should use a different Google desktop OAuth app than the packaged default."})]}),e.jsx("button",{type:"button","aria-label":"Done editing Google OAuth client",className:"inline-flex size-9 shrink-0 items-center justify-center rounded-full border border-white/10 bg-white/[0.06] text-white/72 transition hover:bg-white/[0.12] hover:text-white",onClick:()=>{F(null);const o=Ie(h);K(o),ne(!1)},children:e.jsx(Pe,{className:"size-4"})})]}),e.jsxs(D,{label:"Client ID",description:"Override the packaged Google desktop-app client ID for this Forge install.",children:[e.jsx(B,{"aria-label":"Client ID",value:I.clientId,onChange:o=>{F(null),K({...I,clientId:o.target.value})},placeholder:"1234567890-abcdef.apps.googleusercontent.com"}),W.issues.clientId?e.jsx("p",{className:"mt-2 text-sm text-rose-200",children:W.issues.clientId}):null]}),e.jsxs(D,{label:"Client secret",description:"Override the packaged Google desktop-app client secret for this Forge install.",children:[e.jsx(B,{"aria-label":"Client secret",value:I.clientSecret,onChange:o=>{F(null),K({...I,clientSecret:o.target.value})},placeholder:"GOCSPX-..."}),W.issues.clientSecret?e.jsx("p",{className:"mt-2 text-sm text-rose-200",children:W.issues.clientSecret}):null]}),e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx(k,{type:"button",onClick:()=>void $.mutateAsync(I),disabled:!te||!W.isValid,pending:$.isPending,pendingLabel:"Saving",children:"Save Google OAuth override"}),e.jsx(k,{type:"button",variant:"secondary",onClick:()=>{F(null),K({clientId:"",clientSecret:""})},disabled:$.isPending||!z.clientId&&!z.clientSecret&&I.clientId.length===0&&I.clientSecret.length===0,children:z.clientId||z.clientSecret?"Clear override":"Use packaged default"})]})]}):e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"grid min-w-0 gap-3",children:e.jsxs("div",{className:"flex min-w-0 items-center justify-between gap-3",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsxs("div",{className:"flex min-w-0 items-center gap-2",children:[e.jsx("span",{className:"truncate font-medium text-white",children:"Google OAuth client"}),e.jsx(b,{className:h.storedClientId||h.storedClientSecret?"bg-emerald-500/16 text-emerald-100":"bg-white/[0.08] text-white/72",children:h.storedClientId||h.storedClientSecret?"Stored on server":"Using packaged default"}),e.jsx(Fr,{content:"Forge ships with a packaged Google desktop OAuth client by default. Save both fields only when this Forge install should use a different client ID and client secret pair.",label:"Explain Google OAuth client",className:"shrink-0"})]})}),e.jsx("button",{type:"button","aria-label":"Edit Google OAuth client",className:"inline-flex size-9 shrink-0 items-center justify-center rounded-full border border-white/10 bg-white/[0.06] text-white/72 transition hover:bg-white/[0.12] hover:text-white",onClick:()=>{F(null),ne(!0)},children:e.jsx(mr,{className:"size-4"})})]})}),e.jsx(D,{label:"Effective client ID",description:"This is the Google desktop-app client ID Forge will use right now.",children:e.jsx("div",{className:"flex min-h-11 min-w-0 items-center overflow-hidden rounded-[18px] border border-white/8 bg-black/20 px-4 text-sm text-white/38",children:e.jsx("span",{className:"block min-w-0 truncate",title:h.clientId,children:h.clientId})})}),e.jsx(D,{label:"Effective client secret",description:"Forge uses this value on the local backend when exchanging and refreshing Google tokens.",children:e.jsx("div",{className:"flex min-h-11 min-w-0 items-center overflow-hidden rounded-[18px] border border-white/8 bg-black/20 px-4 text-sm text-white/38",children:e.jsx("span",{className:"block min-w-0 truncate",title:h.clientSecret||"",children:h.clientSecret||""})})})]})}),Z?e.jsx("div",{className:"mt-4 rounded-[18px] border border-white/10 bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/72",children:Z}):null,e.jsx("div",{className:"mt-4 rounded-[18px] border border-sky-400/20 bg-sky-400/10 px-4 py-3 text-sm leading-6 text-sky-50",children:"If you open Forge on a phone or another remote route, Google redirects to localhost on that other device instead of back to Forge."}),e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-3",children:[e.jsxs(k,{type:"button",onClick:()=>void We(),disabled:!h.isReadyForPairing||!Ae||te||$.isPending,pending:(g==null?void 0:g.status)==="pending",pendingLabel:"Waiting for Google",children:[e.jsx(be,{className:"size-4"}),(g==null?void 0:g.status)==="authorized"?"Sign in again":"Sign in with Google"]}),g!=null&&g.accountLabel?e.jsxs(b,{className:"bg-emerald-500/16 text-emerald-100",children:[e.jsx(Pe,{className:"mr-1 size-3.5"}),g.accountLabel]}):null]})]})}):r.provider==="microsoft"?e.jsx("div",{className:"grid gap-4",children:e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(20,32,48,0.98),rgba(11,18,30,0.98))] p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"Guided Microsoft setup"}),e.jsx("p",{className:"mt-2 max-w-2xl text-sm leading-6 text-white/60",children:"Save the Microsoft app registration details for this Forge instance here, optionally test them, then continue into the Microsoft sign-in popup. Exchange Online stays read-only for now."})]}),e.jsx(b,{className:"bg-sky-400/12 text-sky-100",children:"Read only"})]}),e.jsxs("div",{className:"mt-4 grid gap-4 md:grid-cols-2",children:[e.jsxs(D,{label:"Microsoft client ID",description:"Use the Application (client) ID from the Microsoft Entra app registration for this Forge instance.",children:[e.jsx(B,{value:S.clientId,onChange:o=>{L(null),ce(j=>({...j,clientId:o.target.value}))},placeholder:"00000000-0000-0000-0000-000000000000"}),O.issues.clientId?e.jsx("div",{className:"text-sm text-rose-300",children:O.issues.clientId}):null]}),e.jsx(D,{label:"Tenant / authority",description:"Use common unless you need a tenant-specific authority.",children:e.jsx(B,{value:S.tenantId,onChange:o=>{L(null),ce(j=>({...j,tenantId:o.target.value}))},placeholder:"common"})})]}),e.jsxs(D,{label:"Redirect URI",description:"Register this exact Forge callback URI in the Microsoft app registration.",children:[e.jsx(B,{value:S.redirectUri,onChange:o=>{L(null),ce(j=>({...j,redirectUri:o.target.value}))},placeholder:"http://127.0.0.1:4317/api/v1/calendar/oauth/microsoft/callback"}),O.issues.redirectUri?e.jsx("div",{className:"text-sm text-rose-300",children:O.issues.redirectUri}):null]}),e.jsx("div",{className:"mt-4 rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/68",children:"Forge saves the client ID, tenant, and redirect URI for this local instance, then handles Microsoft sign-in in a popup."}),e.jsxs("div",{className:"mt-4 flex flex-wrap items-center gap-3",children:[e.jsx(k,{type:"button",onClick:()=>void ee.mutateAsync(S),disabled:!O.isValid,pending:ee.isPending,pendingLabel:"Saving",children:"Save Microsoft settings"}),e.jsx(k,{type:"button",variant:"secondary",onClick:()=>void re.mutateAsync(S),disabled:!O.isValid,pending:re.isPending,pendingLabel:"Testing",children:"Test Microsoft configuration"}),e.jsxs(k,{type:"button",onClick:()=>void Be(),disabled:!O.isValid||xe||ee.isPending,pending:(u==null?void 0:u.status)==="pending",pendingLabel:"Waiting for Microsoft",children:[e.jsx(be,{className:"size-4"}),(u==null?void 0:u.status)==="authorized"?"Sign in again":"Sign in with Microsoft"]}),u!=null&&u.accountLabel?e.jsxs(b,{className:"bg-emerald-500/16 text-emerald-100",children:[e.jsx(Pe,{className:"mr-1 size-3.5"}),u.accountLabel]}):null]}),e.jsxs("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/68",children:"Save before sign-in. The Microsoft popup always uses the latest saved client ID, tenant, and redirect URI."}),e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/68",children:"After sign-in, Forge will let you choose which Exchange Online calendars to mirror into the Calendar page."})]}),me?e.jsx("div",{className:"mt-4 rounded-[18px] border border-white/10 bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/72",children:me}):null]})}):e.jsxs(e.Fragment,{children:[r.provider==="caldav"?e.jsx(D,{label:"CalDAV base URL",description:"Use the account-level CalDAV server URL, not an individual calendar collection URL.",children:e.jsx(B,{value:r.serverUrl,onChange:o=>a({serverUrl:o.target.value}),placeholder:"https://caldav.example.com"})}):null,r.provider==="apple"?e.jsx(D,{label:"Apple CalDAV base URL",children:e.jsx(B,{value:"https://caldav.icloud.com",disabled:!0})}):null,e.jsx(D,{label:"Account email or username",children:e.jsx(B,{value:r.username,onChange:o=>a({username:o.target.value}),placeholder:"operator@example.com"})}),e.jsx(D,{label:r.provider==="apple"?"App-specific password":"Password or app password",children:e.jsx(B,{type:"password",value:r.password,onChange:o=>a({password:o.target.value}),placeholder:"Password"})})]})]})}},{id:"discovery",eyebrow:"Discovery",title:"Discover the calendars and choose what Forge should sync",description:n.provider==="microsoft"?"Select the Exchange Online calendars Forge should mirror into the Calendar page. This connection stays read-only for now.":n.provider==="macos_local"?E?`Select the host-machine calendars Forge should mirror into the Calendar page. Forge already writes work blocks and timeboxes through ${E}.`:"Select the host-machine calendars Forge should mirror into the Calendar page, then choose the host calendar Forge should write into for work blocks and timeboxes.":E?`Select the calendars Forge should mirror into the Calendar page. Forge already writes work blocks and timeboxes through ${E}.`:"Select the calendars Forge should mirror into the Calendar page, then choose the calendar Forge should write into for work blocks and timeboxes.",render:(r,a)=>e.jsxs("div",{className:"grid gap-4",children:[r.provider==="google"?e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs(k,{type:"button",onClick:()=>void We(),disabled:!h.isReadyForPairing||!Ae,pending:(g==null?void 0:g.status)==="pending",pendingLabel:"Waiting for Google",children:[e.jsx(be,{className:"size-4"}),(g==null?void 0:g.status)==="authorized"?"Reconnect Google":"Sign in with Google"]}),v?e.jsxs(b,{className:"bg-white/[0.08] text-white/74",children:[v.calendars.length," discovered"]}):null]}):r.provider==="microsoft"?e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs(k,{type:"button",onClick:()=>void Be(),disabled:!O.isValid||xe||ee.isPending,pending:(u==null?void 0:u.status)==="pending",pendingLabel:"Waiting for Microsoft",children:[e.jsx(be,{className:"size-4"}),(u==null?void 0:u.status)==="authorized"?"Reconnect Microsoft":"Sign in with Microsoft"]}),v?e.jsxs(b,{className:"bg-white/[0.08] text-white/74",children:[v.calendars.length," discovered"]}):null]}):e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsxs(k,{pending:x.isPending,pendingLabel:"Discovering",onClick:()=>void x.mutateAsync(),disabled:r.provider==="macos_local"&&U!=="full_access",children:[e.jsx(Re,{className:"size-4"}),r.provider==="macos_local"?"Discover host calendars":"Discover calendars"]}),v?e.jsxs(b,{className:"bg-white/[0.08] text-white/74",children:[v.calendars.length," discovered"]}):null]}),v?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4 text-sm leading-6 text-white/64",children:[r.provider==="macos_local"?"Discovered through the host calendar store":"Discovered through"," ",e.jsx("span",{className:"font-medium text-white",children:v.serverUrl}),v.homeUrl?e.jsxs(e.Fragment,{children:[" ","· home set"," ",e.jsx("span",{className:"font-medium text-white",children:v.homeUrl})]}):null]}),r.provider!=="microsoft"&&E?e.jsxs("div",{className:"rounded-[24px] border border-emerald-400/20 bg-emerald-400/10 p-4 text-sm leading-6 text-emerald-50",children:["Forge already writes work blocks and owned timeboxes through"," ",e.jsx("span",{className:"font-medium text-white",children:E}),". This connection only needs a mirror selection."]}):null,e.jsx("div",{className:"grid gap-3",children:v.calendars.map(i=>{const o=r.selectedCalendarUrls.includes(i.url),j=r.forgeCalendarUrl===i.url;return e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:De(i)}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[i.timezone||"No timezone exposed"," ·"," ",i.url]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[i.isForgeCandidate?e.jsx(b,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:"Forge match"}):null,i.isPrimary?e.jsx(b,{className:"bg-white/[0.08] text-white/74",children:"Primary"}):null]})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[e.jsx("button",{type:"button",onClick:()=>a({selectedCalendarUrls:o?r.selectedCalendarUrls.filter(se=>se!==i.url):[...r.selectedCalendarUrls,i.url]}),className:`rounded-full px-3 py-2 text-sm transition ${o?"bg-[var(--primary)]/18 text-[var(--primary)] shadow-[inset_0_0_0_1px_rgba(192,193,255,0.24)]":"bg-white/[0.05] text-white/62 hover:bg-white/[0.08]"}`,children:o?"Mirrored":"Mirror into Forge"}),r.provider!=="microsoft"&&!E?e.jsx("button",{type:"button",onClick:()=>a({forgeCalendarUrl:i.url,createForgeCalendar:!1}),className:`rounded-full px-3 py-2 text-sm transition ${j?"bg-emerald-500/18 text-emerald-100 shadow-[inset_0_0_0_1px_rgba(16,185,129,0.28)]":"bg-white/[0.05] text-white/62 hover:bg-white/[0.08]"}`,children:j?"Forge writes here":"Use for Forge writes"}):e.jsx(b,{className:r.provider==="microsoft"?"bg-sky-400/12 text-sky-100":"bg-white/[0.08] text-white/74",children:r.provider==="microsoft"?"Read only":"Shared target elsewhere"})]})]},i.url)})}),r.provider!=="microsoft"&&!E?e.jsxs("div",{className:"rounded-[24px] border border-dashed border-white/10 bg-white/[0.03] p-4",children:[e.jsx("div",{className:"font-medium text-white",children:"No Forge calendar yet?"}),e.jsxs("p",{className:"mt-2 text-sm leading-6 text-white/60",children:["If none of the discovered calendars should receive Forge-owned work blocks and timeboxes, let Forge create a dedicated calendar named"," ",e.jsx("span",{className:"font-medium text-white",children:"Forge"}),"."]}),e.jsx("div",{className:"mt-4",children:e.jsx("button",{type:"button",onClick:()=>a({forgeCalendarUrl:null,createForgeCalendar:!r.createForgeCalendar}),className:`rounded-full px-3 py-2 text-sm transition ${r.createForgeCalendar?"bg-emerald-500/18 text-emerald-100 shadow-[inset_0_0_0_1px_rgba(16,185,129,0.28)]":"bg-white/[0.05] text-white/62 hover:bg-white/[0.08]"}`,children:r.createForgeCalendar?"Forge will create one":"Create a new Forge calendar"})})]}):r.provider==="microsoft"?e.jsx("div",{className:"rounded-[24px] border border-sky-400/20 bg-sky-400/10 p-4 text-sm leading-6 text-sky-50",children:"Exchange Online is connected through Microsoft Graph in read-only mode. Forge will mirror the calendars you select here, but it will keep work blocks and owned timeboxes local or publish them through another writable provider."}):e.jsxs("div",{className:"rounded-[24px] border border-dashed border-white/10 bg-white/[0.03] p-4 text-sm leading-6 text-white/60",children:["Forge will keep"," ",e.jsx("span",{className:"font-medium text-white",children:E})," ","as the canonical write target instead of creating another Forge calendar on this connection."]})]}):e.jsx("div",{className:"rounded-[24px] border border-dashed border-white/10 bg-white/[0.03] px-4 py-6 text-sm leading-6 text-white/58",children:r.provider==="google"?e.jsx(e.Fragment,{children:"Start the guided Google sign-in first. Forge will bring the discovered Google calendars back here as soon as the popup completes."}):r.provider==="microsoft"?e.jsx(e.Fragment,{children:"Start the guided Microsoft sign-in first. Forge will bring the discovered Exchange Online calendars back here as soon as the popup completes."}):e.jsx(e.Fragment,{children:r.provider==="macos_local"?"Grant macOS Calendar access and discover the host calendars first. If Calendar.app already aggregates Google, Exchange, or iCloud for this Mac, Forge will pick them up here without reconnecting those accounts.":e.jsxs(e.Fragment,{children:["Discover calendars after entering the credentials. For Apple, Forge starts from"," ",e.jsx("span",{className:"font-medium text-white",children:"https://caldav.icloud.com"})," ","and resolves the principal plus calendar home automatically."]})})})]})},{id:"review",eyebrow:"Review",title:"Confirm what Forge will mirror and where it will write",description:"This keeps the sync model explicit before the provider connection is saved.",render:r=>{var a,i;return e.jsxs("div",{className:"grid gap-4",children:[r.provider==="macos_local"&&r.sourceId?e.jsxs("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/70",children:["Selected host source:"," ",e.jsx("span",{className:"font-medium text-white",children:((a=C==null?void 0:C.sources.find(o=>o.sourceId===r.sourceId))==null?void 0:a.accountLabel)??((i=C==null?void 0:C.sources.find(o=>o.sourceId===r.sourceId))==null?void 0:i.sourceTitle)??r.sourceId})]}):null,e.jsxs("div",{className:"rounded-[26px] border border-white/8 bg-[linear-gradient(180deg,rgba(21,31,42,0.96),rgba(10,16,26,0.96))] p-5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"rounded-[18px] bg-[var(--primary)]/14 p-3 text-[var(--primary)]",children:e.jsx(Me,{className:"size-4"})}),e.jsxs("div",{children:[e.jsx("div",{className:"font-display text-xl text-white",children:oe(r.provider,r.label)}),e.jsx("div",{className:"mt-1 text-sm text-white/58",children:r.provider==="google"?"Google Calendar":r.provider==="macos_local"?"Calendars On This Mac":r.provider==="apple"?"Apple Calendar":r.provider==="microsoft"?"Exchange Online":"Custom CalDAV"})]})]}),e.jsxs("div",{className:"mt-4 grid gap-3 md:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] px-4 py-3 text-sm text-white/72",children:["Mirrored calendars:"," ",e.jsx("span",{className:"font-medium text-white",children:r.selectedCalendarUrls.length})]}),e.jsxs("div",{className:"rounded-[20px] bg-white/[0.04] px-4 py-3 text-sm text-white/72",children:["Forge writes:"," ",e.jsx("span",{className:"font-medium text-white",children:r.provider==="microsoft"?"read only":r.forgeCalendarUrl?"existing calendar":r.createForgeCalendar?"new Forge calendar":E?`shared target via ${E}`:"not selected"})]})]}),r.replaceConnectionIds.length>0?e.jsxs("div",{className:"mt-4 rounded-[20px] border border-amber-400/20 bg-amber-400/10 px-4 py-3 text-sm leading-6 text-amber-50",children:["Forge will replace ",r.replaceConnectionIds.length," older overlapping connection",r.replaceConnectionIds.length===1?"":"s"," for this same calendar account so only one visible copy remains.",ge.filter(o=>r.replaceConnectionIds.includes(o.id)).map(o=>o.label).join(", ")?` ${ge.filter(o=>r.replaceConnectionIds.includes(o.id)).map(o=>o.label).join(", ")}.`:""]}):null]})]})}}],[v,x.isPending,n.provider,Oe,I,g,h.clientId,Z,h.allowedOrigins,h.appBaseUrl,h.isLocalOnly,h.isReadyForPairing,h.redirectUri,Ke,te,Ae,Fe,xe,S,T.setupMessage,me,O,$.isPending,ee.isPending,Ce,re.isPending,T.isReadyForSignIn,T.redirectUri,C,u,R,E]),gr=n.provider==="macos_local"&&n.replaceConnectionIds.length>0?"Replace and connect":"Connect provider";return e.jsx($e,{open:t,onOpenChange:c,eyebrow:"Calendar settings",title:"Connect a calendar provider",description:"Discover provider calendars first, choose which calendars Forge should mirror, and only choose a Forge write target when the runtime does not already have one.",value:n,onChange:r=>{V(r),v&&r.provider!==v.provider&&_(null),r.provider!=="macos_local"&&P(null)},draftPersistenceKey:"calendar.connection.new",steps:hr,submitLabel:gr,pending:N,pendingLabel:"Connecting",error:ye,resolveError:lr,initialStepId:w,onSubmit:async()=>{try{if(m(null),!v){m("Discover the available calendars before saving the connection.");return}if(n.selectedCalendarUrls.length===0){m("Select at least one calendar to mirror into Forge.");return}if(n.provider!=="microsoft"&&!n.forgeCalendarUrl&&!n.createForgeCalendar&&!R){m("Choose the calendar Forge should write into, ask Forge to create one, or keep using the existing shared Forge write target.");return}if(n.provider==="google"){if(!(g!=null&&g.sessionId)||g.status!=="authorized"){m("Complete the Google sign-in flow before saving this connection.");return}await Y({provider:"google",label:oe("google",n.label),authSessionId:g.sessionId,selectedCalendarUrls:n.selectedCalendarUrls,forgeCalendarUrl:n.forgeCalendarUrl,createForgeCalendar:n.createForgeCalendar})}else if(n.provider==="apple")await Y({provider:"apple",label:oe("apple",n.label),username:n.username.trim(),password:n.password.trim(),selectedCalendarUrls:n.selectedCalendarUrls,forgeCalendarUrl:n.forgeCalendarUrl,createForgeCalendar:n.createForgeCalendar});else if(n.provider==="microsoft"){if(!(u!=null&&u.sessionId)||u.status!=="authorized"){m("Complete the Microsoft sign-in flow before saving this connection.");return}await Y({provider:"microsoft",label:oe("microsoft",n.label),authSessionId:u.sessionId,selectedCalendarUrls:n.selectedCalendarUrls})}else if(n.provider==="macos_local"){if(!n.sourceId){m("Choose which host calendar source Forge should connect before saving.");return}await Y({provider:"macos_local",label:oe("macos_local",n.label),sourceId:n.sourceId,selectedCalendarUrls:n.selectedCalendarUrls,forgeCalendarUrl:n.forgeCalendarUrl,createForgeCalendar:n.createForgeCalendar,replaceConnectionIds:n.replaceConnectionIds})}else await Y({provider:"caldav",label:oe("caldav",n.label),serverUrl:n.serverUrl.trim(),username:n.username.trim(),password:n.password.trim(),selectedCalendarUrls:n.selectedCalendarUrls,forgeCalendarUrl:n.forgeCalendarUrl,createForgeCalendar:n.createForgeCalendar});c(!1)}catch(r){if(r instanceof Nr&&r.code==="calendar_connection_overlap"){const a=r.response,i=Array.isArray(a==null?void 0:a.overlappingConnectionIds)?a==null?void 0:a.overlappingConnectionIds.filter(o=>typeof o=="string"):[];V(o=>({...o,replaceConnectionIds:i})),m(`${r.message} Submit again to replace the older overlapping connection${i.length===1?"":"s"}.`);return}m(r instanceof Error?r.message:"Forge could not create this calendar connection.")}}})}function ve(t){try{const c=new URL(t);return c.pathname.endsWith("/")||(c.pathname=`${c.pathname}/`),c.toString()}catch{return t}}function tr(t){switch(t){case"google":return"Google Calendar";case"apple":return"Apple Calendar";case"microsoft":return"Exchange Online";case"macos_local":return"Calendars On This Mac";case"caldav":default:return"Custom CalDAV"}}function nt(t){switch(t){case"google":return"Open Google guided flow";case"microsoft":return"Open Microsoft guided flow";case"macos_local":return"Open Mac calendar flow";default:return"Open guided setup"}}function it(t){switch(t){case"google":case"microsoft":return Ee;case"macos_local":return Te;case"apple":return Te;case"caldav":default:return Me}}function ot(t){switch(t){case"microsoft":return"Read only";case"macos_local":return"Read + write";default:return"Read + write"}}function lt(t){switch(t){case"google":return"Local PKCE";case"microsoft":return"Guided sign-in";case"macos_local":return"Host machine";case"apple":return"App password";case"caldav":default:return"CalDAV credentials"}}function ct(t){switch(t){case"google":return"Sign in from the same machine running Forge. After connection, Forge can mirror the calendars you choose and reuse the current shared Forge write target, creating one only when the runtime does not already have one.";case"apple":return"Use your Apple ID email and app-specific password. Forge discovers your iCloud calendars before you choose what to mirror.";case"microsoft":return"Use the guided Microsoft sign-in flow. Forge mirrors the Exchange calendars you choose and keeps this provider read only.";case"macos_local":return"Use the calendars already configured in Calendar.app on this Mac. Forge requests Calendar access through macOS, discovers host calendars by account source, and replaces overlapping remote account connections instead of duplicating them.";case"caldav":default:return"Enter a CalDAV server URL and account credentials. Forge discovers the calendars on that account before you choose what to mirror."}}function sr(t){return`${t} connection${t===1?"":"s"}`}function yt(){var M,fe,R,E,je;const t=ar(),[c,p]=fr(),[w,A]=l.useState(!1),[q,H]=l.useState("google"),[ge,Y]=l.useState(void 0),[N,we]=l.useState(null),[n,V]=l.useState([]),[ye,m]=l.useState(!1),[v,_]=l.useState(null),[U,ae]=l.useState(()=>Vr()),C=Ue({queryKey:["forge-operator-session"],queryFn:Dr}),P=C.isSuccess,g=Ue({queryKey:["forge-settings"],queryFn:_r,enabled:P}),y=Ue({queryKey:["forge-calendar-connections"],queryFn:Pr,enabled:P}),u=Ue({queryKey:["forge-calendar-resources"],queryFn:zr,enabled:P}),X=async()=>{await Promise.all([t.invalidateQueries({queryKey:["forge-settings"]}),t.invalidateQueries({queryKey:["forge-calendar-connections"]}),t.invalidateQueries({queryKey:["forge-calendar-resources"]}),t.invalidateQueries({queryKey:["forge-calendar-overview"]}),Gr(t)])},h=Q({mutationFn:Mr,onSuccess:X}),ue=Q({mutationFn:s=>Er(s),onSuccess:X}),I=Q({mutationFn:({connectionId:s,patch:d})=>Or(s,d),onSuccess:X}),K=Q({mutationFn:s=>Ar(s),onSuccess:X});l.useEffect(()=>{if(!P)return;const s=c.get("intent"),d=c.get("provider");if(s!=="connect")return;H(d==="apple"||d==="caldav"||d==="google"||d==="microsoft"||d==="macos_local"?d:"google"),Y(d==="microsoft"?"credentials":void 0),A(!0);const f=new URLSearchParams(c);f.delete("intent"),f.delete("provider"),p(f,{replace:!0})},[P,c,p]);const z=l.useMemo(()=>{var s,d;return Lr(((s=u.data)==null?void 0:s.calendars)??[],((d=y.data)==null?void 0:d.connections)??[])},[(M=u.data)==null?void 0:M.calendars,(fe=y.data)==null?void 0:fe.connections]),le=l.useMemo(()=>{const s=new Map;for(const d of z){const f=s.get(d.connectionId)??[];f.push(d),s.set(d.connectionId,f)}return s},[z]),Oe=l.useMemo(()=>{var d;const s={};for(const f of((d=y.data)==null?void 0:d.connections)??[])s[f.provider]=(s[f.provider]??0)+1;return s},[(R=y.data)==null?void 0:R.connections]),ne=l.useMemo(()=>Kr(z,U.calendarColors),[z,U.calendarColors]),Z=l.useMemo(()=>{var s;return(((s=y.data)==null?void 0:s.connections)??[]).find(d=>{var f;return typeof((f=d.config)==null?void 0:f.forgeCalendarUrl)=="string"&&d.config.forgeCalendarUrl.trim().length>0})??null},[(E=y.data)==null?void 0:E.connections]),F=l.useMemo(()=>{var s;return((s=y.data)==null?void 0:s.connections.find(d=>d.id===N))??null},[y.data,N]),T=l.useMemo(()=>{var s;return((s=y.data)==null?void 0:s.connections.find(d=>d.id===v))??null},[y.data,v]),pe=l.useMemo(()=>N?le.get(N)??[]:[],[le,N]),S=Ue({queryKey:["forge-calendar-connection-discovery",N],queryFn:()=>Tr(N),enabled:P&&N!==null});l.useEffect(()=>{if(!N){V([]),m(!1);return}const s=pe.filter(d=>d.selectedForSync).map(d=>ve(d.remoteId));V(s),m(!0)},[N,pe]),l.useEffect(()=>{Wr(U)},[U]);const ce=l.useMemo(()=>[{id:"mirrors",eyebrow:"Mirroring",title:"Choose which calendars Forge should mirror",description:"Unselected calendars stop showing up in Forge’s mirrored calendar views. The Forge write calendar stays available for work blocks and timeboxes.",render:(s,d)=>{var J,ee;if(S.isLoading)return e.jsx("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.03] px-4 py-6 text-sm leading-6 text-white/58",children:"Rediscovering calendars for this connection."});if(S.isError||!((J=S.data)!=null&&J.discovery))return e.jsx("div",{className:"rounded-[24px] border border-rose-400/20 bg-rose-400/10 px-4 py-6 text-sm leading-6 text-rose-100",children:S.error instanceof Error?S.error.message:"Forge could not rediscover calendars for this connection."});const f=S.data.discovery,x=(F==null?void 0:F.provider)==="microsoft",G=typeof((ee=F==null?void 0:F.config)==null?void 0:ee.forgeCalendarUrl)=="string"?ve(F.config.forgeCalendarUrl):null;return e.jsx("div",{className:"grid gap-3",children:f.calendars.map($=>{const re=ve($.url),O=ye?s.selectedCalendarUrls.includes(re):pe.some(te=>te.selectedForSync&&ve(te.remoteId)===re),W=G===re;return e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:De($)}),e.jsxs("div",{className:"mt-1 text-sm text-white/56",children:[$.timezone||"No timezone exposed"," ·"," ",$.url]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[W&&!x?e.jsx(b,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:"Forge writes here"}):null,x?e.jsx(b,{className:"bg-sky-400/12 text-sky-100",children:"Read only"}):null,$.isPrimary?e.jsx(b,{className:"bg-white/[0.08] text-white/74",children:"Primary"}):null]})]}),e.jsx("div",{className:"mt-4 flex flex-wrap gap-2",children:e.jsx("button",{type:"button",disabled:W&&!x,onClick:()=>d({selectedCalendarUrls:O?s.selectedCalendarUrls.filter(te=>te!==re):[...s.selectedCalendarUrls,re]}),className:`rounded-full px-3 py-2 text-sm transition ${W&&!x?"cursor-not-allowed bg-white/[0.05] text-white/35":O?"bg-emerald-500/18 text-emerald-100 shadow-[inset_0_0_0_1px_rgba(16,185,129,0.28)]":"bg-white/[0.05] text-white/62 hover:bg-white/[0.08]"}`,children:W&&!x?"Always available for Forge writes":O?"Mirrored into Forge":"Do not mirror"})})]},$.url)})})}}],[F,S]);if(C.isLoading||g.isLoading||y.isLoading||u.isLoading)return e.jsx(Rr,{eyebrow:"Settings · Calendar",title:"Loading calendar settings",description:"Checking the operator session and loading provider connections.",columns:2,blocks:6});if(C.isError)return e.jsx(Ye,{eyebrow:"Settings · Calendar",error:C.error,onRetry:()=>void C.refetch()});if(g.isError||y.isError||u.isError||!((je=g.data)!=null&&je.settings)||!y.data||!u.data)return e.jsx(Ye,{eyebrow:"Settings · Calendar",error:g.error??y.error??u.error??new Error("Calendar settings are unavailable."),onRetry:()=>{g.refetch(),y.refetch(),u.refetch()}});const{providers:Ce,connections:ie}=y.data,me=g.data.settings.calendarProviders.google,L=g.data.settings.calendarProviders.microsoft;return e.jsxs("div",{className:"mx-auto grid w-full max-w-[1220px] gap-5",children:[e.jsx(qr,{title:"Calendar settings",description:"Manage provider connections, review the shared Forge write target, and open guided setup only when you need to connect or reconfigure a provider.",badge:`${ie.length} connection${ie.length===1?"":"s"}`}),e.jsx($r,{}),e.jsxs("div",{className:"grid gap-5",children:[e.jsxs(Ge,{className:"surface-section-panel grid gap-5 rounded-[30px] border",children:[e.jsxs("div",{className:"max-w-3xl",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/45",children:"Provider connections"}),e.jsxs("p",{className:"mt-2 text-sm leading-6 text-white/60",children:["Connect a provider here, then choose which calendars Forge should mirror. Writable providers publish work blocks and owned timeboxes through one shared"," ",e.jsx("span",{className:"font-medium text-white",children:"Forge"})," write target, creating it only when the runtime does not already have one."]})]}),e.jsx("div",{className:"grid gap-4 lg:grid-cols-2",children:Ce.map(s=>{const d=it(s.provider),f=Oe[s.provider]??0,x=f>0;return e.jsxs("div",{className:`flex min-h-[248px] flex-col rounded-[26px] border p-5 shadow-[inset_0_1px_0_var(--ui-border-subtle)] ${x?"border-emerald-400/24 bg-[linear-gradient(180deg,color-mix(in_srgb,#10b981_18%,var(--surface-panel)_82%),var(--ui-surface-2))]":"border-[var(--ui-border-subtle)] bg-[var(--ui-surface-2)]"}`,children:[e.jsxs("div",{className:"flex items-start gap-4",children:[e.jsx("div",{className:`rounded-[18px] p-3 ${x?"bg-emerald-400/16 text-emerald-100":"bg-[var(--primary)]/14 text-[var(--primary)]"}`,children:e.jsx(d,{className:"size-4"})}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("div",{className:"font-medium text-[var(--ui-ink-strong)]",children:s.label}),x?e.jsxs(e.Fragment,{children:[e.jsx(b,{className:"bg-emerald-400/16 text-emerald-50",children:"Connected"}),e.jsx(b,{className:"bg-white/[0.08] text-white/82",children:sr(f)})]}):null]}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-[var(--ui-ink-soft)]",children:ct(s.provider)}),x?e.jsxs("div",{className:"mt-3 text-sm text-emerald-100/88",children:["Forge already has"," ",sr(f)," for this provider. Open the guided flow again to add another account or reconfigure one."]}):null]})]}),e.jsxs("div",{className:"mt-5 flex flex-wrap gap-2",children:[e.jsx(b,{tone:"signal",className:"bg-[var(--primary)]/14 text-white/86",children:lt(s.provider)}),e.jsx(b,{className:s.supportsDedicatedForgeCalendar?"bg-emerald-500/16 text-emerald-100":"bg-sky-400/14 text-sky-100",children:ot(s.provider)})]}),e.jsx("div",{className:"mt-auto pt-5",children:e.jsxs(k,{variant:"secondary",className:"w-full justify-center",onClick:()=>{H(s.provider),Y(s.provider==="google"||s.provider==="microsoft"?"credentials":void 0),A(!0)},children:[e.jsx(be,{className:"size-4"}),nt(s.provider)]})})]},s.provider)})})]}),e.jsxs(Ge,{className:"surface-section-panel grid gap-4 rounded-[30px] border",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/45",children:"Calendar colors"}),e.jsx("p",{className:"mt-2 max-w-3xl text-sm leading-6 text-white/60",children:"Calendar colors are on by default so each mirrored calendar stays legible in the week view. Adjust any display color here without changing the provider itself."})]}),e.jsx("button",{type:"button",onClick:()=>ae(s=>({...s,useCalendarColors:!s.useCalendarColors})),className:`rounded-full px-4 py-2 text-sm transition ${U.useCalendarColors?"bg-[var(--ui-accent-soft)] text-[var(--primary)] shadow-[inset_0_0_0_1px_rgba(192,193,255,0.2)]":"border border-[var(--ui-border-subtle)] bg-[var(--ui-surface-2)] text-[var(--ui-ink-soft)] hover:bg-[var(--ui-surface-hover)]"}`,children:U.useCalendarColors?"Colors on":"Colors off"})]}),z.length>0?e.jsx("div",{className:"grid gap-3",children:z.map(s=>{const d=De(s);return e.jsxs("div",{className:"grid gap-3 rounded-[22px] border border-[var(--ui-border-subtle)] bg-[var(--ui-surface-2)] p-4 md:grid-cols-[minmax(0,1fr)_auto]",children:[e.jsx("div",{className:"min-w-0",children:e.jsxs("div",{className:"flex min-w-0 items-center gap-3",children:[e.jsx("span",{"aria-hidden":"true",className:"size-3 shrink-0 rounded-full",style:{backgroundColor:ne[s.id]}}),e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate font-medium text-[var(--ui-ink-strong)]",children:d}),e.jsxs("div",{className:"mt-1 text-sm text-[var(--ui-ink-soft)]",children:[s.canWrite?"Writable":"Read only"," ·"," ",s.timezone]})]})]})}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx("input",{"aria-label":`Choose display color for ${d}`,type:"color",value:ne[s.id],onChange:f=>ae(x=>({...x,calendarColors:{...x.calendarColors,[s.id]:f.target.value}})),className:"h-10 w-12 cursor-pointer rounded-[14px] border border-[var(--ui-border-subtle)] bg-transparent p-1"}),e.jsx(k,{size:"sm",variant:"secondary",onClick:()=>ae(f=>{const x={...f.calendarColors};return delete x[s.id],{...f,calendarColors:x}}),children:"Reset palette"})]})]},s.id)})}):e.jsx("div",{className:"rounded-[24px] border border-dashed border-[var(--ui-border-subtle)] bg-[var(--ui-surface-1)] px-4 py-5 text-sm leading-6 text-[var(--ui-ink-soft)]",children:"Connect a provider first, then Forge will let you tune the display color of each mirrored calendar here."})]}),e.jsxs(Ge,{className:"surface-section-panel grid gap-4 rounded-[30px] border",children:[e.jsx("div",{className:"flex items-center justify-between gap-3",children:e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/45",children:"Connected providers"}),e.jsx("p",{className:"mt-2 text-sm leading-6 text-white/60",children:"Review connection health, confirm which provider calendars Forge can read or mirror, and see which connection currently owns the shared Forge write target."})]})}),ie.length>0?e.jsx("div",{className:"grid gap-3",children:ie.map(s=>{var x;const d=le.get(s.id)??[],f=s.provider!=="microsoft"&&Z!==null&&Z.id!==s.id;return e.jsxs("div",{className:"rounded-[24px] border border-[var(--ui-border-subtle)] bg-[var(--ui-surface-2)] p-4",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-[var(--ui-ink-strong)]",children:s.label}),e.jsxs("div",{className:"mt-1 text-sm text-[var(--ui-ink-soft)]",children:[tr(s.provider)," ·"," ",s.accountLabel||"No account label yet"]}),s.lastSyncedAt?e.jsxs("div",{className:"mt-2 text-sm text-[var(--ui-ink-faint)]",children:["Last synced"," ",new Date(s.lastSyncedAt).toLocaleString()]}):null,s.lastSyncError?e.jsx("div",{className:"mt-2 text-sm text-rose-200",children:s.lastSyncError}):null,f?e.jsxs("div",{className:"mt-2 text-sm text-[var(--ui-ink-soft)]",children:["Forge writes through"," ",e.jsx("span",{className:"font-medium text-[var(--ui-ink-strong)]",children:Z.label}),Z.accountLabel?` · ${Z.accountLabel}`:"","."]}):null]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(b,{className:"bg-white/[0.08] text-white/74",children:s.status}),((x=s.config)==null?void 0:x.readOnly)===!0?e.jsx(b,{className:"bg-sky-400/12 text-sky-100",children:"Read only"}):null,e.jsxs(k,{size:"sm",variant:"secondary",pending:ue.isPending&&ue.variables===s.id,pendingLabel:"Syncing",onClick:()=>void ue.mutateAsync(s.id),children:[e.jsx(Re,{className:"size-4"}),"Sync"]}),e.jsxs(k,{size:"sm",variant:"secondary",onClick:()=>{const G=(le.get(s.id)??[]).filter(J=>J.selectedForSync).map(J=>ve(J.remoteId));V(G),m(!0),we(s.id)},children:[e.jsx(xr,{className:"size-4"}),"Manage mirrored calendars"]}),e.jsxs(k,{size:"sm",variant:"secondary",onClick:()=>_(s.id),children:[e.jsx(vr,{className:"size-4"}),"Remove"]})]})]}),e.jsx("div",{className:"mt-4 grid gap-2",children:d.map(G=>e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3 rounded-[18px] bg-white/[0.04] px-4 py-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"truncate text-sm font-medium text-[var(--ui-ink-strong)]",children:De(G)}),e.jsxs("div",{className:"mt-1 text-xs uppercase tracking-[0.16em] text-[var(--ui-ink-faint)]",children:[G.canWrite?"Writable":"Read only"," ·"," ",G.timezone]})]}),G.forgeManaged?e.jsx(b,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:"Forge"}):e.jsxs(b,{className:"bg-white/[0.08] text-white/74",children:[e.jsx(Te,{className:"mr-1 size-3.5"}),"Mirrored"]})]},G.id))})]},s.id)})}):e.jsxs("div",{className:"rounded-[26px] border border-dashed border-white/10 bg-white/[0.03] px-5 py-6 text-sm leading-6 text-white/60",children:["No provider is connected yet. Open a guided setup flow above when you are ready. Forge will reuse one shared"," ",e.jsx("span",{className:"font-medium text-white",children:"Forge"})," write target across writable providers when it already exists, create one only when none exists yet, and mirror selected calendars in read-only mode for providers like Exchange Online."]})]})]}),e.jsx(at,{open:w,onOpenChange:s=>{A(s),s||Y(void 0)},initialProvider:q,initialStepId:ge,googleSetup:me,microsoftSetup:L,existingConnections:ie.map(s=>({id:s.id,label:s.label,provider:s.provider,status:s.status,accountLabel:s.accountLabel,forgeCalendarId:s.forgeCalendarId,config:s.config})),onCalendarSettingsChanged:X,pending:h.isPending,onSubmit:async s=>{await h.mutateAsync(s)}}),e.jsx($e,{open:N!==null,onOpenChange:s=>{s||we(null)},eyebrow:"Calendar settings",title:"Manage mirrored calendars",description:"Choose which calendars this connection should mirror into Forge.",value:{selectedCalendarUrls:n},onChange:s=>V(s.selectedCalendarUrls),draftPersistenceKey:N?`settings.calendar.manage.${N}`:"settings.calendar.manage",steps:ce,pending:I.isPending,pendingLabel:"Saving",submitLabel:"Save mirror selection",error:I.error instanceof Error?I.error.message:null,onSubmit:async()=>{N&&(await I.mutateAsync({connectionId:N,patch:{selectedCalendarUrls:n.map(ve)}}),m(!1),we(null))}}),e.jsx($e,{open:v!==null,onOpenChange:s=>{s||_(null)},eyebrow:"Calendar settings",title:"Remove calendar connection",description:"This removes the provider connection, stops syncing its calendars, removes mirrored external events from Forge, and keeps Forge-native events local.",value:{acknowledgement:!1},onChange:()=>{},draftPersistenceKey:v?`settings.calendar.remove.${v}`:"settings.calendar.remove",steps:[{id:"confirm",eyebrow:"Disconnect",title:T?`Remove ${T.label}?`:"Remove this connection?",description:"Use this when you want to disconnect the account entirely. You can reconnect later with the guided setup flow.",render:()=>e.jsx("div",{className:"rounded-[24px] border border-rose-400/20 bg-rose-400/10 p-4 text-sm leading-6 text-rose-100",children:T?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"font-medium text-white",children:[tr(T.provider)," ·"," ",T.accountLabel||"No account label"]}),e.jsx("div",{className:"mt-2",children:"Mirrored provider calendars and external mirrored events from this connection will be removed. Forge-owned events, work blocks, and timeboxes remain in Forge."})]}):"This connection will be removed from Forge."})}],pending:K.isPending,pendingLabel:"Removing",submitLabel:"Remove connection",error:K.error instanceof Error?K.error.message:null,onSubmit:async()=>{v&&(await K.mutateAsync(v),_(null))}})]})}export{yt as SettingsCalendarPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as o,j as e,b2 as $,dr as _,aG as D,bn as G,df as H,c7 as Z}from"./vendor-DHkYh85p.js";import{j as J,i as Q,k as x}from"./state-B-4sS1xO.js";import{S as V}from"./settings-section-nav-DSOuht_F.js";import{P as X}from"./page-hero-DRy5b2MU.js";import{dj as Y,eh as ee,ei as te,ej as ae,ek as se,el as ie,L as ne,E as oe,C as j,B as l,c as p,b$ as de,em as re}from"./index-CF4J4R9L.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";function f(s="openai-api"){return{label:s==="openai-codex"?"OpenAI Codex":s==="openai-compatible"?"Local compatible endpoint":s==="mock"?"Workbench mock runtime":"OpenAI API",provider:s,baseUrl:s==="openai-codex"?"https://chatgpt.com/backend-api":s==="openai-compatible"?"http://127.0.0.1:11434/v1":s==="mock"?"mock://workbench":"https://api.openai.com/v1",model:s==="mock"?"mock-echo":"gpt-5.4-mini",apiKey:""}}function le(s){return{id:s.id,label:s.label,provider:s.provider,baseUrl:s.baseUrl,model:s.model,apiKey:""}}function je(){var z,B,q;const s=J(),[a,c]=o.useState(()=>f()),[y,N]=o.useState(""),[C,k]=o.useState("gpt-5.4-mini"),[A,S]=o.useState(""),[O,I]=o.useState("gpt-5.4-mini"),[v,u]=o.useState(""),[d,b]=o.useState(null),[M,m]=o.useState(null),r=Q({queryKey:["forge-settings"],queryFn:de}),R=Q({queryKey:["forge-openai-codex-oauth",d],queryFn:async()=>{if(!d)throw new Error("Missing OAuth session id");return await re(d)},enabled:!!d,refetchInterval:t=>{var W;const n=(W=t.state.data)==null?void 0:W.session.status;return n&&["authorized","error","consumed","expired"].includes(n)?!1:1500}}),w=async()=>{await s.invalidateQueries({queryKey:["forge-settings"]}),await s.invalidateQueries({queryKey:["forge-openai-codex-oauth",d]})},L=x({mutationFn:()=>Y({modelSettings:{forgeAgent:{basicChat:{connectionId:y||null,model:C},wiki:{connectionId:A||null,model:O}}}}),onSuccess:w}),F=x({mutationFn:()=>ee({id:a.id,label:a.label,provider:a.provider,authMode:a.provider==="openai-codex"?"oauth":"api_key",baseUrl:a.baseUrl,model:a.model,apiKey:a.provider==="openai-codex"?void 0:a.apiKey||void 0,oauthSessionId:a.provider==="openai-codex"?d??void 0:void 0}),onSuccess:async()=>{m("Connection saved."),a.provider==="openai-codex"&&(b(null),u("")),c(f(a.provider)),await w()}}),P=x({mutationFn:te,onSuccess:w}),K=x({mutationFn:async()=>ae({connectionId:a.id,provider:a.provider,baseUrl:a.baseUrl,model:a.model,apiKey:a.provider==="openai-codex"?void 0:a.apiKey||void 0}),onSuccess:({result:t})=>{m(`Connection test succeeded: ${t.outputPreview}`)},onError:t=>{m(t instanceof Error?t.message:"Connection test failed.")}}),E=x({mutationFn:se,onSuccess:({session:t})=>{b(t.id),m("OpenAI Codex OAuth started."),t.authUrl&&window.open(t.authUrl,"_blank","noopener,noreferrer")}}),U=x({mutationFn:async()=>{if(!d)throw new Error("No OAuth session started yet.");return await ie(d,v)},onSuccess:({session:t})=>{m(t.status==="authorized"?"OpenAI Codex OAuth authorized.":"Manual OAuth code submitted.")}});o.useEffect(()=>{var n;const t=(n=r.data)==null?void 0:n.settings;t&&(N(t.modelSettings.forgeAgent.basicChat.connectionId??""),k(t.modelSettings.forgeAgent.basicChat.model),S(t.modelSettings.forgeAgent.wiki.connectionId??""),I(t.modelSettings.forgeAgent.wiki.model))},[r.data]);const h=((z=r.data)==null?void 0:z.settings.modelSettings.connections)??[],i=((B=R.data)==null?void 0:B.session)??null,T=o.useMemo(()=>!a.label.trim()||!a.model.trim()?!1:a.provider==="openai-codex"?!!(a.id||(i==null?void 0:i.status)==="authorized"):a.provider==="mock"?!0:a.apiKey.trim().length>0||!!a.id,[a,i==null?void 0:i.status]);if(r.isLoading)return e.jsx(ne,{eyebrow:"Models",title:"Loading model settings",description:"Fetching Forge agent defaults and configured AI connections."});if(r.isError||!((q=r.data)!=null&&q.settings))return e.jsx(oe,{eyebrow:"Models",error:r.error??new Error("Forge returned an empty model settings payload."),onRetry:()=>void r.refetch()});const g=r.data.settings;return e.jsxs("div",{className:"mx-auto grid w-full max-w-[1440px] gap-5",children:[e.jsx(X,{eyebrow:"AI runtime",title:"Model Settings",description:"Manage Forge Agent defaults, OpenAI OAuth/API connections, and local OpenAI-compatible endpoints as first-class chat agents.",badge:`${h.length} model connection${h.length===1?"":"s"}`}),e.jsx(V,{}),e.jsxs(j,{className:"grid gap-5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx($,{className:"size-4 text-[var(--secondary)]"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-white",children:"Forge Agent defaults"}),e.jsx("div",{className:"text-xs leading-5 text-white/52",children:"Forge Agent stays the default system agent. Choose which model connection powers basic chat and the managed wiki workflow."})]})]}),e.jsxs("div",{className:"grid gap-4 lg:grid-cols-2",children:[e.jsxs("label",{className:"grid gap-2 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("span",{className:"text-sm text-white/72",children:"Basic chat connection"}),e.jsxs("select",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:y,onChange:t=>N(t.target.value),children:[e.jsx("option",{value:"",children:"No external connection"}),h.map(t=>e.jsxs("option",{value:t.id,children:[t.label," (",t.agentLabel,")"]},t.id))]}),e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:C,onChange:t=>k(t.target.value),placeholder:"Model"})]}),e.jsxs("label",{className:"grid gap-2 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("span",{className:"text-sm text-white/72",children:"KarpaWiki model connection"}),e.jsxs("select",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:A,onChange:t=>S(t.target.value),children:[e.jsx("option",{value:"",children:"No external connection"}),h.map(t=>e.jsxs("option",{value:t.id,children:[t.label," (",t.agentLabel,")"]},t.id))]}),e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:O,onChange:t=>I(t.target.value),placeholder:"Model"})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-3",children:[e.jsx(l,{pending:L.isPending,pendingLabel:"Saving defaults",onClick:()=>void L.mutateAsync(),children:"Save Forge Agent defaults"}),e.jsxs(p,{className:"bg-white/[0.06] text-white/78",children:["Forge Agent",g.modelSettings.forgeAgent.basicChat.connectionLabel?` basic chat: ${g.modelSettings.forgeAgent.basicChat.connectionLabel}`:" basic chat stays local"]}),e.jsx(p,{className:"bg-white/[0.06] text-white/78",children:g.modelSettings.forgeAgent.wiki.connectionLabel?`KarpaWiki: ${g.modelSettings.forgeAgent.wiki.connectionLabel}`:"KarpaWiki: no external model selected"})]})]}),e.jsxs("div",{className:"grid gap-5 xl:grid-cols-[minmax(0,1.1fr)_minmax(0,0.9fr)]",children:[e.jsxs(j,{className:"grid gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(_,{className:"size-4 text-[var(--secondary)]"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-white",children:"Connection editor"}),e.jsx("div",{className:"text-xs leading-5 text-white/52",children:"Every saved connection becomes a first-class agent layered on top of Forge Agent."})]})]}),e.jsxs("div",{className:"grid gap-3",children:[e.jsxs("div",{className:"grid gap-2",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Provider"}),e.jsx("div",{className:"grid gap-2 md:grid-cols-3",children:[["openai-api","OpenAI API"],["openai-codex","OpenAI Codex OAuth"],["openai-compatible","OpenAI-compatible"]].map(([t,n])=>e.jsx("button",{type:"button",className:`rounded-[18px] px-4 py-3 text-left text-sm transition ${a.provider===t?"bg-[var(--primary)]/[0.18] text-white":"bg-white/[0.04] text-white/62 hover:bg-white/[0.08]"}`,onClick:()=>{c(f(t)),b(null),u("")},children:n},t))})]}),e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:a.label,onChange:t=>c(n=>({...n,label:t.target.value})),placeholder:"Connection label"}),e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:a.model,onChange:t=>c(n=>({...n,model:t.target.value})),placeholder:"Model"}),a.provider==="mock"?e.jsxs("div",{className:"grid gap-3 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsx("div",{className:"text-sm text-white",children:"The Workbench mock runtime is only meant for local development and test workflows."}),e.jsxs("div",{className:"text-xs leading-5 text-white/52",children:["Use mock models like ",e.jsx("code",{children:"mock-echo"}),", ",e.jsx("code",{children:"mock-json"}),",",e.jsx("code",{children:"mock-tool-search"}),", ",e.jsx("code",{children:"mock-tool-note"}),", or",e.jsx("code",{children:"mock-chat-memory"})," to exercise deterministic flow behavior without a real external model."]})]}):a.provider!=="openai-codex"?e.jsxs(e.Fragment,{children:[e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:a.baseUrl,onChange:t=>c(n=>({...n,baseUrl:t.target.value})),placeholder:"Base URL"}),e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:a.apiKey,onChange:t=>c(n=>({...n,apiKey:t.target.value})),placeholder:a.id?"Leave blank to keep the stored key":"API key",type:"password"})]}):e.jsxs("div",{className:"grid gap-3 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"text-sm text-white",children:["OpenAI Codex uses the documented PKCE flow with the local callback at ",g.modelSettings.oauth.openAiCodex.callbackUrl,"."]}),e.jsx("div",{className:"text-xs leading-5 text-white/52",children:"Start OAuth, finish the browser sign-in, then save the resulting connection as a chat agent backed by the ChatGPT Codex runtime."}),e.jsxs("div",{className:"flex flex-wrap gap-3",children:[e.jsxs(l,{variant:"secondary",pending:E.isPending,pendingLabel:"Starting OAuth",onClick:()=>void E.mutateAsync(),children:[e.jsx(D,{className:"size-4"}),"Start OAuth"]}),i!=null&&i.authUrl?e.jsxs(l,{variant:"secondary",onClick:()=>window.open(i.authUrl??"","_blank","noopener,noreferrer"),children:["Open sign-in",e.jsx(G,{className:"size-4"})]}):null]}),i?e.jsxs("div",{className:"grid gap-2 rounded-[18px] bg-black/20 p-3 text-sm text-white/72",children:[e.jsxs("div",{children:["Status: ",i.status]}),i.accountLabel?e.jsxs("div",{children:["Account: ",i.accountLabel]}):null,i.error?e.jsx("div",{className:"text-rose-200",children:i.error}):null]}):null,e.jsxs("div",{className:"grid gap-2",children:[e.jsx("input",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:v,onChange:t=>u(t.target.value),placeholder:"Paste the authorization code or full redirect URL"}),e.jsx(l,{variant:"secondary",disabled:!v.trim()||!d,pending:U.isPending,pendingLabel:"Submitting",onClick:()=>void U.mutateAsync(),children:"Submit manual code"})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-3",children:[e.jsx(l,{pending:F.isPending,pendingLabel:"Saving connection",disabled:!T,onClick:()=>void F.mutateAsync(),children:"Save connection"}),e.jsxs(l,{variant:"secondary",pending:K.isPending,pendingLabel:"Testing",disabled:a.provider==="openai-codex"?!a.id:a.provider==="mock"?!1:!a.id&&!a.apiKey.trim(),onClick:()=>void K.mutateAsync(),children:[e.jsx(H,{className:"size-4"}),"Test connection"]})]}),M?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm text-white/72",children:M}):null]})]}),e.jsxs(j,{className:"grid gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx($,{className:"size-4 text-[var(--secondary)]"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-white",children:"Connected agents"}),e.jsx("div",{className:"text-xs leading-5 text-white/52",children:"Each connection registers its own chat-facing agent identity."})]})]}),e.jsxs("div",{className:"grid gap-3",children:[h.length===0?e.jsx("div",{className:"rounded-[20px] border border-dashed border-white/10 bg-white/[0.02] px-4 py-5 text-sm leading-6 text-white/58",children:"No external model connection yet. Add one with OAuth or API credentials and Forge will expose it as a first-class agent."}):null,h.map(t=>e.jsxs("div",{className:"grid gap-3 rounded-[20px] bg-white/[0.04] p-4",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-white",children:t.label}),e.jsxs("div",{className:"mt-1 text-xs text-white/46",children:[t.agentLabel," · ",t.provider," ·"," ",t.model]})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(l,{variant:"secondary",onClick:()=>{c(le(t)),b(null),u("")},children:"Edit"}),e.jsx(l,{variant:"secondary",pending:P.isPending,pendingLabel:"Deleting",onClick:()=>void P.mutateAsync(t.id),children:e.jsx(Z,{className:"size-4"})})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(p,{className:"bg-white/[0.06] text-white/78",children:t.authMode==="oauth"?"OAuth":"API key"}),e.jsx(p,{className:"bg-white/[0.06] text-white/78",children:t.status}),e.jsx(p,{className:"bg-white/[0.06] text-white/78",children:t.baseUrl}),t.accountLabel?e.jsx(p,{className:"bg-white/[0.06] text-white/78",children:t.accountLabel}):null]})]},t.id))]})]})]})]})}export{je as SettingsModelsPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r,j as e,aC as W,bg as H,c7 as T,cD as Y,cE as Z}from"./vendor-DHkYh85p.js";import{j as X,i as Q,k as x}from"./state-B-4sS1xO.js";import{S as J}from"./settings-section-nav-DSOuht_F.js";import{P as ee}from"./page-hero-DRy5b2MU.js";import{bV as ie,bW as se,bX as te,bY as ae,bZ as ne,L as re,E as q,B as p,C as w,c as j,aq as de,I as l,b_ as le,b$ as ce}from"./index-CF4J4R9L.js";import"./board-BkDRaMp6.js";import"./ui-C13Nbgas.js";import"./motion-BeD44FeG.js";import"./forms-BFlTgZ3W.js";import"./graph-D6JLqDbD.js";const R=[{value:"gpt-5.4",label:"GPT-5.4",description:"Highest quality drafting for long, connected wiki pages."},{value:"gpt-5.4-mini",label:"GPT-5.4 mini",description:"Balanced speed and quality for regular ingest jobs."},{value:"gpt-5.4-nano",label:"GPT-5.4 nano",description:"Fastest and cheapest option for smaller imports."}];R[1].value;const oe="medium",me="medium";function he(s){const t=s==null?void 0:s.reasoningEffort;return t==="none"||t==="low"||t==="medium"||t==="high"||t==="xhigh"?t:oe}function xe(s){const t=s==null?void 0:s.verbosity;return t==="low"||t==="medium"||t==="high"?t:me}function z(s){var m;return{model:((m=R.find(g=>g.value===s.model))==null?void 0:m.label)??s.model,reasoning:he(s.metadata),verbosity:xe(s.metadata),hasKey:!!s.secretId}}function ke(){var F,O;const s=X(),[t,m]=r.useState(""),[g,y]=r.useState(""),[N,f]=r.useState("personal"),[u,U]=r.useState("Fast wiki search"),[b,B]=r.useState("text-embedding-3-small"),[k,_]=r.useState("https://api.openai.com/v1"),[S,C]=r.useState(""),[L,D]=r.useState("1200"),[P,G]=r.useState("200"),c=Q({queryKey:["forge-wiki-settings"],queryFn:le}),V=Q({queryKey:["forge-settings"],queryFn:ce}),h=async()=>{await Promise.all([s.invalidateQueries({queryKey:["forge-wiki-settings"]}),s.invalidateQueries({queryKey:["forge-wiki-pages"]}),s.invalidateQueries({queryKey:["forge-wiki-page"]}),s.invalidateQueries({queryKey:["forge-wiki-search"]})])},K=x({mutationFn:()=>ie({label:t.trim(),description:g.trim(),visibility:N}),onSuccess:async()=>{m(""),y(""),f("personal"),await h()}}),A=x({mutationFn:()=>se({label:u.trim(),model:b.trim(),baseUrl:k.trim(),apiKey:S.trim()||void 0,chunkSize:Number(L),chunkOverlap:Number(P)}),onSuccess:async()=>{C(""),await h()}}),I=x({mutationFn:({kind:i,profileId:o})=>te(i,o),onSuccess:h}),E=x({mutationFn:()=>ae(),onSuccess:h}),M=x({mutationFn:()=>ne(),onSuccess:h});if(c.isLoading)return e.jsx(re,{eyebrow:"KarpaWiki settings",title:"Loading KarpaWiki controls",description:"Fetching spaces and profile configuration for KarpaWiki."});if(c.isError)return e.jsx(q,{eyebrow:"KarpaWiki settings",error:c.error,onRetry:()=>void c.refetch()});const n=(F=c.data)==null?void 0:F.settings;if(!n)return e.jsx(q,{eyebrow:"KarpaWiki settings",error:new Error("Forge returned an empty KarpaWiki settings payload."),onRetry:()=>void c.refetch()});const d=n.llmProfiles.find(i=>i.enabled)??n.llmProfiles[0]??null,v=d?z(d):null,$="Canonical knowledge lives in SQLite notes, with Forge maintaining metadata, links, search, and optional embedding indexes in the database. Text search and entity-linked search work without embeddings, while semantic search stays additive and profile-driven. Ingest jobs can create pages and media assets now, with room for richer OCR, transcription, and multimodal compilation later.",a=(O=V.data)==null?void 0:O.settings.modelSettings.forgeAgent.wiki;return e.jsxs("div",{className:"mx-auto grid w-full max-w-[1440px] gap-5",children:[e.jsx(ee,{eyebrow:"SQLite memory",title:"KarpaWiki Settings",titleText:"KarpaWiki Settings",description:"Configure SQLite-backed spaces, parse models, and embedding profiles for the KarpaWiki memory system.",badge:`${n.spaces.length} spaces · ${n.embeddingProfiles.length} embedding profiles`,actions:e.jsxs(e.Fragment,{children:[e.jsx(p,{variant:"secondary",pending:E.isPending,pendingLabel:"Syncing",onClick:()=>void E.mutateAsync(),children:"Refresh indexes"}),e.jsx(p,{pending:M.isPending,pendingLabel:"Reindexing",onClick:()=>void M.mutateAsync(),disabled:n.embeddingProfiles.length===0,children:"Reindex embeddings"})]})}),e.jsx(J,{}),e.jsxs("div",{className:"grid gap-5",children:[e.jsxs(w,{className:"grid gap-4",children:[e.jsx("div",{className:"flex items-center gap-3",children:e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-white",children:"Auto-ingest model"}),e.jsx("div",{className:"text-xs leading-5 text-white/50",children:"KarpaWiki ingest now reads its credentials and model slot from the dedicated Models settings page instead of owning the OpenAI setup flow here."})]})}),e.jsxs("div",{className:"grid gap-4 xl:grid-cols-[minmax(0,1.8fr)_minmax(24rem,0.9fr)]",children:[e.jsxs("div",{className:"grid gap-5 rounded-[28px] border border-white/8 bg-[linear-gradient(180deg,rgba(22,32,49,0.9),rgba(12,18,31,0.9))] p-6",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Current profile"}),e.jsx("div",{className:"mt-2 text-xl font-semibold text-white",children:(a==null?void 0:a.connectionLabel)??(d==null?void 0:d.label)??"No external KarpaWiki model selected"}),e.jsx("div",{className:"mt-2 max-w-3xl text-sm leading-6 text-white/58",children:a!=null&&a.connectionLabel?"Forge now resolves wiki ingest through the selected Models connection and syncs the managed wiki profile automatically.":"Pick a Models connection when you want Forge wiki ingest to run through the OpenAI API or a local compatible endpoint."})]}),e.jsx(W,{to:"/settings/models",className:"inline-flex min-h-11 items-center rounded-[16px] bg-white/[0.08] px-4 py-3 text-sm text-white transition hover:bg-white/[0.12]",children:"Open model settings"})]}),e.jsxs("div",{className:"grid gap-3 lg:grid-cols-3",children:[e.jsxs("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.03] px-4 py-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/40",children:"Model"}),e.jsx("div",{className:"mt-2 text-white",children:(a==null?void 0:a.model)??(v==null?void 0:v.model)??"Not set"})]}),e.jsxs("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.03] px-4 py-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/40",children:"Provider"}),e.jsx("div",{className:"mt-2 text-white",children:(a==null?void 0:a.connectionLabel)??"Not set"})]}),e.jsxs("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.03] px-4 py-3",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.16em] text-white/40",children:"Endpoint"}),e.jsx("div",{className:"mt-2 flex items-center gap-2 text-white",children:(a==null?void 0:a.baseUrl)??(d==null?void 0:d.baseUrl)??"Not set"})]})]})]}),e.jsxs("div",{className:"grid gap-3 rounded-[28px] border border-white/8 bg-white/[0.03] p-6",children:[e.jsx("div",{className:"text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Supported controls"}),e.jsxs("div",{className:"text-sm leading-6 text-white/58",children:["OpenAI API and local compatible endpoints are configured under Settings ","->"," Models. OpenAI Codex OAuth lives there as a chat agent path, while Wiki keeps the SQLite memory controls here and consumes the selected ingest model slot."]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:["GPT-5.4","GPT-5.4 mini","GPT-5.4 nano"].map(i=>e.jsx(j,{className:"bg-white/[0.06] text-white/78",children:i},i))}),e.jsxs(W,{to:"/settings/models",className:"inline-flex min-h-11 items-center rounded-[16px] bg-white/[0.08] px-4 py-3 text-sm text-white transition hover:bg-white/[0.12]",children:["Open model settings",e.jsx(H,{className:"ml-2 size-4"})]})]})]}),e.jsxs("div",{className:"grid gap-3",children:[n.llmProfiles.length===0?e.jsx("div",{className:"rounded-[18px] border border-dashed border-white/10 bg-white/[0.02] px-4 py-5 text-sm leading-6 text-white/58",children:"No LLM profile yet. Set up OpenAI once, test it, and Forge will use it for wiki auto-ingest."}):null,n.llmProfiles.map(i=>{const o=z(i);return e.jsxs("div",{className:"grid gap-3 rounded-[18px] bg-white/[0.04] px-4 py-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"text-white",children:i.label}),e.jsxs("div",{className:"mt-1 text-xs text-white/46",children:[o.model," · thinking ",o.reasoning," · verbosity ",o.verbosity]})]}),e.jsx("div",{className:"flex items-center gap-2",children:e.jsx("button",{type:"button",className:"rounded-full p-2 text-white/48 transition hover:bg-white/[0.08] hover:text-white",onClick:()=>void I.mutateAsync({kind:"llm",profileId:i.id}),children:e.jsx(T,{className:"size-4"})})})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 text-xs text-white/58",children:[e.jsx(j,{className:"bg-white/[0.06] text-white/76",children:i.baseUrl}),e.jsx(j,{className:"bg-white/[0.06] text-white/76",children:o.hasKey?"key saved":"key missing"})]})]},i.id)})]})]}),e.jsxs("div",{className:"grid gap-5",children:[e.jsxs(w,{className:"grid gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Y,{className:"size-4 text-[var(--secondary)]"}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("div",{className:"text-sm text-white",children:"Spaces"}),e.jsx(de,{content:$,label:"Explain the wiki operating model"})]}),e.jsx("div",{className:"text-xs leading-5 text-white/50",children:"Personal and shared wiki spaces map to explicit SQLite namespaces."})]})]}),e.jsx("div",{className:"grid gap-3",children:n.spaces.map(i=>e.jsxs("div",{className:"grid gap-1 rounded-[18px] bg-white/[0.04] px-4 py-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"text-white",children:i.label}),e.jsx("div",{className:"text-xs uppercase tracking-[0.16em] text-white/42",children:i.visibility})]}),e.jsx("div",{className:"text-xs text-white/46",children:i.slug}),e.jsx("div",{className:"text-sm text-white/60",children:i.description||"No description yet."})]},i.id))}),e.jsxs("div",{className:"grid gap-3 rounded-[20px] bg-white/[0.03] p-4",children:[e.jsx(l,{value:t,onChange:i=>m(i.target.value),placeholder:"New space label"}),e.jsx(l,{value:g,onChange:i=>y(i.target.value),placeholder:"Description"}),e.jsxs("select",{className:"rounded-[16px] border border-white/10 bg-white/[0.04] px-3 py-3 text-sm text-white",value:N,onChange:i=>f(i.target.value),children:[e.jsx("option",{value:"personal",children:"Personal"}),e.jsx("option",{value:"shared",children:"Shared"})]}),e.jsx(p,{pending:K.isPending,pendingLabel:"Creating",disabled:!t.trim(),onClick:()=>void K.mutateAsync(),children:"Create space"})]})]}),e.jsxs(w,{className:"grid gap-4",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(Z,{className:"size-4 text-[var(--secondary)]"}),e.jsxs("div",{children:[e.jsx("div",{className:"text-sm text-white",children:"Embedding profiles"}),e.jsx("div",{className:"text-xs leading-5 text-white/50",children:"Semantic search stays opt-in. The recommended starter is fast and cheap, with heading-aware chunking for agent memory retrieval."})]})]}),e.jsx("div",{className:"grid gap-3",children:n.embeddingProfiles.map(i=>e.jsxs("div",{className:"grid gap-2 rounded-[18px] bg-white/[0.04] px-4 py-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"text-white",children:i.label}),e.jsx("button",{type:"button",className:"rounded-full p-2 text-white/48 transition hover:bg-white/[0.08] hover:text-white",onClick:()=>void I.mutateAsync({kind:"embedding",profileId:i.id}),children:e.jsx(T,{className:"size-4"})})]}),e.jsxs("div",{className:"text-xs text-white/46",children:[i.model," · ",i.baseUrl]}),e.jsxs("div",{className:"text-sm text-white/60",children:["chunkSize ",i.chunkSize," · overlap"," ",i.chunkOverlap]})]},i.id))}),e.jsxs("div",{className:"grid gap-3 rounded-[20px] bg-white/[0.03] p-4",children:[e.jsx(l,{value:u,onChange:i=>U(i.target.value),placeholder:"Profile label"}),e.jsx(l,{value:b,onChange:i=>B(i.target.value),placeholder:"Model"}),e.jsx(l,{value:k,onChange:i=>_(i.target.value),placeholder:"Base URL"}),e.jsx(l,{value:S,onChange:i=>C(i.target.value),placeholder:"API key (optional)",type:"password"}),e.jsxs("div",{className:"grid gap-3 md:grid-cols-2",children:[e.jsx(l,{value:L,onChange:i=>D(i.target.value),placeholder:"Chunk size",type:"number"}),e.jsx(l,{value:P,onChange:i=>G(i.target.value),placeholder:"Chunk overlap",type:"number"})]}),e.jsx(p,{pending:A.isPending,pendingLabel:"Saving",disabled:!u.trim()||!b.trim(),onClick:()=>void A.mutateAsync(),children:"Save embedding profile"})]})]})]})]})]})}export{ke as SettingsWikiPage};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{r as c,j as e,b3 as Ne,cb as pt,b4 as ze,bT as ut,c7 as mt}from"./vendor-DHkYh85p.js";import{u as gt,a as xt,D as ft,c as bt,S as wt,v as yt,d as vt,P as jt,b as It,C as Nt}from"./board-BkDRaMp6.js";import{bl as te,Q as kt,bk as St,F as k,I as F,j as Ze,a0 as Tt,a1 as Ct,b as P,c as C,U as B,T as ce,V as Ke,Z as he,B as D,W as Mt,al as Pt}from"./index-CF4J4R9L.js";function Je(i){return[{id:"title",label:"Strategy title is set",satisfied:i.title.trim().length>0},{id:"graph",label:"Graph contains at least one linked project or task",satisfied:i.graph.nodes.length>0},{id:"targets",label:"At least one target goal or project is selected",satisfied:i.targetGoalIds.length>0||i.targetProjectIds.length>0},{id:"narrative",label:"The plan already names an overview or end state",satisfied:i.overview.trim().length>0||i.endStateDescription.trim().length>0}]}function Et(i){return Je(i).every(p=>p.satisfied)}function Dt(i){return[{id:"coverage",label:"Agreed work moving",value:i.planCoverageScore,detail:`${i.startedNodeCount}/${i.totalNodeCount} agreed steps have started or finished.`},{id:"order",label:"Order respected",value:i.sequencingScore,detail:`${i.outOfOrderNodeIds.length} step${i.outOfOrderNodeIds.length===1?"":"s"} started before prerequisites were complete.`},{id:"scope",label:"Scope held",value:i.scopeDisciplineScore,detail:`${i.offPlanEntityCount} unagreed item${i.offPlanEntityCount===1?"":"s"} are inside the strategy scope, ${i.offPlanActiveEntityCount} still active.`},{id:"satisfaction",label:"End-state satisfaction",value:i.qualityScore,detail:`${i.targetProgressScore}% target progress with ${i.blockedNodeIds.length} blocked step${i.blockedNodeIds.length===1?"":"s"}.`}]}function Gt(i){return i.trim().toLowerCase()}function J(i,p){return i.includes(p)?i.filter(r=>r!==p):[...i,p]}function Qe(i,p){return i.some(r=>r.entityType===p.entityType&&r.entityId===p.entityId)?i.filter(r=>!(r.entityType===p.entityType&&r.entityId===p.entityId)):[...i,p]}function Fe(i,p){if(i.length!==p.length)return!1;const r=new Set(p);return i.every(u=>r.has(u))}function pe(i="project",p){return{id:`strategy_node_${Math.random().toString(36).slice(2,10)}`,entityType:i,entityId:"",branchLabel:"",notes:"",dependencyMode:"after_previous",customPredecessorIds:[],...p}}function $t(i){const p=new Map(i.graph.nodes.map(m=>[m.id,m])),r=new Map(i.graph.nodes.map(m=>[m.id,0])),u=new Map,h=new Map(i.graph.nodes.map((m,w)=>[m.id,w]));for(const m of i.graph.nodes)u.set(m.id,[]);for(const m of i.graph.edges)r.set(m.to,(r.get(m.to)??0)+1),u.set(m.from,[...u.get(m.from)??[],m.to]);const o=i.graph.nodes.filter(m=>(r.get(m.id)??0)===0).sort((m,w)=>(h.get(m.id)??0)-(h.get(w.id)??0)).map(m=>m.id),g=[];for(;o.length>0;){o.sort((y,G)=>(h.get(y)??0)-(h.get(G)??0));const m=o.shift();if(!m)continue;const w=p.get(m);if(w){g.push(w);for(const y of u.get(m)??[]){const G=(r.get(y)??0)-1;r.set(y,G),G===0&&o.push(y)}}}return g.length===i.graph.nodes.length?g:i.graph.nodes}function qt(i){const p=new Map;for(const u of i.graph.nodes)p.set(u.id,[]);for(const u of i.graph.edges)p.set(u.to,[...p.get(u.to)??[],u.from]);const r=$t(i);return{title:i.title,overview:i.overview,endStateDescription:i.endStateDescription,status:i.status,userId:i.userId??null,targetGoalIds:i.targetGoalIds,targetProjectIds:i.targetProjectIds,linkedEntities:i.linkedEntities,nodes:r.map((u,h)=>{const o=p.get(u.id)??[],g=r[h-1],m=g?p.get(g.id)??[]:[];let w="custom";return o.length===0?w="start":g&&Fe(o,[g.id])?w="after_previous":g&&o.length>0&&Fe(o,m)&&(w="parallel_with_previous"),pe(u.entityType,{id:u.id,entityId:u.entityId,branchLabel:u.branchLabel,notes:u.notes,dependencyMode:w,customPredecessorIds:o})})}}function Ue(i){const p=new Map,r=new Set;for(const[u,h]of i.entries()){const o=i[u-1];let g;switch(h.dependencyMode){case"after_previous":g=o?[o.id]:[];break;case"parallel_with_previous":g=o?[...p.get(o.id)??[]]:[];break;case"custom":g=h.customPredecessorIds.filter(m=>r.has(m));break;case"start":default:g=[];break}p.set(h.id,g),r.add(h.id)}return p}function He(i){const p=Ue(i),r=new Set,u=new Set;function h(o){if(u.has(o))return!0;if(r.has(o))return!1;r.add(o),u.add(o);for(const g of p.get(o)??[])if(h(g))return!0;return u.delete(o),!1}return i.some(o=>h(o.id))}const We={title:"",overview:"",endStateDescription:"",status:"active",userId:null,targetGoalIds:[],targetProjectIds:[],linkedEntities:[],nodes:[pe("project",{dependencyMode:"start"})]};function Z(i,p){const r=p[0];return{title:"",description:"",goalId:(r==null?void 0:r.goalId)??"",projectId:(r==null?void 0:r.id)??"",userId:(r==null?void 0:r.userId)??i,priority:"medium",effort:"deep",energy:"steady",points:60}}function At(i,p,r){const u=Ue(i.nodes),h=new Set(i.nodes.filter(o=>o.entityId).map(o=>o.id));return{nodes:i.nodes.filter(o=>o.entityId).map(o=>{var g,m;return{id:o.id,entityType:o.entityType,entityId:o.entityId,title:o.entityType==="project"?((g=p.get(o.entityId))==null?void 0:g.title)??o.entityId:((m=r.get(o.entityId))==null?void 0:m.title)??o.entityId,branchLabel:o.branchLabel.trim(),notes:o.notes.trim()}}),edges:i.nodes.flatMap(o=>h.has(o.id)?(u.get(o.id)??[]).filter(g=>h.has(g)).map(g=>({from:g,to:o.id,label:"",condition:""})):[])}}function Ye(i){return((i==null?void 0:i.progress)??0)/100}function Bt(i){switch(i==null?void 0:i.status){case"done":return 1;case"in_progress":return .66;case"focus":return .5;case"blocked":return .25;default:return 0}}function Lt(i){const{draft:p,graph:r,goals:u,projects:h,projectsById:o,tasks:g,tasksById:m}=i,w=new Map(r.nodes.map(d=>[d.id,d.entityType==="project"?Ye(o.get(d.entityId)):Bt(m.get(d.entityId))])),y=new Map;for(const d of r.nodes)y.set(d.id,[]);for(const d of r.edges)y.set(d.to,[...y.get(d.to)??[],d.from]);const G=r.nodes.filter(d=>(w.get(d.id)??0)>=1).map(d=>d.id),H=r.nodes.filter(d=>(w.get(d.id)??0)>0).map(d=>d.id),W=r.nodes.filter(d=>{var f,b;return d.entityType==="project"?((f=o.get(d.entityId))==null?void 0:f.status)==="paused":((b=m.get(d.entityId))==null?void 0:b.status)==="blocked"}).map(d=>d.id),n=r.nodes.filter(d=>(w.get(d.id)??0)<=0?!1:(y.get(d.id)??[]).some(b=>(w.get(b)??0)<1)).map(d=>d.id),T=r.nodes.filter(d=>(w.get(d.id)??0)>=1?!1:(y.get(d.id)??[]).every(b=>(w.get(b)??0)>=1)).map(d=>d.id),N=new Map(u.map(d=>[d.id,d])),_=p.targetGoalIds.map(d=>{var b;const f=g.filter(I=>I.goalId===d);return f.length===0?((b=N.get(d))==null?void 0:b.status)==="completed"?1:0:f.filter(I=>I.status==="done").length/f.length}),O=p.targetProjectIds.map(d=>Ye(o.get(d))),j=[..._,...O],$=r.nodes.length===0?0:r.nodes.reduce((d,f)=>d+(w.get(f.id)??0),0)/r.nodes.length,Y=j.length===0?$:j.reduce((d,f)=>d+f,0)/j.length,ue=new Set(r.nodes.filter(d=>d.entityType==="project").map(d=>d.entityId)),R=new Set(r.nodes.filter(d=>d.entityType==="task").map(d=>d.entityId)),L=new Set,z=new Set,v=new Set;for(const d of p.targetProjectIds){const f=h.find(b=>b.id===d);if(f&&!ue.has(f.id)&&f.status!=="completed"){const b=`project:${f.id}`;L.add(b),z.add(b)}for(const b of g.filter(I=>I.projectId===d))if(!R.has(b.id)&&["focus","in_progress","done","blocked"].includes(b.status)){const I=`task:${b.id}`;L.add(I),b.status==="done"?v.add(I):z.add(I)}}for(const d of p.targetGoalIds)for(const f of g.filter(b=>b.goalId===d))if(!R.has(f.id)&&["focus","in_progress","done","blocked"].includes(f.status)){const b=`task:${f.id}`;L.add(b),f.status==="done"?v.add(b):z.add(b)}const S=Math.max(1,r.nodes.length),se=L.size,K=W.length/S,U=Math.max(0,Math.min(100,Math.round($*100))),E=Math.max(0,Math.min(100,Math.round(100-n.length/S*100))),ie=Math.max(0,Math.min(100,Math.round(100-se/S*100))),X=Math.max(0,Math.min(100,Math.round(Math.max(0,Math.min(1,Y*.8+(1-K)*.2))*100))),q=Math.max(0,Math.min(100,Math.round(Y*100)));return{alignmentScore:Math.max(0,Math.min(100,Math.round(U*.35+E*.3+ie*.2+X*.15))),planCoverageScore:U,sequencingScore:E,scopeDisciplineScore:ie,qualityScore:X,targetProgressScore:q,completedNodeCount:G.length,startedNodeCount:H.length,readyNodeCount:T.length,totalNodeCount:S,completedTargetCount:j.filter(d=>d>=1).length,totalTargetCount:j.length,offPlanEntityCount:se,offPlanActiveEntityCount:z.size,offPlanCompletedEntityCount:v.size,activeNodeIds:T.slice(0,8),nextNodeIds:T.slice(0,5),blockedNodeIds:W,outOfOrderNodeIds:n}}function _t({node:i,index:p,total:r,projectsById:u,tasksById:h,usersById:o,allNodes:g,onUpdate:m,onRemove:w}){const{attributes:y,listeners:G,setNodeRef:H,transform:W,transition:n,isDragging:T}=It({id:i.id}),N=i.entityType==="project"?u.get(i.entityId):h.get(i.entityId),_=N&&"userId"in N&&N.userId?o.get(N.userId)??N.user??null:null,O=g.slice(0,p);return e.jsxs("div",{ref:H,style:{transform:Nt.Transform.toString(W),transition:n},className:he("min-w-0 overflow-hidden rounded-[24px] border border-white/8 bg-[rgba(8,14,26,0.8)] p-4 shadow-[0_24px_60px_rgba(0,0,0,0.2)]",T&&"opacity-70"),children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{className:"flex min-w-0 items-start gap-3",children:[e.jsx("button",{type:"button",className:"mt-1 rounded-full bg-white/[0.06] p-2 text-white/58 transition hover:bg-white/[0.1] hover:text-white",...y,...G,children:e.jsx(ut,{className:"size-4"})}),e.jsxs("div",{className:"min-w-0",children:[e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(C,{className:"bg-white/[0.08] text-white/76",children:["Step ",p+1]}),e.jsx(C,{className:"bg-white/[0.08] text-white/76",children:i.entityType}),N?e.jsx(P,{kind:i.entityType,label:N.title,compact:!0,gradient:!1}):null]}),e.jsx("div",{className:"mt-3 text-base font-medium text-white",children:(N==null?void 0:N.title)||"Select an entity for this step"}),e.jsx("div",{className:"mt-2 break-words text-sm leading-6 text-white/54",children:i.notes||(N&&"description"in N?N.description:"")||"Add an optional note if this phase needs intent or setup context."}),_?e.jsx("div",{className:"mt-3",children:e.jsx(B,{user:_,compact:!0})}):null]})]}),e.jsxs(D,{type:"button",variant:"secondary",size:"sm",className:"w-full sm:w-auto",disabled:r===1,onClick:()=>w(i.id),children:[e.jsx(mt,{className:"size-4"}),"Remove"]})]}),e.jsxs("div",{className:"mt-4 grid gap-4 xl:grid-cols-[minmax(0,0.9fr)_minmax(0,1.1fr)]",children:[e.jsx(k,{label:"Relationship to the flow",labelHelp:"Keep the sequence mostly linear in the form. Use parallel when this step should open beside the previous one, or custom only when the dependency is special.",children:e.jsx(Ze,{value:i.dependencyMode,columns:2,onChange:j=>m(i.id,{dependencyMode:j}),options:[{value:"start",label:"Start here",description:"This step opens immediately."},{value:"after_previous",label:"After previous",description:"Use the prior step as the gate."},{value:"parallel_with_previous",label:"Parallel with previous",description:"Open beside the prior branch."},{value:"custom",label:"Custom dependency",description:"Pick earlier steps manually."}]})}),e.jsxs("div",{className:"grid gap-4",children:[e.jsx(k,{label:"Branch label",children:e.jsx(F,{value:i.branchLabel,onChange:j=>m(i.id,{branchLabel:j.target.value}),placeholder:"Core path, fallback lane, support branch"})}),e.jsx(k,{label:"Step note",children:e.jsx(ce,{value:i.notes,onChange:j=>m(i.id,{notes:j.target.value}),placeholder:"Explain what has to be true before or after this step."})})]})]}),i.dependencyMode==="custom"?e.jsxs("div",{className:"mt-4 rounded-[20px] border border-white/8 bg-white/[0.03] p-4",children:[e.jsx("div",{className:"text-sm font-medium text-white",children:"Depends on"}),e.jsx("div",{className:"mt-3 grid gap-2",children:O.length===0?e.jsx("div",{className:"text-sm text-white/52",children:"No earlier steps available yet."}):O.map(j=>{const $=j.entityType==="project"?u.get(j.entityId):h.get(j.entityId);return e.jsxs("label",{className:"flex items-start justify-between gap-3 rounded-[16px] bg-white/[0.04] px-4 py-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium text-white",children:($==null?void 0:$.title)||`Step ${g.indexOf(j)+1}`}),e.jsx("div",{className:"mt-1 text-xs leading-5 text-white/52",children:j.branchLabel||j.entityType})]}),e.jsx("input",{type:"checkbox",checked:i.customPredecessorIds.includes(j.id),onChange:()=>m(i.id,{customPredecessorIds:J(i.customPredecessorIds,j.id)})})]},j.id)})})]}):null]})}function Kt({open:i,pending:p=!1,editingStrategy:r,goals:u,projects:h,tasks:o,habits:g,strategies:m,users:w,defaultUserId:y=null,initialStepId:G,onOpenChange:H,onSubmit:W}){const[n,T]=c.useState(We),[N,_]=c.useState(""),[O,j]=c.useState(""),[$,Y]=c.useState(""),[ue,R]=c.useState(null),[L,z]=c.useState([]),[v,S]=c.useState(Z(y,h)),[se,K]=c.useState(!1),[U,E]=c.useState(null),[ie,X]=c.useState(!1);c.useEffect(()=>{var s,a,l;if(!i)return;const t=r?qt(r):{...We,userId:y,nodes:[pe("project",{dependencyMode:"start"})]};T(t),_(""),j(""),Y(""),z([]),K(!1),S(Z(y,h).projectId&&t.targetProjectIds[0]?{...Z(y,h),goalId:((s=h.find(x=>x.id===t.targetProjectIds[0]))==null?void 0:s.goalId)??"",projectId:t.targetProjectIds[0]??((a=h[0])==null?void 0:a.id)??"",userId:((l=h.find(x=>x.id===t.targetProjectIds[0]))==null?void 0:l.userId)??y}:Z(y,h)),E(null),R(null)},[y,r,i,h]);const q=c.useDeferredValue(N),M=c.useDeferredValue(O),d=c.useDeferredValue($),f=c.useMemo(()=>{const t=new Set(L.map(s=>s.id));return[...L,...o.filter(s=>!t.has(s.id))]},[L,o]),b=c.useMemo(()=>new Map(u.map(t=>[t.id,t])),[u]),I=c.useMemo(()=>new Map(h.map(t=>[t.id,t])),[h]),V=c.useMemo(()=>new Map(f.map(t=>[t.id,t])),[f]),ke=c.useMemo(()=>new Map(w.map(t=>[t.id,t])),[w]),me=w.find(t=>t.id===y)??null,ge=w.find(t=>t.id===n.userId)??me,A=(t,s,a)=>{const l=Gt(t);return l.length===0||St(s,a).includes(l)},Se=c.useMemo(()=>u.filter(t=>A(M,[t.title,t.description],t.user)),[M,u]),xe=c.useMemo(()=>u.filter(t=>A(q,[t.title,t.description],t.user)),[u,q]),fe=c.useMemo(()=>h.filter(t=>A(q,[t.title,t.description,t.goalTitle,t.status],t.user)),[q,h]),Te=c.useMemo(()=>h.filter(t=>A(M,[t.title,t.description,t.goalTitle,t.status],t.user)),[M,h]),Ce=c.useMemo(()=>f.filter(t=>A(M,[t.title,t.description,t.owner,t.status],t.user)),[f,M]),Me=c.useMemo(()=>g.filter(t=>A(M,[t.title,t.description,t.frequency,t.status],t.user)),[M,g]),Pe=c.useMemo(()=>m.filter(t=>t.id!==(r==null?void 0:r.id)&&A(M,[t.title,t.overview,t.endStateDescription,t.status],t.user)),[M,r==null?void 0:r.id,m]),be=c.useMemo(()=>[...Se.map(s=>({key:`goal:${s.id}`,entityType:"goal",entityId:s.id,label:s.title,description:te(s.description,s.user,"Goal"),user:s.user??null})),...Te.map(s=>({key:`project:${s.id}`,entityType:"project",entityId:s.id,label:s.title,description:te(`${s.goalTitle}${s.goalTitle?" · ":""}${s.status}`,s.user,`Project · ${s.goalTitle}`),user:s.user??null})),...Ce.map(s=>({key:`task:${s.id}`,entityType:"task",entityId:s.id,label:s.title,description:te(`${s.status} · ${s.owner}`,s.user,`Task · ${s.owner}`),user:s.user??null})),...Me.map(s=>({key:`habit:${s.id}`,entityType:"habit",entityId:s.id,label:s.title,description:te(s.description,s.user,"Habit"),user:s.user??null})),...Pe.map(s=>({key:`strategy:${s.id}`,entityType:"strategy",entityId:s.id,label:s.title,description:te(s.overview,s.user,"Strategy"),user:s.user??null}))].sort((s,a)=>s.label.localeCompare(a.label)),[Se,Me,Te,Pe,Ce]),Q=c.useMemo(()=>At(n,I,V),[n,I,V]),Ee=c.useMemo(()=>Lt({draft:n,graph:Q,goals:u,projects:h,projectsById:I,tasks:f,tasksById:V}),[f,n,Q,u,h,I,V]),Xe=c.useMemo(()=>[...Je({title:n.title,overview:n.overview,endStateDescription:n.endStateDescription,targetGoalIds:n.targetGoalIds,targetProjectIds:n.targetProjectIds,graph:Q}),{id:"acyclic",label:"Graph stays directed and non-looping",satisfied:!He(n.nodes)}],[n.endStateDescription,n.nodes,n.overview,n.targetGoalIds,n.targetProjectIds,n.title,Q]),we=c.useMemo(()=>Et({title:n.title,overview:n.overview,endStateDescription:n.endStateDescription,targetGoalIds:n.targetGoalIds,targetProjectIds:n.targetProjectIds,graph:Q}),[n.endStateDescription,n.overview,n.targetGoalIds,n.targetProjectIds,n.title,Q]),Ve=c.useMemo(()=>Dt(Ee),[Ee]),ye=c.useMemo(()=>{if(!n.title.trim())return"Strategy title is required.";if(n.nodes.length===0)return"Add at least one project or task step.";const t=new Set;for(const s of n.nodes){if(!s.entityId)return"Every step needs a linked project or task.";const a=`${s.entityType}:${s.entityId}`;if(t.has(a))return"Each project or task should appear only once in the sequence.";t.add(a)}return He(n.nodes)?"Strategy graph must stay directed and non-loopy.":null},[n.nodes,n.title]),et=t=>t==="sequence"?ue??ye??(we?null:"This can still be saved as a draft. Add the target plus the overview or end state later, then lock it as the contract from the strategy detail page."):null,De=c.useMemo(()=>u.filter(t=>A(d,[t.title,t.description],t.user)),[u,d]),ae=c.useMemo(()=>h.filter(t=>A(d,[t.title,t.description,t.goalTitle,t.status],t.user)),[h,d]),ne=c.useMemo(()=>f.filter(t=>A(d,[t.title,t.description,t.owner,t.status],t.user)),[f,d]),re=c.useMemo(()=>new Set(n.targetGoalIds),[n.targetGoalIds]),de=c.useMemo(()=>new Set(n.targetProjectIds),[n.targetProjectIds]),le=c.useMemo(()=>new Set(n.nodes.map(t=>`${t.entityType}:${t.entityId}`)),[n.nodes]),Ge=c.useMemo(()=>n.targetGoalIds.map(t=>b.get(t)).filter(t=>!!t),[n.targetGoalIds,b]),$e=c.useMemo(()=>n.targetProjectIds.map(t=>I.get(t)).filter(t=>!!t),[n.targetProjectIds,I]),qe=c.useMemo(()=>ae.filter(t=>de.has(t.id)||re.has(t.goalId)),[ae,re,de]),Ae=c.useMemo(()=>ne.filter(t=>de.has(t.projectId??"")||re.has(t.goalId??"")),[ne,re,de]),Be=c.useMemo(()=>xe.slice(0,8),[xe]),Le=c.useMemo(()=>fe.slice(0,8),[fe]),_e=c.useMemo(()=>be.slice(0,12),[be]),ve=c.useMemo(()=>De.slice(0,6),[De]),je=c.useMemo(()=>ae.slice(0,8),[ae]),Ie=c.useMemo(()=>ne.slice(0,10),[ne]),Oe=c.useMemo(()=>qe.slice(0,4),[qe]),Re=c.useMemo(()=>Ae.slice(0,6),[Ae]),tt=c.useMemo(()=>{if(!v.goalId)return h;const t=h.filter(s=>s.goalId===v.goalId);return t.length>0?t:h},[v.goalId,h]),st=d.length>0,it=ve.length>0||je.length>0||Ie.length>0,at=(t,s)=>{T(a=>({...a,nodes:a.nodes.map(l=>l.id===t?{...l,...s}:l)}))},ee=(t,s)=>{n.nodes.some(a=>a.entityType===t&&a.entityId===s)||T(a=>({...a,nodes:[...a.nodes,pe(t,{entityId:s,dependencyMode:a.nodes.length===0?"start":"after_previous"})]}))},nt=t=>{T(s=>{const a=s.nodes.filter(l=>l.id!==t);return{...s,nodes:a.map((l,x)=>({...l,dependencyMode:x===0&&l.dependencyMode==="after_previous"?"start":l.dependencyMode,customPredecessorIds:l.customPredecessorIds.filter(oe=>oe!==t)}))}})},rt=gt(xt(jt,{activationConstraint:{distance:6}})),dt=t=>{!t.over||t.active.id===t.over.id||T(s=>{const a=s.nodes.findIndex(x=>x.id===t.active.id),l=s.nodes.findIndex(x=>{var oe;return x.id===((oe=t.over)==null?void 0:oe.id)});return a<0||l<0?s:{...s,nodes:vt(s.nodes,a,l)}})},lt=()=>{const t=$.trim(),s=n.targetProjectIds.map(x=>I.get(x)).find(x=>!!x)??I.get(v.projectId)??h[0]??null,a=(s==null?void 0:s.goalId)??n.targetGoalIds[0]??"",l=h.find(x=>x.goalId===a&&(s?x.id===s.id:!0))??h.find(x=>x.goalId===a)??s;S(x=>({...Z(y,h),title:t||x.title,description:x.description,goalId:a,projectId:(l==null?void 0:l.id)??x.projectId,userId:(l==null?void 0:l.userId)??x.userId??y})),E(null),K(!0)},ot=async()=>{const t=I.get(v.projectId);if(!v.title.trim()){E("Task title is required.");return}if(!t){E("Pick a project for the new task.");return}X(!0),E(null);try{const s=ke.get(v.userId??t.userId??"")??t.user??ge??me,a=(await Pt({title:v.title.trim(),description:v.description.trim(),level:"task",owner:(s==null?void 0:s.displayName)??"Albert",userId:v.userId??t.userId??n.userId,assigneeUserIds:[],goalId:t.goalId,projectId:t.id,parentWorkItemId:null,priority:v.priority,status:"focus",effort:v.effort,energy:v.energy,dueDate:"",points:v.points,plannedDurationSeconds:86400,aiInstructions:"",executionMode:null,acceptanceCriteria:[],blockerLinks:[],completionReport:null,gitRefs:[],tagIds:[],notes:[]})).task;z(l=>[a,...l]),ee("task",a.id),S({...Z(y,h),goalId:t.goalId,projectId:t.id,userId:a.userId??t.userId??n.userId}),Y(""),K(!1)}catch(s){E(s instanceof Error?s.message:"Task creation failed.")}finally{X(!1)}},ct=async()=>{if(ye){R(ye);return}try{await W({title:n.title.trim(),overview:n.overview.trim(),endStateDescription:n.endStateDescription.trim(),status:n.status,userId:n.userId,targetGoalIds:n.targetGoalIds,targetProjectIds:n.targetProjectIds,linkedEntities:n.linkedEntities,graph:Q},r==null?void 0:r.id),R(null),H(!1)}catch(t){R(t instanceof Error?t.message:"Strategy save failed.")}},ht=[{id:"foundation",eyebrow:"Foundation",title:"Set the owner and the strategic frame",description:"Start with who owns the strategy, what the plan is called, and whether this should open as active, paused, or already landed.",render:(t,s)=>e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid gap-4 lg:grid-cols-[minmax(0,1fr)_minmax(16rem,0.8fr)]",children:[e.jsx(k,{label:"Strategy title",children:e.jsx(F,{value:t.title,onChange:a=>s({title:a.target.value}),placeholder:"Land the multi-user planning system"})}),e.jsx(k,{label:"Status",children:e.jsx(Ze,{value:t.status,onChange:a=>s({status:a}),options:[{value:"active",label:"Active",description:"Use this when the plan should drive work now."},{value:"paused",label:"Paused",description:"Keep the strategy visible without active pressure."},{value:"completed",label:"Completed",description:"The end state is already landed."}]})})]}),e.jsx(Tt,{value:t.userId,users:w,onChange:a=>s({userId:a}),label:"Owner user",defaultLabel:Ct(me),help:"Strategies can belong to a human or a bot even when the sequence spans multiple owners."}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(135deg,rgba(192,193,255,0.16),rgba(125,211,252,0.08))] px-5 py-5",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/46",children:"Live posture"}),e.jsxs("div",{className:"mt-2 flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"strategy",label:t.title.trim()||"Untitled strategy",compact:!0,gradient:!1}),e.jsx(C,{className:"bg-white/[0.12] text-white/86",children:t.status}),ge?e.jsx(B,{user:ge,compact:!0}):null]}),e.jsx("div",{className:"mt-3 text-sm leading-6 text-white/62",children:"This flow is built to keep strategy creation as guided as the other major entities in Forge: clear questions first, then a focused sequence stage at the end."})]})]})},{id:"objective",eyebrow:"Objective",title:"Define the objective and the end targets",description:"Capture what this strategy is coordinating, what done looks like, and which goals or projects are the real targets.",render:(t,s)=>e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid gap-4",children:[e.jsx(k,{label:"Overview",children:e.jsx(ce,{value:t.overview,onChange:a=>s({overview:a.target.value}),placeholder:"Explain what this strategy is coordinating and why it matters right now."})}),e.jsx(k,{label:"End state",children:e.jsx(ce,{value:t.endStateDescription,onChange:a=>s({endStateDescription:a.target.value}),placeholder:"Describe what reality should look like when this strategy lands."})})]}),e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(21,28,44,0.9),rgba(12,17,30,0.88))] px-5 py-5",children:[e.jsx(k,{label:"Search goals or projects",description:"Keep this page search-first. Add only the targets that truly define what this strategy is trying to land.",children:e.jsxs("div",{className:"flex items-center gap-3 rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-3",children:[e.jsx(Ne,{className:"size-4 text-white/42"}),e.jsx(F,{className:"border-none bg-transparent px-0 py-0",value:N,onChange:a=>_(a.target.value),placeholder:"Search goals, projects, owners, humans, or bots"})]})}),e.jsxs("div",{className:"mt-5 grid gap-4 xl:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Selected goals"}),e.jsx("div",{className:"mt-3 flex flex-wrap gap-2",children:Ge.length===0?e.jsx(C,{className:"bg-white/[0.08] text-white/62",children:"No target goals yet"}):Ge.map(a=>e.jsxs("button",{type:"button",className:"inline-flex items-center gap-2 rounded-full bg-[rgba(192,193,255,0.14)] px-3 py-1.5 text-sm text-white transition hover:bg-[rgba(192,193,255,0.2)]",onClick:()=>s({targetGoalIds:J(t.targetGoalIds,a.id)}),children:[e.jsx(P,{kind:"goal",label:a.title,compact:!0,gradient:!1}),e.jsx("span",{children:"Remove"})]},a.id))})]}),e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Selected projects"}),e.jsx("div",{className:"mt-3 flex flex-wrap gap-2",children:$e.length===0?e.jsx(C,{className:"bg-white/[0.08] text-white/62",children:"No target projects yet"}):$e.map(a=>e.jsxs("button",{type:"button",className:"inline-flex items-center gap-2 rounded-full bg-[rgba(192,193,255,0.14)] px-3 py-1.5 text-sm text-white transition hover:bg-[rgba(192,193,255,0.2)]",onClick:()=>s({targetProjectIds:J(t.targetProjectIds,a.id)}),children:[e.jsx(P,{kind:"project",label:a.title,compact:!0,gradient:!1}),e.jsx("span",{children:"Remove"})]},a.id))})]})]})]}),e.jsxs("div",{className:"grid gap-5 xl:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Goal matches"}),q?e.jsxs(C,{className:"bg-white/[0.08] text-white/72",children:[xe.length," found"]}):null]}),e.jsx("div",{className:"mt-3 grid gap-3",children:q?Be.length===0?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"No goals match this search yet."}):Be.map(a=>{const l=t.targetGoalIds.includes(a.id);return e.jsxs("button",{type:"button",className:he("rounded-[22px] border px-4 py-4 text-left transition",l?"border-[rgba(192,193,255,0.28)] bg-[rgba(192,193,255,0.14)] text-white":"border-white/8 bg-white/[0.04] text-white/72 hover:bg-white/[0.07]"),onClick:()=>s({targetGoalIds:J(t.targetGoalIds,a.id)}),children:[e.jsxs("div",{className:"flex min-w-0 flex-wrap items-center justify-between gap-2",children:[e.jsx(Ke,{kind:"goal",label:a.title,className:"max-w-full min-w-0"}),e.jsx(B,{user:a.user,compact:!0})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:a.description||"No strategic note attached yet."})]},a.id)}):e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"Search for the goal this strategy is meant to land."})})]}),e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Project matches"}),q?e.jsxs(C,{className:"bg-white/[0.08] text-white/72",children:[fe.length," found"]}):null]}),e.jsx("div",{className:"mt-3 grid gap-3",children:q?Le.length===0?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"No projects match this search yet."}):Le.map(a=>{const l=t.targetProjectIds.includes(a.id);return e.jsxs("button",{type:"button",className:he("rounded-[22px] border px-4 py-4 text-left transition",l?"border-[rgba(192,193,255,0.28)] bg-[rgba(192,193,255,0.14)] text-white":"border-white/8 bg-white/[0.04] text-white/72 hover:bg-white/[0.07]"),onClick:()=>s({targetProjectIds:J(t.targetProjectIds,a.id)}),children:[e.jsxs("div",{className:"flex min-w-0 flex-wrap items-center justify-between gap-2",children:[e.jsx(Ke,{kind:"project",label:a.title,className:"max-w-full min-w-0",showIcon:!1}),e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(C,{className:"bg-white/[0.08] text-white/70",children:a.goalTitle}),e.jsx(B,{user:a.user,compact:!0})]})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:a.description||"No project summary attached yet."})]},a.id)}):e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"Search for the concrete project this strategy should land or organize."})})]})]})]})},{id:"context",eyebrow:"Context",title:"Keep the right supporting entities in view",description:"Linked entities stay visible in the strategy context without becoming part of the main execution sequence.",render:(t,s)=>e.jsxs(e.Fragment,{children:[e.jsx(k,{label:"Search supporting context",description:"Search across goals, projects, tasks, habits, and other strategies.",children:e.jsxs("div",{className:"flex items-center gap-3 rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-3",children:[e.jsx(Ne,{className:"size-4 text-white/42"}),e.jsx(F,{className:"border-none bg-transparent px-0 py-0",value:O,onChange:a=>j(a.target.value),placeholder:"Search by title, owner, @handle, human, or bot"})]})}),e.jsx("div",{className:"flex flex-wrap gap-2",children:t.linkedEntities.length===0?e.jsx(C,{className:"bg-white/[0.08] text-white/62",children:"No extra linked context yet"}):t.linkedEntities.map(a=>{const l=be.find(x=>x.entityType===a.entityType&&x.entityId===a.entityId);return e.jsxs("button",{type:"button",className:"inline-flex items-center gap-1 rounded-full bg-[rgba(192,193,255,0.14)] px-3 py-1.5 text-sm text-white/82 transition hover:bg-[rgba(192,193,255,0.22)]",onClick:()=>s({linkedEntities:t.linkedEntities.filter(x=>!(x.entityType===a.entityType&&x.entityId===a.entityId))}),children:[e.jsx(pt,{className:"mr-1 size-3.5"}),(l==null?void 0:l.label)??`${a.entityType}:${a.entityId}`,e.jsx("span",{children:"Remove"})]},`${a.entityType}:${a.entityId}`)})}),e.jsx("div",{className:"grid gap-3",children:M?_e.length===0?e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"No supporting entities match this search yet."}):_e.map(a=>{const l=t.linkedEntities.some(x=>x.entityType===a.entityType&&x.entityId===a.entityId);return e.jsxs("label",{className:he("flex items-start justify-between gap-3 rounded-[20px] border px-4 py-4",l?"border-[rgba(192,193,255,0.24)] bg-[rgba(192,193,255,0.12)]":"border-white/8 bg-white/[0.04]"),children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:a.entityType,label:a.label,compact:!0,gradient:!1}),a.user?e.jsx(B,{user:a.user,compact:!0}):null]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:a.description})]}),e.jsx("input",{type:"checkbox",checked:l,onChange:()=>s({linkedEntities:Qe(t.linkedEntities,{entityType:a.entityType,entityId:a.entityId})})})]},a.key)}):e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"Search when you want to pull another entity into the background context. This keeps the page focused instead of dumping every record into one long list."})})]})},{id:"sequence",eyebrow:"Sequence",title:"Build the execution sequence",description:"Search, add steps, and create missing tasks.",render:()=>e.jsxs("div",{className:"grid min-w-0 gap-5",children:[e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-[linear-gradient(180deg,rgba(21,28,44,0.9),rgba(12,17,30,0.88))] px-5 py-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Search and add"}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:"Search goals, projects, tasks, humans, and bots."})]}),e.jsxs(C,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:[n.nodes.length," planned steps"]})]}),e.jsxs("div",{className:"mt-4 flex items-center gap-3 rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-3",children:[e.jsx(Ne,{className:"size-4 text-white/42"}),e.jsx(F,{className:"border-none bg-transparent px-0 py-0",value:$,onChange:t=>Y(t.target.value),placeholder:"Search goals, projects, tasks, owners, humans, or bots"})]}),e.jsxs("div",{className:"mt-4 grid gap-3",children:[e.jsxs(D,{type:"button",className:"w-full justify-start",variant:"secondary",onClick:lt,children:[e.jsx(ze,{className:"size-4"}),"Create new task"]}),se?e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.04] px-4 py-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-medium text-white",children:"New task"}),e.jsx("div",{className:"mt-1 text-sm text-white/54",children:"Add the task and place it in the sequence."})]}),e.jsx(D,{type:"button",variant:"secondary",className:"w-full sm:w-auto",onClick:()=>{K(!1),E(null)},children:"Close"})]}),e.jsxs("div",{className:"mt-4 grid gap-4",children:[e.jsx(k,{label:"Task title",children:e.jsx(F,{value:v.title,onChange:t=>S(s=>({...s,title:t.target.value})),placeholder:"Draft the shared strategy hierarchy view"})}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(k,{label:"Goal",children:e.jsxs("select",{value:v.goalId,onChange:t=>{const s=t.target.value,a=h.find(l=>l.goalId===s)??null;S(l=>({...l,goalId:s,projectId:(a==null?void 0:a.id)??"",userId:(a==null?void 0:a.userId)??l.userId??y}))},className:"min-h-10 rounded-[var(--radius-control)] border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.3)]",children:[e.jsx("option",{value:"",children:"Select goal"}),u.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})}),e.jsx(k,{label:"Project",children:e.jsxs("select",{value:v.projectId,onChange:t=>S(s=>{var a,l;return{...s,projectId:t.target.value,goalId:((a=I.get(t.target.value))==null?void 0:a.goalId)??s.goalId,userId:((l=I.get(t.target.value))==null?void 0:l.userId)??s.userId}}),className:"min-h-10 rounded-[var(--radius-control)] border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.3)]",children:[e.jsx("option",{value:"",children:"Select project"}),tt.map(t=>e.jsx("option",{value:t.id,children:t.title},t.id))]})})]}),e.jsx(k,{label:"Notes",children:e.jsx(ce,{value:v.description,onChange:t=>S(s=>({...s,description:t.target.value})),placeholder:"Optional detail or acceptance note."})}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(k,{label:"Priority",children:e.jsxs("select",{value:v.priority,onChange:t=>S(s=>({...s,priority:t.target.value})),className:"min-h-10 rounded-[var(--radius-control)] border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.3)]",children:[e.jsx("option",{value:"low",children:"Low"}),e.jsx("option",{value:"medium",children:"Medium"}),e.jsx("option",{value:"high",children:"High"}),e.jsx("option",{value:"critical",children:"Critical"})]})}),e.jsx(k,{label:"Points",children:e.jsx(F,{type:"number",value:v.points,onChange:t=>S(s=>({...s,points:Number(t.target.value)||0}))})})]}),e.jsxs("div",{className:"grid gap-4 md:grid-cols-2",children:[e.jsx(k,{label:"Effort",children:e.jsxs("select",{value:v.effort,onChange:t=>S(s=>({...s,effort:t.target.value})),className:"min-h-10 rounded-[var(--radius-control)] border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.3)]",children:[e.jsx("option",{value:"light",children:"Light"}),e.jsx("option",{value:"deep",children:"Deep"}),e.jsx("option",{value:"extended",children:"Extended"})]})}),e.jsx(k,{label:"Energy",children:e.jsxs("select",{value:v.energy,onChange:t=>S(s=>({...s,energy:t.target.value})),className:"min-h-10 rounded-[var(--radius-control)] border border-white/10 bg-white/[0.04] px-3 py-2 text-sm text-white outline-none transition focus:border-[rgba(192,193,255,0.3)]",children:[e.jsx("option",{value:"calm",children:"Calm"}),e.jsx("option",{value:"steady",children:"Steady"}),e.jsx("option",{value:"intense",children:"Intense"})]})})]}),U?e.jsx("div",{className:"rounded-[18px] border border-rose-400/20 bg-rose-500/[0.08] px-4 py-3 text-sm text-rose-100/90",children:U}):null,e.jsxs("div",{className:"flex flex-wrap justify-end gap-2",children:[e.jsx(D,{type:"button",variant:"secondary",className:"w-full sm:w-auto",onClick:()=>{K(!1),E(null)},children:"Cancel"}),e.jsxs(D,{type:"button",className:"w-full sm:w-auto",pending:ie,pendingLabel:"Creating task",onClick:()=>void ot(),children:[e.jsx(ze,{className:"size-4"}),"Create task"]})]})]})]}):null,st?it?e.jsxs("div",{className:"grid gap-3",children:[ve.length>0?e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Goals"}):null,ve.map(t=>{const s=n.targetGoalIds.includes(t.id),a=n.linkedEntities.some(l=>l.entityType==="goal"&&l.entityId===t.id);return e.jsx("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"goal",label:t.title,compact:!0,gradient:!1}),e.jsx(B,{user:t.user,compact:!0})]}),t.description?e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:t.description}):null]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:s?"secondary":"primary",onClick:()=>T(l=>({...l,targetGoalIds:J(l.targetGoalIds,t.id)})),children:s?"Targeted":"Add target"}),e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:"secondary",onClick:()=>T(l=>({...l,linkedEntities:Qe(l.linkedEntities,{entityType:"goal",entityId:t.id})})),children:a?"Unlink":"Link"})]})]})},t.id)}),je.length>0?e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Projects"}):null,je.map(t=>{const s=le.has(`project:${t.id}`);return e.jsx("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"project",label:t.title,compact:!0,gradient:!1}),e.jsx(C,{className:"bg-white/[0.08] text-white/72",children:t.goalTitle}),e.jsx(B,{user:t.user,compact:!0})]}),t.description?e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:t.description}):null]}),e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:s?"secondary":"primary",disabled:s,onClick:()=>ee("project",t.id),children:s?"In sequence":"Add step"})]})},`sequence-project:${t.id}`)}),Ie.length>0?e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Tasks"}):null,Ie.map(t=>{const s=le.has(`task:${t.id}`);return e.jsx("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"task",label:t.title,compact:!0,gradient:!1}),e.jsx(C,{className:"bg-white/[0.08] text-white/72",children:t.status}),e.jsx(B,{user:t.user,compact:!0})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:t.description||`${t.owner} · ${t.projectId}`})]}),e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:s?"secondary":"primary",disabled:s,onClick:()=>ee("task",t.id),children:s?"In sequence":"Add step"})]})},`sequence-task:${t.id}`)})]}):e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"No goals, projects, or tasks match this search."}):Oe.length>0||Re.length>0?e.jsxs("div",{className:"grid gap-3",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Suggested from targets"}),Oe.map(t=>{const s=le.has(`project:${t.id}`);return e.jsx("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"project",label:t.title,compact:!0,gradient:!1}),e.jsx(B,{user:t.user,compact:!0})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:t.description||t.goalTitle})]}),e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:s?"secondary":"primary",disabled:s,onClick:()=>ee("project",t.id),children:s?"In sequence":"Add step"})]})},`suggested-project:${t.id}`)}),Re.map(t=>{const s=le.has(`task:${t.id}`);return e.jsx("div",{className:"rounded-[20px] border border-white/8 bg-white/[0.04] px-4 py-4",children:e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[e.jsx(P,{kind:"task",label:t.title,compact:!0,gradient:!1}),e.jsx(B,{user:t.user,compact:!0})]}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/54",children:t.description||`${t.owner} · ${t.status}`})]}),e.jsx(D,{type:"button",className:"w-full sm:w-auto",variant:s?"secondary":"primary",disabled:s,onClick:()=>ee("task",t.id),children:s?"In sequence":"Add step"})]})},`suggested-task:${t.id}`)})]}):e.jsx("div",{className:"rounded-[18px] bg-white/[0.04] px-4 py-3 text-sm leading-6 text-white/56",children:"Type to search."})]})]}),e.jsxs("div",{className:"grid min-w-0 gap-4",children:[e.jsxs("div",{className:"rounded-[24px] border border-white/8 bg-white/[0.03] px-5 py-5",children:[e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Sequence"}),e.jsx("div",{className:"mt-2 text-sm leading-6 text-white/58",children:"Keep the flow mostly linear here. When a step should open beside the previous one, switch it to parallel. Use custom only for special joins."})]}),e.jsxs(C,{className:"bg-[var(--primary)]/14 text-[var(--primary)]",children:[n.nodes.length," planned steps"]})]}),e.jsxs("div",{className:"mt-4 flex flex-wrap gap-2",children:[n.targetGoalIds.map(t=>{const s=b.get(t);return s?e.jsx(P,{kind:"goal",label:s.title,compact:!0,gradient:!1},t):null}),n.targetProjectIds.map(t=>{const s=I.get(t);return s?e.jsx(P,{kind:"project",label:s.title,compact:!0,gradient:!1},t):null})]})]}),e.jsx(ft,{sensors:rt,collisionDetection:bt,onDragEnd:dt,children:e.jsx(wt,{items:n.nodes.map(t=>t.id),strategy:yt,children:e.jsx("div",{className:"grid gap-3",children:n.nodes.map((t,s)=>e.jsx(_t,{node:t,index:s,total:n.nodes.length,projectsById:I,tasksById:V,usersById:ke,allNodes:n.nodes,onUpdate:at,onRemove:nt},t.id))})})})]}),e.jsxs("div",{className:"grid gap-3 lg:grid-cols-2",children:[e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Contract readiness"}),e.jsx("div",{className:"mt-3 grid gap-2",children:Xe.map(t=>e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-[14px] bg-white/[0.03] px-3 py-2",children:[e.jsx("div",{className:"text-sm text-white/62",children:t.label}),e.jsx(C,{className:t.satisfied?"bg-emerald-500/12 text-emerald-200":"bg-amber-500/12 text-amber-200",children:t.satisfied?"Ready":"Missing"})]},t.id))})]}),e.jsxs("div",{className:"rounded-[22px] border border-white/8 bg-white/[0.03] px-4 py-4",children:[e.jsx("div",{className:"font-label text-[11px] uppercase tracking-[0.18em] text-white/42",children:"Alignment preview"}),e.jsx("div",{className:"mt-3 grid gap-3",children:Ve.map(t=>e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between gap-3 text-sm text-white/60",children:[e.jsx("span",{children:t.label}),e.jsxs("span",{children:[t.value,"%"]})]}),e.jsx(Mt,{value:t.value,className:"mt-2"})]},t.id))})]})]})]})}];return e.jsx(kt,{open:i,onOpenChange:H,eyebrow:"Strategy",title:r?"Edit strategy":"Create strategy",description:"Strategies connect goals, projects, and tasks into a guided multi-step plan with a focused sequence builder at the end.",value:n,onChange:T,draftPersistenceKey:r?`strategy.${r.id}`:"strategy.new",steps:ht,initialStepId:G,contentClassName:"lg:h-[min(56rem,calc(100vh-1rem))] lg:w-[min(78rem,calc(100vw-1.5rem))]",submitLabel:r?we?"Save strategy":"Save draft":we?"Create strategy":"Create draft",pending:p,pendingLabel:"Saving strategy",resolveError:et,onSubmit:ct})}export{Kt as S,Je as a,Dt as b,Et as i};
|