vibe64 0.1.48 → 0.1.49
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/bin/run.js +1746 -1725
- package/bin/server.js +75 -75
- package/bin/upgrade-state.js +4275 -4254
- package/dist/assets/GithubBrowserTabs-BwpiRS2u.js +1 -0
- package/dist/assets/{LocalDatabaseServer-ih_gadbx.js → LocalDatabaseServer-u_Ky7bNS.js} +1 -1
- package/dist/assets/{Vibe64AuthSettingsButton-BZsCIA2Z.js → Vibe64AuthSettingsButton-BCwswT1G.js} +1 -1
- package/dist/assets/{Vibe64DashboardShell-DFE-2tFZ.js → Vibe64DashboardShell-CWlgrR2B.js} +1 -1
- package/dist/assets/{Vibe64DatabaseWorkspace-BdvxuFPT.js → Vibe64DatabaseWorkspace-Dhs8_H0P.js} +1 -1
- package/dist/assets/Vibe64OutputControls-Dn548CZa.js +8 -0
- package/dist/assets/{Vibe64RepositoryWorkspace-CVN2HKCB.js → Vibe64RepositoryWorkspace-C-8S4JUF.js} +1 -1
- package/dist/assets/{Vibe64SessionFiles-DKo5wd8-.js → Vibe64SessionFiles-Cx6J7DDN.js} +1 -1
- package/dist/assets/{Vibe64UiStoryboardView-BYqVdBAt.js → Vibe64UiStoryboardView-DHyhJiWS.js} +1 -1
- package/dist/assets/{Vibe64UnavailableSessions-CQjgoaS0.js → Vibe64UnavailableSessions-Da4RxIhA.js} +1 -1
- package/dist/assets/{_sessionId_-ByUkrRd7.js → _sessionId_-DCpgDPSI.js} +1 -1
- package/dist/assets/_slug_-BbEWp01a.js +25 -0
- package/dist/assets/{_slug_-B16mTWjj.css → _slug_-DerKOisL.css} +1 -1
- package/dist/assets/{access-CWZMu-ND.js → access-D4di2sCr.js} +1 -1
- package/dist/assets/{app-D_itm2S5.js → app-Adr9Iz8p.js} +1 -1
- package/dist/assets/{changes-BYuFfnEm.js → changes-3Dd1O8Lu.js} +1 -1
- package/dist/assets/{client-CP2EwnrY.js → client-BAXHGUOC.js} +1 -1
- package/dist/assets/{client-B88Jggew.js → client-CCZIu6yc.js} +1 -1
- package/dist/assets/{conversation-DL4AODd9.js → conversation-ErAO1CmH.js} +1 -1
- package/dist/assets/{dashboard-R4qgYv8O.js → dashboard-0tCzDYCX.js} +1 -1
- package/dist/assets/{english-definitions-CdIGswXU.js → english-definitions-DeiQ-jTT.js} +1 -1
- package/dist/assets/env-DsyQ2MFX.js +1 -0
- package/dist/assets/{health-Ut9eZrbK.js → health-DyTXU-nb.js} +1 -1
- package/dist/assets/{history-BrmvkGgi.js → history-BXGAdPMI.js} +1 -1
- package/dist/assets/{incoming-CicEs40v.js → incoming-yajkdGBY.js} +1 -1
- package/dist/assets/{index-DZgCwvFD.js → index-CGz4Yow6.js} +4 -4
- package/dist/assets/{integrations-QHeHC-C9.js → integrations-BMrXET36.js} +1 -1
- package/dist/assets/{issues-Ds7iAQFQ.js → issues-kc1XBZCK.js} +1 -1
- package/dist/assets/{learning-Dq0xbg3x.js → learning-CIE5ghYv.js} +1 -1
- package/dist/assets/publish-DTh6amqi.js +3 -0
- package/dist/assets/{pull-requests-DHLK83qZ.js → pull-requests-CbfGSSIh.js} +1 -1
- package/dist/assets/{repository-DWw1VFIQ.js → repository-BstMh-bG.js} +1 -1
- package/dist/assets/settings-Bf8C6dls.js +1 -0
- package/dist/assets/useArchivedVibe64Sessions-DIOpfUxD.js +1 -0
- package/dist/assets/{useCommand-DhwB5k1w.js → useCommand-CVuya6vG.js} +1 -1
- package/dist/assets/{useEndpointResource-tVvsJvd4.js → useEndpointResource-7-YDfAxX.js} +1 -1
- package/dist/assets/{useUiFeedback-DLUToc5y.js → useUiFeedback-Bd3rao6E.js} +1 -1
- package/dist/assets/useVibe64ConversationLog-ChJOU2SD.js +1 -0
- package/dist/assets/{useVibe64DatabaseTools-Cac_aZnv.js → useVibe64DatabaseTools-DKV-TeNJ.js} +1 -1
- package/dist/assets/useVibe64SessionData-BkIHUrP5.js +1 -0
- package/dist/assets/useVibe64SessionSelection-N8wX5oqo.js +1 -0
- package/dist/assets/{useVibe64SystemGraph-idV9zXa9.js → useVibe64SystemGraph-Db_eD-X8.js} +1 -1
- package/dist/assets/vibe64RepositoryRealtime-CHT4-6VN.js +1 -0
- package/dist/assets/vibe64SessionFocus-CS6Ex53G.js +1 -0
- package/dist/assets/vibe64SessionFocus-CSm4YJQD.css +1 -0
- package/dist/assets/vibe64SessionRequestConfig-xIx-5jxQ.js +1 -0
- package/dist/index.html +10 -9
- package/docs/colleague-usage/ai-accounts.md +6 -2
- package/docs/colleague-usage/ai-balance-and-allowance.md +15 -2
- package/docs/colleague-usage/coding-agent-failures.md +2 -1
- package/docs/colleague-usage/coding-agent-goals.md +8 -3
- package/docs/colleague-usage/coding-agents.md +16 -0
- package/docs/colleague-usage/github-work.md +14 -0
- package/docs/colleague-usage/project-setup.md +6 -3
- package/docs/colleague-usage/running-vibe64-on-your-computer.md +3 -1
- package/docs/colleague-usage/sessions.md +35 -7
- package/docs/colleague-usage/starter-apps.md +3 -0
- package/docs/colleague-usage/temporary-chat-context.md +2 -1
- package/docs/colleague-usage/temporary-chats.md +17 -5
- package/node_modules/@jskit-ai/assistant-core/package.json +1 -1
- package/node_modules/@jskit-ai/assistant-runtime/README.md +2 -1
- package/node_modules/@jskit-ai/assistant-runtime/locales/en.json +2 -1
- package/node_modules/@jskit-ai/assistant-runtime/package.json +1 -1
- package/node_modules/@jskit-ai/assistant-voice/package.json +1 -1
- package/node_modules/@local/vibe64-execution/src/host/execHelper.js +34 -34
- package/node_modules/@local/vibe64-execution/src/server/gitTurnCheckpointCommand.js +1327 -0
- package/node_modules/@local/vibe64-genesis/bin/vibe64-genesis-host-context +120 -120
- package/node_modules/@local/vibe64-runtime/src/server/codexAppServerProcess.js +143 -143
- package/node_modules/@local/vibe64-sessions/package.json +2 -1
- package/node_modules/@local/vibe64-terminals/src/server/sessionWorkOperationCommand.js +1385 -1362
- package/package.json +5 -5
- package/server.bundle.mjs +38576 -38459
- package/dist/assets/GithubBrowserTabs-_l6htLOV.js +0 -1
- package/dist/assets/Vibe64OutputControls-DsCbasR0.js +0 -8
- package/dist/assets/_slug_-hep_be7Z.js +0 -24
- package/dist/assets/env-DtkytCtq.js +0 -1
- package/dist/assets/publish-eErG67LW.js +0 -3
- package/dist/assets/settings-QkwnoNn3.js +0 -1
- package/dist/assets/useArchivedVibe64Sessions-Biy_4sxD.js +0 -1
- package/dist/assets/useVibe64ConversationLog-jM3KOvN7.js +0 -1
- package/dist/assets/useVibe64SessionData-FGnNvFfK.js +0 -1
- package/dist/assets/useVibe64SessionSelection-Bgsif-tm.js +0 -1
- package/dist/assets/vibe64RepositoryRealtime-C-J0I5jY.js +0 -1
- package/dist/assets/vibe64SessionFocus-CDIB5Gpr.js +0 -1
- package/dist/assets/vibe64SessionFocus-DSW5Irm6.css +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{D as createVNode,E as createTextVNode,Ht as watch,On as unref,_ as createBaseVNode,b as createElementBlock,bt as renderList,g as computed,mt as openBlock,o as Fragment,qt as withCtx,tr as toDisplayString,v as createBlock,vn as ref,y as createCommentVNode}from"./runtime-core.esm-bundler-DGXg_mpN.js";import{D as ROUTE_VISIBILITY_PUBLIC,t as useEndpointResource}from"./useEndpointResource-7-YDfAxX.js";import{_ as useRouter,g as useRoute}from"./useApi-BPuI6ZR9-CFWU1m37.js";import{t as VSelect}from"./VSelect-Dqnp_CFi.js";import{t as VTextField}from"./VTextField-CnkGeXaT.js";import{r as scopedDevelopmentApiUrl}from"./studioUrls-B0-GdWh8.js";import{t as VBtn}from"./VBtn-Sj5jAuOx.js";import{t as VAlert}from"./VAlert-7_VM9EUm.js";import{t as VCheckbox}from"./VCheckbox-CHFec5Bg.js";import{n as VRadio,t as VRadioGroup}from"./VRadioGroup-OHg3N6_i.js";import{t as VSwitch}from"./VSwitch-B_DmcTxG.js";import{t as VTextarea}from"./VTextarea-wqoRFl1K.js";import{t as _plugin_vue_export_helper_default}from"./_plugin-vue_export-helper-DNW4j-dv.js";import{n as useRealtimeEvent}from"./useRealtimeEvent-BNXVwzFG.js";import{t as useCommand}from"./useCommand-CVuya6vG.js";import{C as VIBE64_PROMPT_HINTS_SETTINGS_API_SUFFIX,O as projectSettingsQueryKey,b as VIBE64_PROJECT_CHANGED_EVENT,g as VIBE64_ENGINEERING_API_SUFFIX,h as VIBE64_DEVELOPMENT_DATABASE_API_SUFFIX,l as PROJECT_SETTINGS_ENDPOINT,n as DEVELOPMENT_DATABASE_ENDPOINT,p as VIBE64_COLLABORATION_API_SUFFIX,r as ENGINEERING_ENDPOINT,t as COLLABORATION_ENDPOINT,u as PROMPT_HINTS_SETTINGS_ENDPOINT,w as engineeringSettingsQueryKey}from"./studioGateApi-mkX1eOTX.js";import{n as useVibe64ProjectSlug}from"./useVibe64ProjectScope-DXjsKKhl.js";import{s as VIBE64_SESSION_CHANGED_EVENT}from"./vibe64SessionRequestConfig-xIx-5jxQ.js";import{T as requestVibe64AccountConnectionsDialog}from"./index-CGz4Yow6.js";import{t as Vibe64AsyncModuleState_default}from"./Vibe64AsyncModuleState-CPEGxBWZ.js";import{t as sessionListRealtimeShouldRefresh}from"./useVibe64SessionData-BkIHUrP5.js";var CONNECTED_CUSTOM_PACKAGE_TYPE=`custom`;var CONNECTED_PACKAGE_TYPES=Object.freeze([Object.freeze({value:`npm`,label:`npm (Node.js)`}),Object.freeze({value:`composer`,label:`Composer (PHP)`}),Object.freeze({value:`pip`,label:`pip (Python)`}),Object.freeze({value:`bundler`,label:`Bundler (Ruby)`}),Object.freeze({value:`gomod`,label:`Go modules`}),Object.freeze({value:`cargo`,label:`Cargo (Rust)`}),Object.freeze({value:`maven`,label:`Maven`}),Object.freeze({value:`gradle`,label:`Gradle`}),Object.freeze({value:`nuget`,label:`NuGet (.NET)`}),Object.freeze({value:CONNECTED_CUSTOM_PACKAGE_TYPE,label:`custom`})]);var CONNECTED_PACKAGE_TYPE_VALUES=Object.freeze(CONNECTED_PACKAGE_TYPES.map(type=>type.value));function connectedPackageTypeUsesScript(type){return type===CONNECTED_CUSTOM_PACKAGE_TYPE}var _hoisted_1$2={class:`project-settings__section`,"aria-labelledby":`connected-projects-title`};var _hoisted_2$1={class:`project-settings__content text-body-medium`};var _hoisted_3$1={key:0};var _hoisted_4$1={key:0};var _hoisted_5$1=[`disabled`];var _hoisted_6$1={class:`text-label-large`};var _hoisted_7$1={key:2};var _hoisted_8$1={class:`connection-actions`};var _sfc_main$2={__name:`ConnectedProjectsSettings`,props:{projectSlug:{type:String,required:true},state:{type:Object,default:()=>({})}},emits:[`saved`],setup(__props,{emit:__emit}){const props=__props;const emit=__emit;const draft=ref([]);const baseline=ref(`[]`);const revision=ref(``);const saving=ref(false);const changed=computed(()=>JSON.stringify(draft.value)!==baseline.value);const stale=computed(()=>props.state.available&&revision.value!==props.state.revision);const relationships=[{label:`Dependency — a library or tool`,value:`dependency`},{label:`Composition — source assembled into this project`,value:`composition`}];const packageTypes=[{label:`Stack default`,value:``},...CONNECTED_PACKAGE_TYPES];function scriptAllowed(entry){return!entry.type||connectedPackageTypeUsesScript(entry.type)}function setPackageType(entry,value){if(value)entry.type=value;else delete entry.type;if(!scriptAllowed(entry))delete entry.script}function setScript(entry,value){if(value)entry.script=value;else delete entry.script}function resetDraft(){draft.value=(props.state.projects||[]).map(entry=>({...entry}));baseline.value=JSON.stringify(draft.value);revision.value=props.state.revision||``}let sourceIdentity=``;watch(()=>[props.projectSlug,props.state],()=>{if(!props.state.source)return;const identity=JSON.stringify([props.projectSlug,props.state.source]);if(identity!==sourceIdentity||!changed.value)resetDraft();sourceIdentity=identity},{immediate:true});const saveCommand=useCommand({access:`never`,apiSuffix:`/vibe64/settings/connections`,buildCommandOptions:()=>({method:`PUT`,path:scopedDevelopmentApiUrl(`/api/vibe64/settings/connections`,props.projectSlug)}),buildRawPayload:(_model,{context})=>context,fallbackRunError:`Connected projects could not be saved.`,messages:{error:`Connected projects could not be saved.`,success:`Connected projects saved in source.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.project.connections.save`,surfaceId:`app`,writeMethod:`PUT`});async function save(){if(saving.value||stale.value||!props.state.canEdit)return;saving.value=true;try{if(!await saveCommand.run({projects:draft.value.map(entry=>({...entry})),revision:revision.value,sessionId:props.state.source?.sessionId||``}))return;baseline.value=JSON.stringify(draft.value);emit(`saved`)}catch{}finally{saving.value=false}}return(_ctx,_cache)=>{return openBlock(),createElementBlock(`section`,_hoisted_1$2,[_cache[6]||(_cache[6]=createBaseVNode(`div`,{class:`project-settings__section-copy text-body-medium`},[createBaseVNode(`h2`,{id:`connected-projects-title`,class:`text-title-medium font-weight-bold`},`Connected projects`),createBaseVNode(`p`,null,`Libraries and source projects you contribute to from this project.`),createBaseVNode(`p`,null,[createTextVNode(`Saved in this source checkout’s `),createBaseVNode(`code`,null,`vibe64.connections.json`),createTextVNode(`. Changes follow normal project Save.`)])],-1)),createBaseVNode(`div`,_hoisted_2$1,[!__props.state.available?(openBlock(),createElementBlock(`p`,_hoisted_3$1,toDisplayString(__props.state.unavailableReason||`Select a session to configure connected projects.`),1)):(openBlock(),createElementBlock(Fragment,{key:1},[!__props.state.exists?(openBlock(),createElementBlock(`p`,_hoisted_4$1,`No connection file yet. Add projects below, then save the list.`)):createCommentVNode(``,true),stale.value?(openBlock(),createBlock(VAlert,{key:1,type:`warning`,variant:`tonal`},{default:withCtx(()=>[_cache[2]||(_cache[2]=createTextVNode(` The saved list changed while you were editing. Reload the saved list and review your changes before saving. `,-1)),createVNode(VBtn,{variant:`text`,onClick:resetDraft},{default:withCtx(()=>[..._cache[1]||(_cache[1]=[createTextVNode(`Reload saved list`,-1)])]),_:1})]),_:1})):createCommentVNode(``,true),(openBlock(true),createElementBlock(Fragment,null,renderList(draft.value,(entry,index)=>{return openBlock(),createElementBlock(`fieldset`,{key:index,class:`connection-entry`,disabled:!__props.state.canEdit||saving.value},[createBaseVNode(`legend`,_hoisted_6$1,`Connected project `+toDisplayString(index+1),1),createVNode(VTextField,{disabled:!__props.state.canEdit||saving.value,modelValue:entry.name,"onUpdate:modelValue":$event=>entry.name=$event,label:`Name`,maxlength:`100`,variant:`outlined`,"hide-details":`auto`},null,8,[`disabled`,`modelValue`,`onUpdate:modelValue`]),createVNode(VTextField,{disabled:!__props.state.canEdit||saving.value,modelValue:entry.repository,"onUpdate:modelValue":$event=>entry.repository=$event,label:`GitHub repository URL`,placeholder:`https://github.com/owner/repository`,variant:`outlined`,"hide-details":`auto`},null,8,[`disabled`,`modelValue`,`onUpdate:modelValue`]),createVNode(VSelect,{disabled:!__props.state.canEdit||saving.value,modelValue:entry.relationship,"onUpdate:modelValue":$event=>entry.relationship=$event,label:`Relationship`,items:relationships,"item-title":`label`,"item-value":`value`,variant:`outlined`,"hide-details":`auto`},null,8,[`disabled`,`modelValue`,`onUpdate:modelValue`]),createVNode(VSelect,{disabled:!__props.state.canEdit||saving.value,"model-value":entry.type||``,"onUpdate:modelValue":$event=>setPackageType(entry,$event),label:`Package type`,items:packageTypes,"item-title":`label`,"item-value":`value`,variant:`outlined`,"hide-details":`auto`},null,8,[`disabled`,`model-value`,`onUpdate:modelValue`]),createVNode(VTextField,{disabled:!__props.state.canEdit||saving.value||!scriptAllowed(entry),"model-value":entry.script||``,"onUpdate:modelValue":$event=>setScript(entry,$event),label:`Preparation script (project-relative)`,placeholder:`tooling/prepare-native-worker.mjs`,maxlength:`1024`,hint:`Required for custom. Relative to this project's root; Stack declares the runtime.`,"persistent-hint":``,variant:`outlined`,"hide-details":`auto`},null,8,[`disabled`,`model-value`,`onUpdate:modelValue`]),createVNode(VBtn,{disabled:!__props.state.canEdit||saving.value,variant:`text`,"aria-label":`Remove ${entry.name||`connected project`}`,onClick:$event=>draft.value.splice(index,1)},{default:withCtx(()=>[..._cache[3]||(_cache[3]=[createTextVNode(`Remove`,-1)])]),_:1},8,[`disabled`,`aria-label`,`onClick`])],8,_hoisted_5$1)}),128)),__props.state.exists&&!draft.value.length?(openBlock(),createElementBlock(`p`,_hoisted_7$1,`No connected projects.`)):createCommentVNode(``,true),_cache[5]||(_cache[5]=createBaseVNode(`p`,{class:`text-body-small`},`Removing a connection preserves its existing contributions and pending work.`,-1)),createBaseVNode(`div`,_hoisted_8$1,[createVNode(VBtn,{disabled:!__props.state.canEdit||saving.value||draft.value.length>=unref(64),variant:`outlined`,onClick:_cache[0]||(_cache[0]=$event=>draft.value.push({name:``,repository:``,relationship:`dependency`}))},{default:withCtx(()=>[..._cache[4]||(_cache[4]=[createTextVNode(`Add project`,-1)])]),_:1},8,[`disabled`]),createVNode(VBtn,{disabled:!__props.state.canEdit||saving.value||stale.value||!changed.value&&__props.state.exists,color:`primary`,variant:`flat`,onClick:save},{default:withCtx(()=>[createTextVNode(toDisplayString(saving.value?`Saving…`:`Save connected projects`),1)]),_:1},8,[`disabled`])])],64))])])}}};var ConnectedProjectsSettings_default=_plugin_vue_export_helper_default(_sfc_main$2,[[`__scopeId`,`data-v-b1c8a0e6`]]);var _hoisted_1$1={class:`project-settings`};var _hoisted_2={class:`project-settings__header`};var _hoisted_3={class:`project-settings__section`,"aria-labelledby":`engineering-approach-title`};var _hoisted_4={class:`project-settings__section-copy text-body-medium`};var _hoisted_5={key:0,class:`project-settings__scope text-label-medium`};var _hoisted_6={key:0,class:`project-settings__content text-body-medium`};var _hoisted_7={class:`project-settings__engineering-field`};var _hoisted_8={class:`project-settings__action text-body-small`};var _hoisted_9={key:1,class:`project-settings__action text-body-small`};var _hoisted_10={class:`project-settings__section`,"aria-labelledby":`development-database-title`};var _hoisted_11={class:`project-settings__section-copy text-body-medium`};var _hoisted_12={key:0};var _hoisted_13={key:1};var _hoisted_14={key:0,class:`project-settings__content text-body-medium`};var _hoisted_15={class:`project-settings__option`};var _hoisted_16={key:0,id:`development-database-session-reason`,class:`project-settings__option-support text-body-small`};var _hoisted_17={class:`project-settings__option`};var _hoisted_18={key:0,id:`development-database-project-reason`,class:`project-settings__option-support text-body-small`};var _hoisted_19={key:0,class:`project-settings__action text-body-small`};var _hoisted_20={class:`project-settings__action text-body-small`};var _hoisted_21={key:0};var _hoisted_22={key:1};var _hoisted_23={class:`project-settings__section`,"aria-labelledby":`ai-behaviour-title`};var _hoisted_24={class:`project-settings__section-copy text-body-medium`};var _hoisted_25={class:`project-settings__scope text-label-medium`};var _hoisted_26={class:`project-settings__content text-body-medium`};var _hoisted_27={class:`project-settings__ai-fields`};var _hoisted_28={class:`project-settings__action text-body-small`};var _hoisted_29={key:0};var _hoisted_30={key:1};var _hoisted_31={key:2};var _hoisted_32={class:`project-settings__section`,"aria-labelledby":`prompt-suggestions-title`};var _hoisted_33={class:`project-settings__content text-body-medium`};var _hoisted_34={class:`project-settings__action text-body-small`};var _hoisted_35={key:0,class:`project-settings__section`,"aria-labelledby":`repository-workflow-title`};var _hoisted_36={class:`project-settings__content text-body-medium`};var _hoisted_37={class:`project-settings__action text-body-small`};var _sfc_main$1={__name:`ProjectSettingsPanel`,setup(__props){const projectSlug=useVibe64ProjectSlug();const route=useRoute();const router=useRouter();const scopeDraft=ref(`session`);const sharedSessionsDraft=ref(false);const collaborationDraft=ref(normalizeCollaborationDraft());const savedCollaboration=ref(normalizeCollaborationDraft());const promptHintsDraft=ref(true);const savedPromptHints=ref(true);const requirePullRequest=ref(false);const engineeringProfileDraft=ref(``);const savedEngineeringProfile=ref(``);const routeSessionId=computed(()=>String(route.query.sessionId||``).trim());const resource=useEndpointResource({fallbackLoadError:`Project settings could not load.`,path:computed(()=>scopedDevelopmentApiUrl(PROJECT_SETTINGS_ENDPOINT,projectSlug.value)),queryKey:computed(()=>projectSettingsQueryKey(`app`,ROUTE_VISIBILITY_PUBLIC,projectSlug.value,routeSessionId.value)),readQuery:computed(()=>routeSessionId.value?{sessionId:routeSessionId.value}:{}),refreshOnPull:true,requestRecoveryLabel:`Project settings`});const engineeringResource=useEndpointResource({fallbackLoadError:`Engineering approach could not load.`,path:computed(()=>scopedDevelopmentApiUrl(ENGINEERING_ENDPOINT,projectSlug.value)),queryKey:computed(()=>engineeringSettingsQueryKey(`app`,ROUTE_VISIBILITY_PUBLIC,projectSlug.value,routeSessionId.value)),readQuery:computed(()=>routeSessionId.value?{sessionId:routeSessionId.value}:{}),realtime:{event:VIBE64_PROJECT_CHANGED_EVENT,matches:()=>!engineeringSaveCommand.isRunning},refreshOnPull:true,requestRecoveryLabel:`Engineering approach`});const databaseSaveCommand=useCommand({access:`never`,apiSuffix:VIBE64_DEVELOPMENT_DATABASE_API_SUFFIX,buildCommandOptions:()=>({method:`PUT`,path:DEVELOPMENT_DATABASE_ENDPOINT}),buildRawPayload:(_model,{context})=>({scope:context.scope,allowSharedDatabaseSessions:context.allowSharedDatabaseSessions}),fallbackRunError:`Development database choice could not be saved.`,messages:{error:`Development database choice could not be saved.`,success:`Development database choice saved.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.development-database.scope.save`,surfaceId:`app`,writeMethod:`PUT`});const collaborationSaveCommand=useCommand({access:`never`,apiSuffix:VIBE64_COLLABORATION_API_SUFFIX,buildCommandOptions:()=>({method:`PUT`,path:COLLABORATION_ENDPOINT}),buildRawPayload:(_model,{context})=>({...context.collaboration,...context.sessionId?{sessionId:context.sessionId}:{}}),fallbackRunError:`Collaboration guidance could not be saved.`,messages:{error:`Collaboration guidance could not be saved.`,success:`Collaboration guidance saved.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.collaboration.save`,surfaceId:`app`,writeMethod:`PUT`});const promptHintsSaveCommand=useCommand({access:`never`,apiSuffix:VIBE64_PROMPT_HINTS_SETTINGS_API_SUFFIX,buildCommandOptions:()=>({method:`PUT`,path:PROMPT_HINTS_SETTINGS_ENDPOINT}),buildRawPayload:(_model,{context})=>({promptHints:context.promptHints}),fallbackRunError:`Prompt suggestions could not be saved.`,messages:{error:`Prompt suggestions could not be saved.`,success:`Prompt suggestions saved.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.prompt-hints.save`,surfaceId:`app`,writeMethod:`PUT`});const repositoryWorkflowCommand=useCommand({access:`never`,apiSuffix:`/vibe64/repository/workflow`,buildCommandOptions:()=>({method:`PUT`,path:scopedDevelopmentApiUrl(`/api/vibe64/repository/workflow`,projectSlug.value)}),buildRawPayload:(_model,{context})=>({requirePullRequest:context.requirePullRequest}),fallbackRunError:`Repository workflow could not be saved.`,messages:{error:`Repository workflow could not be saved.`,success:`Repository workflow saved.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.repository.workflow`,surfaceId:`app`,writeMethod:`PUT`});const repositoryWorkflow=computed(()=>resource.data.value?.repositoryWorkflow||{});watch(()=>repositoryWorkflow.value.requirePullRequest,value=>{requirePullRequest.value=value===true},{immediate:true});async function saveRepositoryWorkflow(){await repositoryWorkflowCommand.run({requirePullRequest:requirePullRequest.value});await resource.reload()}const engineeringSaveCommand=useCommand({access:`never`,apiSuffix:VIBE64_ENGINEERING_API_SUFFIX,buildCommandOptions:()=>({method:`PUT`,path:ENGINEERING_ENDPOINT}),buildRawPayload:(_model,{context})=>({profile:context.profile,...context.sessionId?{sessionId:context.sessionId}:{}}),fallbackRunError:`Engineering approach could not be saved.`,messages:{error:`Engineering approach could not be saved.`,success:`Engineering approach saved.`},ownershipFilter:ROUTE_VISIBILITY_PUBLIC,placementSource:`vibe64.engineering.profile.save`,surfaceId:`app`,writeMethod:`PUT`});const developmentDatabase=computed(()=>resource.data.value?.developmentDatabase||{});const managed=computed(()=>developmentDatabase.value.managed===true);const canChange=computed(()=>developmentDatabase.value.canChange===true);const disabledReason=computed(()=>String(developmentDatabase.value.disabledReason||``));const sessionScopeOption=computed(()=>developmentDatabase.value.options?.session||{});const projectScopeOption=computed(()=>developmentDatabase.value.options?.project||{});const sessionScopeAvailable=computed(()=>sessionScopeOption.value.available===true);const projectScopeAvailable=computed(()=>projectScopeOption.value.available===true);const sessionScopeReason=computed(()=>String(sessionScopeOption.value.disabledReason||``));const projectScopeReason=computed(()=>String(projectScopeOption.value.disabledReason||``));const scopeDraftAvailable=computed(()=>scopeDraft.value===`project`?projectScopeAvailable.value:sessionScopeAvailable.value);const collaboration=computed(()=>resource.data.value?.collaboration||{});const collaborationAvailable=computed(()=>collaboration.value.available===true);const collaborationCanEdit=computed(()=>collaboration.value.canEdit===true);const collaborationSourceLabel=computed(()=>collaboration.value.source?.rootKind===`session-source`?`This session's project source`:`This project source`);const collaborationUnavailableReason=computed(()=>String(collaboration.value.unavailableReason||`Collaboration guidance is not available for this source.`));const toneOptions=computed(()=>collaborationOptions(`tone`));const responseLengthOptions=computed(()=>collaborationOptions(`responseLength`));const experienceOptions=computed(()=>collaborationOptions(`experience`));const explanationStyleOptions=computed(()=>collaborationOptions(`explanationStyle`));const promptHints=computed(()=>resource.data.value?.promptHints||{});const promptHintsCanEdit=computed(()=>promptHints.value.canEdit===true);const engineering=computed(()=>engineeringResource.data.value?.engineering||{});const engineeringAvailable=computed(()=>engineering.value.available===true);const engineeringProfiles=computed(()=>Array.isArray(engineering.value.profiles)?engineering.value.profiles:[]);const engineeringSourceLabel=computed(()=>engineering.value.source?.rootKind===`session-source`?`This session's project source`:`This project source`);const engineeringUnavailableReason=computed(()=>String(engineering.value.unavailableReason||`An engineering profile is not available for this source.`));const selectedEngineeringDescription=computed(()=>String(engineeringProfiles.value.find(profile=>profile.id===engineeringProfileDraft.value)?.description||``));const engineeringStatusText=computed(()=>engineering.value.status===`defaulted`?`The focused default is active. Saving records the choice in genesis/engineering.md.`:`This choice is stored in genesis/engineering.md and follows the source.`);const loading=computed(()=>resource.isLoading.value===true||engineeringResource.isLoading.value===true);const initialLoading=computed(()=>loading.value&&(!resource.data.value||!engineeringResource.data.value));const loadError=computed(()=>String(resource.loadError.value||engineeringResource.loadError.value||``));const databaseSaving=computed(()=>databaseSaveCommand.isRunning===true);const collaborationSaving=ref(false);const promptHintsSaving=computed(()=>promptHintsSaveCommand.isRunning===true);const engineeringSaving=ref(false);const databaseChanged=computed(()=>managed.value&&(scopeDraft.value!==developmentDatabase.value.scope||sharedSessionsDraft.value!==(developmentDatabase.value.allowSharedDatabaseSessions===true)));const databaseSaveAllowed=computed(()=>scopeDraft.value===developmentDatabase.value.scope||canChange.value&&scopeDraftAvailable.value);const collaborationChanged=computed(()=>JSON.stringify(collaborationDraft.value)!==JSON.stringify(savedCollaboration.value));const promptHintsChanged=computed(()=>promptHintsDraft.value!==savedPromptHints.value);const engineeringChanged=computed(()=>engineeringAvailable.value&&Boolean(engineeringProfileDraft.value)&&engineeringProfileDraft.value!==savedEngineeringProfile.value);watch(()=>developmentDatabase.value.allowSharedDatabaseSessions,value=>{sharedSessionsDraft.value=value===true},{immediate:true});watch(()=>developmentDatabase.value.scope,scope=>{if([`project`,`session`].includes(scope))scopeDraft.value=scope},{immediate:true});let collaborationSource=null;watch([projectSlug,collaboration],([slug,value])=>{if(!value.source)return;const sourceChanged=!collaborationSource||collaborationSource.projectSlug!==slug||collaborationSource.rootKind!==value.source.rootKind||collaborationSource.sessionId!==value.source.sessionId;const next=normalizeCollaborationDraft(value);if(sourceChanged||!collaborationChanged.value)collaborationDraft.value=next;savedCollaboration.value={...next};collaborationSource={projectSlug:slug,...value.source}},{immediate:true});watch(()=>promptHints.value.enabled,value=>{const enabled=value!==false;if(!promptHintsChanged.value)promptHintsDraft.value=enabled;savedPromptHints.value=enabled},{immediate:true});let engineeringSource=null;watch([projectSlug,engineering],([slug,value])=>{if(!value.source)return;const sourceChanged=!engineeringSource||engineeringSource.projectSlug!==slug||engineeringSource.rootKind!==value.source.rootKind||engineeringSource.sessionId!==value.source.sessionId;const profile=String(value.profile?.id||``).trim();if(sourceChanged||engineeringProfileDraft.value===savedEngineeringProfile.value)engineeringProfileDraft.value=profile;savedEngineeringProfile.value=profile;engineeringSource={projectSlug:slug,...value.source};const sourceSessionId=String(value.source?.sessionId||``).trim();if(!routeSessionId.value&&sourceSessionId)router.replace({query:{...route.query,sessionId:sourceSessionId}})},{immediate:true});useRealtimeEvent({event:VIBE64_SESSION_CHANGED_EVENT,matches:event=>sessionListRealtimeShouldRefresh(event,projectSlug.value),onEvent(){resource.reload();engineeringResource.reload()}});async function refresh(){await Promise.all([resource.reload(),engineeringResource.reload()])}function collaborationOptions(field=``){const choices=collaboration.value.choices?.[field];return(Array.isArray(choices)?choices:[]).flatMap(choice=>{const value=String(choice?.id||``).trim();const label=String(choice?.name||``).trim();return value&&label?[{label,value}]:[]})}function normalizeCollaborationDraft(value={}){return{tone:String(value?.tone||``),responseLength:String(value?.responseLength||``),experience:String(value?.experience||``),explanationStyle:String(value?.explanationStyle||``),requirements:String(value?.requirements||``)}}async function saveDatabase(){if(!databaseChanged.value||!databaseSaveAllowed.value||databaseSaving.value)return;await databaseSaveCommand.run({scope:scopeDraft.value,allowSharedDatabaseSessions:sharedSessionsDraft.value});await resource.reload()}async function saveCollaboration(){if(!collaborationChanged.value||!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value)return;collaborationSaving.value=true;try{try{await collaborationSaveCommand.run({collaboration:normalizeCollaborationDraft(collaborationDraft.value),sessionId:routeSessionId.value||String(collaboration.value.source?.sessionId||``).trim()})}catch{return}await resource.reload()}finally{collaborationSaving.value=false}}async function savePromptHints(){if(!promptHintsChanged.value||!promptHintsCanEdit.value||promptHintsSaving.value)return;await promptHintsSaveCommand.run({promptHints:promptHintsDraft.value});await resource.reload()}async function saveEngineeringProfile(){if(!engineeringChanged.value||engineeringSaving.value)return;engineeringSaving.value=true;try{await engineeringSaveCommand.run({profile:engineeringProfileDraft.value,sessionId:routeSessionId.value||String(engineering.value.source?.sessionId||``).trim()})}catch{}finally{try{await engineeringResource.reload()}finally{engineeringSaving.value=false}}}function openPersonalSettings(){requestVibe64AccountConnectionsDialog({refresh:false,section:`profile`})}function reloadPage(){if(typeof window!==`undefined`)window.location.reload()}return(_ctx,_cache)=>{return openBlock(),createElementBlock(`section`,_hoisted_1$1,[createBaseVNode(`header`,_hoisted_2,[_cache[11]||(_cache[11]=createBaseVNode(`div`,null,[createBaseVNode(`h1`,{class:`text-headline-small font-weight-bold ma-0`},`Project settings`),createBaseVNode(`p`,{class:`text-body-medium`},`Choose how you and your AI work on this project.`)],-1)),createVNode(VBtn,{class:`project-settings__refresh`,disabled:loading.value,height:`48`,type:`button`,variant:`text`,onClick:refresh},{default:withCtx(()=>[createTextVNode(toDisplayString(loading.value?`Refreshing…`:`Refresh`),1)]),_:1},8,[`disabled`])]),initialLoading.value||loadError.value?(openBlock(),createBlock(Vibe64AsyncModuleState_default,{key:0,label:`Project settings`,loading:loading.value,message:loadError.value||`Loading project settings.`,"min-height":`12rem`,onReload:reloadPage,onRetry:refresh},null,8,[`loading`,`message`])):(openBlock(),createElementBlock(Fragment,{key:1},[createVNode(ConnectedProjectsSettings_default,{"project-slug":unref(projectSlug),state:unref(resource).data.value?.connectedProjects,onSaved:_cache[0]||(_cache[0]=$event=>unref(resource).reload())},null,8,[`project-slug`,`state`]),createBaseVNode(`section`,_hoisted_3,[createBaseVNode(`div`,_hoisted_4,[engineeringAvailable.value?(openBlock(),createElementBlock(`p`,_hoisted_5,toDisplayString(engineeringSourceLabel.value),1)):createCommentVNode(``,true),_cache[12]||(_cache[12]=createBaseVNode(`h2`,{id:`engineering-approach-title`,class:`text-title-medium font-weight-bold`},`Engineering approach`,-1)),_cache[13]||(_cache[13]=createBaseVNode(`p`,null,` Choose how cautiously the AI changes your software. Every profile keeps changes simple and asks before adding necessary complexity. `,-1))]),engineeringAvailable.value?(openBlock(),createElementBlock(`div`,_hoisted_6,[createBaseVNode(`div`,_hoisted_7,[createVNode(VSelect,{modelValue:engineeringProfileDraft.value,"onUpdate:modelValue":_cache[1]||(_cache[1]=$event=>engineeringProfileDraft.value=$event),disabled:engineeringSaving.value,density:`comfortable`,"hide-details":`auto`,hint:selectedEngineeringDescription.value,"item-title":`name`,"item-value":`id`,items:engineeringProfiles.value,label:`Engineering profile`,"persistent-hint":``,variant:`outlined`},null,8,[`modelValue`,`disabled`,`hint`,`items`])]),createBaseVNode(`div`,_hoisted_8,[createBaseVNode(`p`,null,toDisplayString(engineeringStatusText.value),1),createVNode(VBtn,{disabled:!engineeringChanged.value||engineeringSaving.value,color:engineeringChanged.value?`primary`:void 0,height:`48`,type:`button`,variant:`flat`,onClick:saveEngineeringProfile},{default:withCtx(()=>[createTextVNode(toDisplayString(engineeringSaving.value?`Saving…`:`Save engineering approach`),1)]),_:1},8,[`disabled`,`color`])])])):(openBlock(),createElementBlock(`div`,_hoisted_9,[createBaseVNode(`p`,null,toDisplayString(engineeringUnavailableReason.value),1)]))]),createBaseVNode(`section`,_hoisted_10,[createBaseVNode(`div`,_hoisted_11,[_cache[14]||(_cache[14]=createBaseVNode(`h2`,{id:`development-database-title`,class:`text-title-medium font-weight-bold`},`Development database`,-1)),managed.value?(openBlock(),createElementBlock(`p`,_hoisted_12,` Share development data across sessions or keep a separate database for each. `)):(openBlock(),createElementBlock(`p`,_hoisted_13,` This Vibe64 installation does not manage development databases. The application receives its database connection through the project Env configuration. `))]),managed.value?(openBlock(),createElementBlock(`div`,_hoisted_14,[createVNode(VRadioGroup,{modelValue:scopeDraft.value,"onUpdate:modelValue":_cache[2]||(_cache[2]=$event=>scopeDraft.value=$event),"aria-labelledby":`development-database-title`,class:`project-settings__options`,disabled:databaseSaving.value,"hide-details":``},{default:withCtx(()=>[createBaseVNode(`div`,_hoisted_15,[createVNode(VRadio,{class:`py-1`,"aria-describedby":sessionScopeReason.value?`development-database-session-reason`:void 0,disabled:!sessionScopeAvailable.value,label:`A separate database for each session`,value:`session`},null,8,[`aria-describedby`,`disabled`]),sessionScopeReason.value?(openBlock(),createElementBlock(`p`,_hoisted_16,toDisplayString(sessionScopeReason.value),1)):createCommentVNode(``,true)]),createBaseVNode(`div`,_hoisted_17,[createVNode(VRadio,{class:`py-1`,"aria-describedby":projectScopeReason.value?`development-database-project-reason`:void 0,disabled:!projectScopeAvailable.value,label:`One database shared by this project`,value:`project`},null,8,[`aria-describedby`,`disabled`]),projectScopeReason.value?(openBlock(),createElementBlock(`p`,_hoisted_18,toDisplayString(projectScopeReason.value),1)):createCommentVNode(``,true)])]),_:1},8,[`modelValue`,`disabled`]),scopeDraft.value===`project`?(openBlock(),createElementBlock(`div`,_hoisted_19,[createVNode(VCheckbox,{modelValue:sharedSessionsDraft.value,"onUpdate:modelValue":_cache[3]||(_cache[3]=$event=>sharedSessionsDraft.value=$event),label:`Allow multiple sessions with this shared database`,disabled:databaseSaving.value,"hide-details":``},null,8,[`modelValue`,`disabled`]),_cache[15]||(_cache[15]=createBaseVNode(`p`,null,`All sessions will share the same database.`,-1))])):createCommentVNode(``,true),createBaseVNode(`div`,_hoisted_20,[disabledReason.value?(openBlock(),createElementBlock(`p`,_hoisted_21,toDisplayString(disabledReason.value),1)):scopeDraft.value===`project`?(openBlock(),createElementBlock(`p`,_hoisted_22,` Data and schema changes will be visible to every project session and remain after a session is archived. `)):createCommentVNode(``,true),createVNode(VBtn,{disabled:!databaseChanged.value||!databaseSaveAllowed.value||databaseSaving.value,color:databaseChanged.value?`primary`:void 0,height:`48`,type:`button`,variant:`flat`,onClick:saveDatabase},{default:withCtx(()=>[createTextVNode(toDisplayString(databaseSaving.value?`Saving…`:`Save database choice`),1)]),_:1},8,[`disabled`,`color`])])])):createCommentVNode(``,true)]),createBaseVNode(`section`,_hoisted_23,[createBaseVNode(`div`,_hoisted_24,[createBaseVNode(`p`,_hoisted_25,toDisplayString(collaborationSourceLabel.value),1),_cache[17]||(_cache[17]=createBaseVNode(`h2`,{id:`ai-behaviour-title`,class:`text-title-medium font-weight-bold`},`AI behaviour`,-1)),_cache[18]||(_cache[18]=createBaseVNode(`p`,null,` Set the tone, level of detail and project requirements for your conversations. These choices follow your project source. `,-1)),createVNode(VBtn,{class:`project-settings__account-link`,height:`48`,type:`button`,variant:`text`,onClick:openPersonalSettings},{default:withCtx(()=>[..._cache[16]||(_cache[16]=[createTextVNode(` Set your Vibe64 name `,-1)])]),_:1})]),createBaseVNode(`div`,_hoisted_26,[createBaseVNode(`div`,_hoisted_27,[createVNode(VSelect,{modelValue:collaborationDraft.value.tone,"onUpdate:modelValue":_cache[4]||(_cache[4]=$event=>collaborationDraft.value.tone=$event),disabled:!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,density:`comfortable`,"hide-details":``,"item-title":`label`,"item-value":`value`,items:toneOptions.value,label:`Tone`,variant:`outlined`},null,8,[`modelValue`,`disabled`,`items`]),createVNode(VSelect,{modelValue:collaborationDraft.value.responseLength,"onUpdate:modelValue":_cache[5]||(_cache[5]=$event=>collaborationDraft.value.responseLength=$event),disabled:!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,density:`comfortable`,"hide-details":``,"item-title":`label`,"item-value":`value`,items:responseLengthOptions.value,label:`Response length`,variant:`outlined`},null,8,[`modelValue`,`disabled`,`items`]),createVNode(VSelect,{modelValue:collaborationDraft.value.experience,"onUpdate:modelValue":_cache[6]||(_cache[6]=$event=>collaborationDraft.value.experience=$event),disabled:!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,density:`comfortable`,"hide-details":``,"item-title":`label`,"item-value":`value`,items:experienceOptions.value,label:`Experience level`,variant:`outlined`},null,8,[`modelValue`,`disabled`,`items`]),createVNode(VSelect,{modelValue:collaborationDraft.value.explanationStyle,"onUpdate:modelValue":_cache[7]||(_cache[7]=$event=>collaborationDraft.value.explanationStyle=$event),disabled:!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,density:`comfortable`,"hide-details":``,"item-title":`label`,"item-value":`value`,items:explanationStyleOptions.value,label:`Explanation style`,variant:`outlined`},null,8,[`modelValue`,`disabled`,`items`]),createVNode(VTextarea,{modelValue:collaborationDraft.value.requirements,"onUpdate:modelValue":_cache[8]||(_cache[8]=$event=>collaborationDraft.value.requirements=$event),class:`project-settings__ai-note`,disabled:!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,"auto-grow":``,density:`comfortable`,"hide-details":``,label:`Project requirements (optional)`,placeholder:`For example: use Australian English.`,rows:`6`,"max-rows":`18`,variant:`outlined`},null,8,[`modelValue`,`disabled`])]),createBaseVNode(`div`,_hoisted_28,[!collaborationAvailable.value?(openBlock(),createElementBlock(`p`,_hoisted_29,toDisplayString(collaborationUnavailableReason.value),1)):!collaborationCanEdit.value?(openBlock(),createElementBlock(`p`,_hoisted_30,` Only the project owner can change these controls in Settings. Anyone who can edit this source can change genesis/collaboration.md directly. `)):(openBlock(),createElementBlock(`p`,_hoisted_31,` Applies when a conversation next starts or refreshes its context. Existing history and instructions in an active Codex conversation stay as they are. `)),createVNode(VBtn,{disabled:!collaborationChanged.value||!collaborationAvailable.value||!collaborationCanEdit.value||collaborationSaving.value,color:collaborationChanged.value?`primary`:void 0,height:`48`,type:`button`,variant:`flat`,onClick:saveCollaboration},{default:withCtx(()=>[createTextVNode(toDisplayString(collaborationSaving.value?`Saving…`:`Save collaboration`),1)]),_:1},8,[`disabled`,`color`])])])]),createBaseVNode(`section`,_hoisted_32,[_cache[19]||(_cache[19]=createBaseVNode(`div`,{class:`project-settings__section-copy text-body-medium`},[createBaseVNode(`h2`,{id:`prompt-suggestions-title`,class:`text-title-medium font-weight-bold`},`Prompt suggestions`),createBaseVNode(`p`,null,`Get ideas for what to ask next. This Vibe64 setting does not change your AI's instructions.`)],-1)),createBaseVNode(`div`,_hoisted_33,[createVNode(VSwitch,{modelValue:promptHintsDraft.value,"onUpdate:modelValue":_cache[9]||(_cache[9]=$event=>promptHintsDraft.value=$event),class:`project-settings__ai-hints`,color:`primary`,disabled:!promptHintsCanEdit.value||promptHintsSaving.value,"hide-details":``,label:`Suggest useful next prompts`},null,8,[`modelValue`,`disabled`]),createBaseVNode(`div`,_hoisted_34,[createVNode(VBtn,{disabled:!promptHintsChanged.value||!promptHintsCanEdit.value||promptHintsSaving.value,color:promptHintsChanged.value?`primary`:void 0,height:`48`,type:`button`,variant:`flat`,onClick:savePromptHints},{default:withCtx(()=>[createTextVNode(toDisplayString(promptHintsSaving.value?`Saving…`:`Save prompt suggestions`),1)]),_:1},8,[`disabled`,`color`])])])]),repositoryWorkflow.value.available?(openBlock(),createElementBlock(`section`,_hoisted_35,[_cache[22]||(_cache[22]=createBaseVNode(`div`,{class:`project-settings__section-copy text-body-medium`},[createBaseVNode(`h2`,{id:`repository-workflow-title`,class:`text-title-medium font-weight-bold`},`Git workflow`),createBaseVNode(`p`,null,`Choose how Vibe64 saves changes to this repository.`)],-1)),createBaseVNode(`div`,_hoisted_36,[createVNode(VRadioGroup,{modelValue:requirePullRequest.value,"onUpdate:modelValue":_cache[10]||(_cache[10]=$event=>requirePullRequest.value=$event),label:`GitHub save workflow`,color:`primary`,"hide-details":``,disabled:!repositoryWorkflow.value.canEdit||unref(repositoryWorkflowCommand).isRunning},{default:withCtx(()=>[createVNode(VRadio,{label:`Allow direct commits and pushes`,value:false,class:`py-1`}),createVNode(VRadio,{label:`Require pull requests`,value:true,class:`py-1`})]),_:1},8,[`modelValue`,`disabled`]),_cache[20]||(_cache[20]=createBaseVNode(`p`,null,`GitHub branch rules still apply. Requiring pull requests makes Create draft PR the main Save action until a session is attached to a PR.`,-1)),_cache[21]||(_cache[21]=createBaseVNode(`p`,null,`This setting controls Vibe64's Save actions. GitHub rules control pushes from terminals and other tools.`,-1)),createBaseVNode(`div`,_hoisted_37,[createVNode(VBtn,{color:requirePullRequest.value!==repositoryWorkflow.value.requirePullRequest?`primary`:void 0,height:`48`,variant:`flat`,disabled:!repositoryWorkflow.value.canEdit||unref(repositoryWorkflowCommand).isRunning||requirePullRequest.value===repositoryWorkflow.value.requirePullRequest,onClick:saveRepositoryWorkflow},{default:withCtx(()=>[createTextVNode(toDisplayString(unref(repositoryWorkflowCommand).isRunning?`Saving…`:`Save repository workflow`),1)]),_:1},8,[`color`,`disabled`])])])])):createCommentVNode(``,true)],64))])}}};var ProjectSettingsPanel_default=_plugin_vue_export_helper_default(_sfc_main$1,[[`__scopeId`,`data-v-d2b09657`]]);var _hoisted_1={class:`vibe64-dashboard-page`};var _sfc_main={__name:`index`,setup(__props){return(_ctx,_cache)=>{return openBlock(),createElementBlock(`section`,_hoisted_1,[createVNode(ProjectSettingsPanel_default)])}}};var settings_default=_plugin_vue_export_helper_default(_sfc_main,[[`__scopeId`,`data-v-d998a641`]]);export{settings_default as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{Ht as watch,g as computed,hn as proxyRefs,vn as ref}from"./runtime-core.esm-bundler-DGXg_mpN.js";import{D as ROUTE_VISIBILITY_PUBLIC,t as useEndpointResource}from"./useEndpointResource-7-YDfAxX.js";import{g as useRoute}from"./useApi-BPuI6ZR9-CFWU1m37.js";import{d as getHttpWebClient,r as projectAppPath}from"./vibe64ProjectScope.local-l5_-E6pq.js";import{Nt as mdiFileDocumentOutline,gr as mdiSourceBranch,yr as mdiSourceCommit}from"./mdi-X9prU-DG.js";import{a as normalizeConversationLogPage,i as mergeConversationLogPages,o as normalizeConversationLogPagination,r as conversationLogReadQuery}from"./conversation-DG9lp25w.js";import{t as usePaths}from"./usePaths-Y6UuQxmI.js";import{n as useVibe64ProjectSlug}from"./useVibe64ProjectScope-DXjsKKhl.js";import{B as vibe64SessionsQueryKey,F as vibe64SessionPath,b as vibe64ConversationLogQueryKey,n as VIBE64_ARCHIVED_SESSIONS_API_SUFFIX,o as VIBE64_SESSIONS_API_SUFFIX,y as vibe64ConversationLogPath,z as vibe64SessionQueryKey}from"./vibe64SessionRequestConfig-xIx-5jxQ.js";import{C as readRefOrGetterValue}from"./index-CGz4Yow6.js";import{t as isArchivedVibe64Session}from"./vibe64SessionViewModel-B0cCumM8.js";import{n as enrichVibe64SessionForDisplay}from"./vibe64SessionPanelModel-DoorGDCG.js";import{t as normalizeConversationLog}from"./useVibe64ConversationLog-ChJOU2SD.js";function useArchivedVibe64ConversationHistory({active=true,projectSlug,session,sessionsApiPath}={}){const httpClient=getHttpWebClient();const sessionId=computed(()=>String(readRefOrGetterValue(session)?.sessionId||``).trim());const enabled=computed(()=>readRefOrGetterValue(active)!==false&&Boolean(sessionId.value));const path=computed(()=>sessionId.value?vibe64ConversationLogPath(readRefOrGetterValue(sessionsApiPath),sessionId.value):``);const resource=useEndpointResource({enabled,fallbackLoadError:`Conversation history could not be loaded.`,path,queryKey:computed(()=>vibe64ConversationLogQueryKey(`app`,ROUTE_VISIBILITY_PUBLIC,sessionId.value,readRefOrGetterValue(projectSlug))),queryOptions:{queryFn:({signal})=>httpClient.request(path.value,{method:`GET`,query:conversationLogReadQuery(),signal}),placeholderData:previousData=>previousData,refetchOnMount:false,refetchOnWindowFocus:false},readMethod:`GET`,refreshOnPull:true,requestRecoveryLabel:`Conversation history`,realtime:null});const olderPages=ref([]);const loadingMore=ref(false);const loadMoreError=ref(``);const latestPage=computed(()=>normalizeConversationLogPage(resource.data.value||{}));const oldestLoadedPage=computed(()=>olderPages.value[0]||latestPage.value);const hasMoreBefore=computed(()=>Boolean(normalizeConversationLogPagination(oldestLoadedPage.value?.pagination).hasMoreBefore));const turns=computed(()=>normalizeConversationLog(mergeConversationLogPages([...olderPages.value,latestPage.value])));function reload(){olderPages.value=[];loadMoreError.value=``;return resource.reload()}async function loadMore({complete}={}){const finish=result=>{if(typeof complete===`function`)complete(result)};const pagination=normalizeConversationLogPagination(oldestLoadedPage.value?.pagination);const beforeTurnId=pagination.nextBeforeTurnId||pagination.oldestTurnId||String(turns.value[0]?.turnId||``).trim();if(!enabled.value||!path.value||!hasMoreBefore.value||loadingMore.value||!beforeTurnId){finish({changed:false,loaded:false});return false}const requestedSessionId=sessionId.value;loadingMore.value=true;loadMoreError.value=``;try{const page=await httpClient.request(path.value,{method:`GET`,query:conversationLogReadQuery({beforeTurnId,limit:10})});if(sessionId.value!==requestedSessionId){finish({changed:false,loaded:false});return false}const messageCount=()=>turns.value.reduce((count,turn)=>count+(turn.messages?.length||0),0);const previousOldestTurnId=String(turns.value[0]?.turnId||``).trim();const previousMessageCount=messageCount();olderPages.value=[normalizeConversationLogPage(page),...olderPages.value];const nextOldestTurnId=String(turns.value[0]?.turnId||``).trim();finish({changed:Boolean(nextOldestTurnId&&(nextOldestTurnId!==previousOldestTurnId||messageCount()!==previousMessageCount)),loaded:true});return true}catch(error){if(sessionId.value===requestedSessionId)loadMoreError.value=String(error?.message||error||`Older conversation history could not be loaded.`);finish({changed:false,loaded:false});return false}finally{loadingMore.value=false}}watch(sessionId,()=>{olderPages.value=[];loadMoreError.value=``});return{error:resource.loadError,hasMoreBefore,loadMore,loadMoreError,loading:resource.isLoading,loadingMore,reload,turns}}var archivedVibe64SessionsEmits=[`loading-changed`];var archivedAtFormatter=new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`short`});var archivedVibe64SessionsProps={description:{default:``,type:String},emptyText:{default:``,type:String},emptyTitle:{default:`No sessions`,type:String},showRefresh:{default:true,type:Boolean},title:{default:``,type:String}};function useArchivedVibe64Sessions(emit){const paths=usePaths();const projectSlug=useVibe64ProjectSlug();const sessionsApiPath=computed(()=>paths.api(VIBE64_ARCHIVED_SESSIONS_API_SUFFIX,{surface:`app`}));const sessionListResource=useEndpointResource({fallbackLoadError:`Archived sessions could not be loaded.`,path:sessionsApiPath,queryKey:computed(()=>[...vibe64SessionsQueryKey(`app`,ROUTE_VISIBILITY_PUBLIC,projectSlug.value),`archived`]),requestRecoveryLabel:`Archived sessions`});const loading=computed(()=>Boolean(sessionListResource.isLoading.value));const error=computed(()=>String(sessionListResource.loadError.value||``));const sessions=computed(()=>{const payload=sessionListResource.data.value;return(Array.isArray(payload?.sessions)?payload.sessions:[]).map(enrichVibe64SessionForDisplay).filter(isArchivedVibe64Session)});watch(loading,isLoading=>{emit(`loading-changed`,isLoading)},{immediate:true});return{unavailableSessions:computed(()=>sessionListResource.data.value?.unavailableSessions||[]),error,loadSessions,loading,formatArchivedAt,sessionRoute,sessions};async function loadSessions(){await sessionListResource.reload()}function sessionRoute(session={}){return archivedSessionDetailRoute({projectSlug:projectSlug.value,sessionId:session.sessionId})}}function useArchivedVibe64SessionDetail(){const route=useRoute();const paths=usePaths();const projectSlug=useVibe64ProjectSlug(route);const sessionId=computed(()=>firstRouteParam(route.params.sessionId));const sessionsApiPath=computed(()=>paths.api(VIBE64_SESSIONS_API_SUFFIX,{surface:`app`}));const sessionPath=computed(()=>sessionId.value?vibe64SessionPath(sessionsApiPath.value,sessionId.value):``);const sessionResource=useEndpointResource({enabled:computed(()=>Boolean(sessionId.value)),fallbackLoadError:`Archived session could not be loaded.`,path:sessionPath,queryKey:computed(()=>[...vibe64SessionQueryKey(`app`,ROUTE_VISIBILITY_PUBLIC,projectSlug.value),`archive-detail`,sessionId.value]),readQuery:computed(()=>projectSlug.value?{projectSlug:projectSlug.value}:null),requestRecoveryLabel:`Archived session`});const session=computed(()=>{const payload=sessionResource.data.value;if(!payload||typeof payload!==`object`||Array.isArray(payload))return null;if(String(payload.sessionId||``).trim()!==sessionId.value)return null;const enrichedSession=enrichVibe64SessionForDisplay(payload);return isArchivedVibe64Session(enrichedSession)?enrichedSession:null});return{backTo:computed(()=>({path:`${projectAppPath(projectSlug.value)}/dashboard/history`})),conversationLog:proxyRefs(useArchivedVibe64ConversationHistory({active:computed(()=>Boolean(session.value)),projectSlug,session,sessionsApiPath})),error:computed(()=>String(sessionResource.loadError.value||``)),loading:computed(()=>Boolean(sessionResource.isLoading.value||sessionResource.isInitialLoading?.value)),reload:sessionResource.reload,session,sessionId,sessionsApiPath,projectSlug}}function formatArchivedAt(value=``){const date=new Date(String(value||``));return Number.isNaN(date.getTime())?`time unavailable`:archivedAtFormatter.format(date)}function archivedSessionDetailRoute({projectSlug=``,sessionId=``}={}){return{path:`${projectAppPath(projectSlug)}/dashboard/history/${encodeURIComponent(String(sessionId||``).trim())}`}}function firstRouteParam(value){return String(Array.isArray(value)?value[0]:value||``).trim()}function metadataValue(session={},name=``){return String(session.metadata?.[name]||``).trim()}function archiveFactRows(session={}){return[{icon:mdiSourceBranch,label:`Branch`,value:session.branch||metadataValue(session,`source_recovery_branch`)},{icon:mdiSourceCommit,label:`Head`,value:metadataValue(session,`source_recovery_head`)||metadataValue(session,`base_commit`)},{icon:mdiFileDocumentOutline,label:`Saved patch`,value:metadataValue(session,`source_recovery_patch_artifact`)||`No saved patch`},{icon:mdiFileDocumentOutline,label:`Untracked files`,value:metadataValue(session,`source_recovery_untracked_artifact`)||`No saved untracked archive`}].filter(row=>row.value)}export{useArchivedVibe64Sessions as a,useArchivedVibe64SessionDetail as i,archivedVibe64SessionsEmits as n,archivedVibe64SessionsProps as r,archiveFactRows as t};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ht as watch,On as unref,g as computed,gn as reactive,hn as proxyRefs}from"./runtime-core.esm-bundler-DGXg_mpN.js";import{r as useShellWebErrorRuntime}from"./error-W1ZAEk4a.js";import{A as useJskitText,C as resolveEnabledRef,S as ROUTE_VISIBILITY_WORKSPACE,_ as resolveApiSuffix,b as resolveQueryKey,d as asPlainObject,f as ensureAccessModeCompatibility,g as resolveAccessModeEnabled,h as normalizePermissions,l as toUiFieldErrors,m as normalizeOwnershipFilter,p as normalizeAccessMode,r as useOperationRealtime,t as useEndpointResource,tt as useQueryClient,v as resolveEnabled,y as resolvePermissionAccess}from"./useEndpointResource-tVvsJvd4.js";import{o as normalizeSurfaceId}from"./returnToPath-gKtcu91D.js";import{f as normalizeText}from"./normalize-BNAdWJYg.js";import{C as validateSchemaPayload,d as getHttpWebClient,m as createValidationFailure,v as hasPermission,y as normalizePermissionList}from"./vibe64ProjectScope.local-l5_-E6pq.js";import{n as resolveScopedRouteBase}from"./surface-DzO5xqc8.js";import{c as useWebPlacementContext,r as resolveSurfaceDefinitionFromPlacementContext}from"./placement-DYM3JJ-F.js";import{r as useSurfaceRouteContext,t as usePaths}from"./usePaths-Y6UuQxmI.js";import{t as useUiFeedback}from"./useUiFeedback-DLUToc5y.js";var{t:t$3,text:text$1}=useJskitText();function validateOperationInput({input,rawPayload={},fieldBag=null,feedback=null,validationMessage=``}={}){if(!input)return{ok:true,parsedInput:rawPayload};try{return{ok:true,parsedInput:validateSchemaPayload(input,rawPayload,{phase:`input`,context:`operation input`})}}catch(error){if(!error?.fieldErrors||typeof error.fieldErrors!==`object`)throw error;const fieldErrorCodes=error.fieldErrorCodes||error.details?.fieldErrorCodes;const failure={...createValidationFailure({error:text$1(validationMessage)||t$3(`jskit.http.feedback.validationFailed`),code:`validation_failed`,fieldErrors:error?.fieldErrors}),...fieldErrorCodes?{fieldErrorCodes}:{}};fieldBag?.apply?.(toUiFieldErrors(failure));feedback?.error?.(failure,failure.error);return{ok:false,failure,parsedInput:null}}}var{t:t$2,text}=useJskitText();function useCommandCore({model,resource,writeMethod=`POST`,canRun,fieldBag,feedback,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage=false,messages={}}={}){const queryClient=useQueryClient();const normalizedWriteMethod=String(writeMethod||`POST`).trim().toUpperCase();const running=resource?.isSaving;const fieldErrors=fieldBag?.errors;const message=feedback?.message;const messageType=feedback?.messageType;async function run(context={}){if(!canRun?.value||running?.value)return null;feedback?.clear?.();fieldBag?.clear?.();const rawPayload=typeof buildRawPayload===`function`?buildRawPayload(model,{queryClient,resource,context}):{};const validationResult=validateOperationInput({input,rawPayload,fieldBag,feedback,validationMessage:text(messages.validation)||t$2(`jskit.http.feedback.validationFailed`)});if(!validationResult.ok)return null;const{parsedInput}=validationResult;const payload=typeof buildCommandPayload===`function`?buildCommandPayload(parsedInput,{rawPayload,queryClient,resource,context}):normalizedWriteMethod===`DELETE`?void 0:parsedInput;const options=typeof buildCommandOptions===`function`?buildCommandOptions(parsedInput,{rawPayload,queryClient,resource,context}):{};try{const response=await resource.save(payload,options);if(typeof onRunSuccess===`function`)await onRunSuccess(response,{parsed:parsedInput,rawPayload,payload,options,queryClient,resource,context});if(!suppressSuccessMessage)feedback?.success?.(text(messages.success)||t$2(`jskit.http.feedback.completed`));return response}catch(error){fieldBag?.apply?.(toUiFieldErrors(error));if(typeof onRunError===`function`)await onRunError(error,{parsed:parsedInput,rawPayload,payload,options,queryClient,resource,context});feedback?.error?.(error,text(messages.error)||t$2(`jskit.http.feedback.actionFailed`));throw error}}return Object.freeze({running,fieldErrors,message,messageType,run})}var{t:t$1}=useJskitText();function asPermissionList(value){if(Array.isArray(value))return value;if(value===void 0||value===null||value===``)return[];return[value]}function useAccess({enabled=true,access=`always`,hasPermissionRequirements=false}={}){const normalizedAccessMode=normalizeAccessMode(access);const accessRequired=resolveAccessModeEnabled(normalizedAccessMode,{hasPermissionRequirements:hasPermissionRequirements===true});const{context:placementContext}=useWebPlacementContext();const queryEnabled=computed(()=>resolveEnabledRef(enabled)&&accessRequired);const hasPlacementPermissions=computed(()=>{const source=placementContext.value;if(!source||typeof source!==`object`)return false;return Object.hasOwn(source,`permissions`)});const placementPermissions=computed(()=>normalizePermissionList(placementContext.value?.permissions));const permissions=computed(()=>{if(!queryEnabled.value||!hasPlacementPermissions.value)return[];return placementPermissions.value});const permissionsUnavailableError=computed(()=>{if(!queryEnabled.value||hasPlacementPermissions.value)return``;return t$1(`jskit.http.access.permissionsUnavailable`)});const awaitingPlacementPermissions=computed(()=>queryEnabled.value&&!hasPlacementPermissions.value);function can(permission){return hasPermission(permissions.value,permission)}function canAny(requiredPermissions){const list=asPermissionList(requiredPermissions);if(list.length<1)return true;for(const entry of list)if(can(entry))return true;return false}function canAll(requiredPermissions){const list=asPermissionList(requiredPermissions);if(list.length<1)return true;for(const entry of list)if(!can(entry))return false;return true}return Object.freeze({accessMode:normalizedAccessMode,accessRequired,permissions,permissionsUnavailableError,awaitingPlacementPermissions,can,canAny,canAll})}var ROUTE_PARAM_NAME_PATTERN=/^[A-Za-z][A-Za-z0-9_]*$/;function normalizeRouteParamName(value=``,{context=`http-web route param`}={}){const normalizedValue=String(value||``).trim();if(!normalizedValue)throw new TypeError(`${context} must be a non-empty route parameter name.`);if(!ROUTE_PARAM_NAME_PATTERN.test(normalizedValue))throw new TypeError(`${context} "${normalizedValue}" is invalid. Use letters, numbers, and underscores only.`);return normalizedValue}function toRouteParamValue(value){if(Array.isArray(value))return toRouteParamValue(value[0]);if(value==null)return``;return String(value).trim()}function resolveRouteSourceValue(source=null){if(typeof source===`function`)return source();return unref(source)}function resolveRouteParamsSource(source=null){return asPlainObject(resolveRouteSourceValue(source))}function normalizeRouteParamNameList(value=[]){return(Array.isArray(value)?value:[]).map(entry=>String(entry||``).trim()).filter(Boolean)}function resolveRouteParamNamesSource(source=[]){return normalizeRouteParamNameList(resolveRouteSourceValue(source))}function normalizeRoutePathname(value=``){const sanitizedPathname=String(value||``).trim().split(/[?#]/u,1)[0]||``;if(!sanitizedPathname)return`/`;return sanitizedPathname.startsWith(`/`)?sanitizedPathname:`/${sanitizedPathname}`}function resolveRoutePathnameSource(source=``){return normalizeRoutePathname(resolveRouteSourceValue(source))}function segmentMatchesParamValue(segment=``,paramValue=``){const normalizedSegment=String(segment||``).trim();const normalizedParamValue=toRouteParamValue(paramValue);if(!normalizedSegment||!normalizedParamValue)return false;if(normalizedSegment===encodeURIComponent(normalizedParamValue))return true;try{return decodeURIComponent(normalizedSegment)===normalizedParamValue}catch{return false}}function findRouteParamSegmentIndex(segments=[],paramValue=``,fromIndex=0){const source=Array.isArray(segments)?segments:[];const cursor=Number.isInteger(fromIndex)&&fromIndex>0?fromIndex:0;for(let index=cursor;index<source.length;index+=1)if(segmentMatchesParamValue(source[index],paramValue))return index;return-1}function normalizePathPrefix(segments=[],endIndex=-1){const source=Array.isArray(segments)?segments:[];if(!Number.isInteger(endIndex)||endIndex<0)return`/`;return`/${source.slice(0,endIndex+1).join(`/`)}`}function resolveAnchorEndIndex(segmentIndex=-1,totalSegments=0,anchorMode=`at`){const normalizedSegmentIndex=Number.isInteger(segmentIndex)?segmentIndex:-1;if(normalizedSegmentIndex<0)return-1;const normalizedTotalSegments=Number.isInteger(totalSegments)&&totalSegments>0?totalSegments:0;const normalizedMode=String(anchorMode||`at`).trim().toLowerCase();if(normalizedMode===`before`)return normalizedSegmentIndex-1;if(normalizedMode===`after`)return normalizedTotalSegments>0?Math.min(normalizedSegmentIndex+1,normalizedTotalSegments-1):normalizedSegmentIndex+1;return normalizedSegmentIndex}function resolveScopedRoutePathname({currentPathname=`/`,params={},orderedParamNames=[],anchorParamName=``,anchorParamValue=``,anchorMode=`at`}={}){const normalizedCurrentPathname=resolveRoutePathnameSource(currentPathname);const normalizedAnchorParamName=String(anchorParamName||``).trim();if(!normalizedAnchorParamName)return normalizedCurrentPathname;const sourceParams=asPlainObject(params);const segments=normalizedCurrentPathname.split(`/`).filter(Boolean);if(segments.length<1)return normalizedCurrentPathname;const paramNames=resolveRouteParamNamesSource(orderedParamNames);let cursor=0;for(const paramName of paramNames){const segmentIndex=findRouteParamSegmentIndex(segments,sourceParams[paramName],cursor);if(segmentIndex<0)continue;if(paramName===normalizedAnchorParamName)return normalizePathPrefix(segments,resolveAnchorEndIndex(segmentIndex,segments.length,anchorMode));cursor=segmentIndex+1}const fallbackAnchorValue=toRouteParamValue(anchorParamValue)||toRouteParamValue(sourceParams[normalizedAnchorParamName]);if(!fallbackAnchorValue)return normalizedCurrentPathname;const fallbackSegmentIndex=findRouteParamSegmentIndex(segments,fallbackAnchorValue,0);if(fallbackSegmentIndex<0)return normalizedCurrentPathname;return normalizePathPrefix(segments,resolveAnchorEndIndex(fallbackSegmentIndex,segments.length,anchorMode))}function resolveRouteTemplatePath(routeTemplate=``,params={}){const normalizedTemplate=String(routeTemplate||``).trim();if(!normalizedTemplate)return``;const source=asPlainObject(params);const missingParams=[];const resolvedPath=normalizedTemplate.replace(/:([A-Za-z][A-Za-z0-9_]*)/g,(_,key)=>{const value=toRouteParamValue(source[key]);if(!value){missingParams.push(key);return`:${key}`}return encodeURIComponent(value)});if(missingParams.length>0)return``;return resolvedPath}function resolveRouteTemplateLocation(routeTemplate=``,{params={},currentPathname=`/`}={}){const resolvedTemplatePath=resolveRouteTemplatePath(routeTemplate,params);if(!resolvedTemplatePath)return``;if(resolvedTemplatePath.startsWith(`/`))return resolvedTemplatePath;const normalizedCurrentPathname=resolveRoutePathnameSource(currentPathname);const basePathname=normalizedCurrentPathname.endsWith(`/`)?normalizedCurrentPathname:`${normalizedCurrentPathname}/`;const resolvedPathname=new URL(resolvedTemplatePath,`https://jskit.local${basePathname}`).pathname;if(resolvedPathname.length>1&&resolvedPathname.endsWith(`/`))return resolvedPathname.slice(0,-1);return resolvedPathname}function createRouteTemplateResolver({recordIdParam,routeParams=null,routeParamNames=null,routePath=``,routeRecordId=null,anchorMode=`at`,anchorOnTargetRecord=false,fillRecordId=true}={}){function resolveCurrentRecordId(currentRouteParams=resolveRouteParamsSource(routeParams)){const explicitRecordId=toRouteParamValue(resolveRouteSourceValue(routeRecordId));if(explicitRecordId)return explicitRecordId;return toRouteParamValue(currentRouteParams[recordIdParam])}function resolveTemplatePath(urlTemplate=``,extraParams={}){const normalizedTemplate=String(urlTemplate||``).trim();if(!normalizedTemplate)return``;const currentRouteParams=resolveRouteParamsSource(routeParams);const sourceParams={...currentRouteParams,...asPlainObject(extraParams)};const currentRecordId=resolveCurrentRecordId(currentRouteParams);const targetRecordId=toRouteParamValue(sourceParams[recordIdParam])||currentRecordId;if(fillRecordId)sourceParams[recordIdParam]=targetRecordId;return resolveRouteTemplateLocation(normalizedTemplate,{params:sourceParams,currentPathname:resolveScopedRoutePathname({currentPathname:routePath,params:currentRouteParams,orderedParamNames:routeParamNames,anchorParamName:recordIdParam,anchorParamValue:anchorOnTargetRecord?targetRecordId:currentRecordId,anchorMode})})}return Object.freeze({resolveRecordId:()=>resolveCurrentRecordId(),resolveTemplatePath})}function extractRouteParamNames(pathTemplate=``){const normalizedTemplate=String(pathTemplate||``).trim();if(!normalizedTemplate)return[];const names=[];const seen=new Set;const pattern=/:([A-Za-z][A-Za-z0-9_]*)/g;let match=null;while((match=pattern.exec(normalizedTemplate))!=null){const name=String(match[1]||``).trim();if(!name||seen.has(name))continue;seen.add(name);names.push(name)}return names}function resolveRouteParamNamesInOrder(route=null){const sourceRoute=route&&typeof route===`object`?route:{};const matched=Array.isArray(sourceRoute.matched)?sourceRoute.matched:[];const names=[];const seen=new Set;for(const entry of matched){const entryPath=String(entry?.path||``).trim();if(!entryPath)continue;for(const name of extractRouteParamNames(entryPath)){if(seen.has(name))continue;seen.add(name);names.push(name)}}if(names.length>0)return names;return Object.keys(asPlainObject(sourceRoute.params)).map(entry=>String(entry||``).trim()).filter(Boolean)}var{t}=useJskitText();function resolveScopedRouteParamNames(placementContext=null,surfaceId=``){const routeBase=resolveSurfaceDefinitionFromPlacementContext(placementContext,surfaceId)?.routeBase||`/`;return extractRouteParamNames(resolveScopedRouteBase(routeBase))}function useScopeRuntime({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,accessMode=`auto`,hasPermissionRequirements=false}={}){const normalizedOwnershipFilter=normalizeOwnershipFilter(ownershipFilter);const normalizedAccessMode=ensureAccessModeCompatibility({accessMode,hasPermissionRequirements,caller:`useScopeRuntime`});const accessRequired=resolveAccessModeEnabled(normalizedAccessMode,{hasPermissionRequirements});const routeContext=useSurfaceRouteContext();const paths=usePaths({routeContext});const resolvedSurfaceId=computed(()=>{const explicitSurfaceId=normalizeSurfaceId(surfaceId);if(explicitSurfaceId)return explicitSurfaceId;return normalizeSurfaceId(routeContext.currentSurfaceId.value)});const scopedRouteParamNames=computed(()=>resolveScopedRouteParamNames(routeContext.placementContext.value,resolvedSurfaceId.value));const routeScopeParams=computed(()=>{const source=paths.routeParams.value;const next={};for(const paramName of scopedRouteParamNames.value){const paramValue=toRouteParamValue(source[paramName]);if(paramValue)next[paramName]=paramValue}return Object.freeze(next)});const missingScopedRouteParamNames=computed(()=>scopedRouteParamNames.value.filter(paramName=>!routeScopeParams.value[paramName]));const requiresScopedRouteParams=computed(()=>scopedRouteParamNames.value.length>0);const hasRequiredRouteScope=computed(()=>missingScopedRouteParamNames.value.length<1);const scopeParamValue=computed(()=>{const[primaryScopeParamName=``]=scopedRouteParamNames.value;return primaryScopeParamName?routeScopeParams.value[primaryScopeParamName]||``:``});const routeScopeError=computed(()=>{if(!requiresScopedRouteParams.value||hasRequiredRouteScope.value)return``;const missingParams=missingScopedRouteParamNames.value.join(`, `);return t(`jskit.http.access.routeParamsRequired`,{params:missingParams,surface:resolvedSurfaceId.value||`<unknown>`})});const accessRuntime=useAccess({enabled:computed(()=>accessRequired&&hasRequiredRouteScope.value),access:normalizedAccessMode,hasPermissionRequirements});function resolveApiPath(apiSuffix=``,context={}){if(routeScopeError.value)return``;const suffix=resolveApiSuffix(apiSuffix,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter,...asPlainObject(context)});return paths.api(suffix,{surface:resolvedSurfaceId.value,params:routeScopeParams.value})}function requireRouteScope(caller=`useScopeRuntime`){if(routeScopeError.value)throw new Error(`${caller}: ${routeScopeError.value}`)}return Object.freeze({normalizedOwnershipFilter,requiresScopedRouteParams:requiresScopedRouteParams.value,resolvedSurfaceId,accessMode:normalizedAccessMode,accessRequired,routeContext,scopedRouteParamNames,routeScopeParams,scopeParamValue,hasRequiredRouteScope,routeScopeError,access:accessRuntime,resolveApiPath,requireRouteScope})}function normalizePermissionSets(permissionSets={}){const source=permissionSets&&typeof permissionSets===`object`&&!Array.isArray(permissionSets)?permissionSets:{};const normalized={};for(const[key,value]of Object.entries(source))normalized[key]=normalizePermissions(value);return normalized}function hasAnyPermissions(permissionSets={}){for(const list of Object.values(permissionSets))if(Array.isArray(list)&&list.length>0)return true;return false}function useOperationScope({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,access=`auto`,apiSuffix=``,model,readEnabled=true,queryKeyFactory=null,permissionSets={},realtime=null}={}){const normalizedPermissionSets=normalizePermissionSets(permissionSets);const scopeRuntime=useScopeRuntime({ownershipFilter,surfaceId,accessMode:access,hasPermissionRequirements:hasAnyPermissions(normalizedPermissionSets)});const normalizedOwnershipFilter=scopeRuntime.normalizedOwnershipFilter;const routeContext=scopeRuntime.routeContext;const scopeParamValue=scopeRuntime.scopeParamValue;const hasRequiredRouteScope=scopeRuntime.hasRequiredRouteScope;const accessRuntime=scopeRuntime.access;const apiPath=computed(()=>scopeRuntime.resolveApiPath(apiSuffix,{model}));const queryEnabled=computed(()=>resolveEnabled(readEnabled,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter,model}));const queryKey=computed(()=>resolveQueryKey(queryKeyFactory,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter}));const realtimeBinding=useOperationRealtime({realtime,queryKey:typeof queryKeyFactory===`function`?queryKey:null,enabled:computed(()=>hasRequiredRouteScope.value&&Boolean(apiPath.value))});function queryCanRun(accessGate=true){return computed(()=>queryEnabled.value&&hasRequiredRouteScope.value&&Boolean(apiPath.value)&&Boolean(unref(accessGate)))}function permissionGate(key=``){const list=normalizedPermissionSets[String(key||``)]||[];return computed(()=>resolvePermissionAccess(accessRuntime,list))}function loadError(baseError=``){return computed(()=>{if(scopeRuntime.routeScopeError.value)return scopeRuntime.routeScopeError.value;const permissionsError=String(accessRuntime.permissionsUnavailableError.value||``).trim();if(permissionsError)return permissionsError;if(baseError===void 0||baseError===null||baseError===``)return``;return String(unref(baseError)||``).trim()})}function isLoading(baseLoading=false){return computed(()=>Boolean(unref(baseLoading))||accessRuntime.awaitingPlacementPermissions.value)}return Object.freeze({scopeRuntime,routeContext,normalizedOwnershipFilter,scopeParamValue,hasRequiredRouteScope,access:accessRuntime,apiPath,queryEnabled,queryKey,queryCanRun,realtime:realtimeBinding,permissionGate,loadError,isLoading})}function normalizeFieldErrorKeys(keys){return Array.isArray(keys)?keys.map(entry=>String(entry||``).trim()).filter(Boolean):[]}function useFieldErrorBag(keys=[]){const normalizedKeys=normalizeFieldErrorKeys(keys);const hasFixedKeys=normalizedKeys.length>0;const errors=reactive(Object.fromEntries(normalizedKeys.map(key=>[key,``])));function clear(){const keysToClear=hasFixedKeys?normalizedKeys:Object.keys(errors);for(const key of keysToClear)errors[key]=``}function apply(source={}){const fieldErrorMap=source&&typeof source===`object`?source:{};if(hasFixedKeys){for(const key of normalizedKeys)errors[key]=String(fieldErrorMap[key]||``);return}clear();for(const[field,message]of Object.entries(fieldErrorMap)){const key=String(field||``).trim();if(!key)continue;errors[key]=String(message||``)}}function set(field,message){const key=String(field||``).trim();if(!key)return;if(hasFixedKeys&&!(key in errors))return;errors[key]=String(message||``)}return Object.freeze({errors,clear,apply,set})}function normalizeMessage(value){return String(value||``).trim()}function setupOperationErrorReporting({enabled=true,source=`http-web.operation`,loadError=null,notFoundError=null,loadActionFactory=null,notFoundActionFactory=null,loadChannel=``,notFoundChannel=``,loadSeverity=`error`,notFoundSeverity=`warning`,dedupeWindowMs=2e3}={}){if(!enabled)return;const runtime=useShellWebErrorRuntime();const normalizedSource=normalizeMessage(source)||`http-web.operation`;function watchMessage(value,{kind=`load`,channel=``,intent=`resource-load`,severity=`error`,actionFactory=null}={}){let lastMessage=``;let lastPresentationId=``;watch(()=>normalizeMessage(value?.value),nextMessage=>{if(!nextMessage){lastMessage=``;if(lastPresentationId){runtime.dismiss(lastPresentationId);lastPresentationId=``}return}if(nextMessage===lastMessage)return;lastMessage=nextMessage;const action=typeof actionFactory===`function`?actionFactory({message:nextMessage,kind}):null;const reportResult=runtime.report({source:normalizedSource,message:nextMessage,intent,severity,channel,action,dedupeKey:`${normalizedSource}:${kind}:${nextMessage}`,dedupeWindowMs});const nextPresentationId=String(reportResult?.presentationId||``).trim();if(nextPresentationId){if(lastPresentationId&&lastPresentationId!==nextPresentationId)runtime.dismiss(lastPresentationId);lastPresentationId=nextPresentationId}},{immediate:true})}if(loadError)watchMessage(loadError,{kind:`load`,channel:loadChannel,intent:`resource-load`,severity:loadSeverity,actionFactory:loadActionFactory});if(notFoundError)watchMessage(notFoundError,{kind:`not-found`,channel:notFoundChannel,intent:`resource-load`,severity:notFoundSeverity,actionFactory:notFoundActionFactory})}function setupRouteChangeCleanup({enabled=true,route=null,feedback=null,fieldBag=null,onClear=null}={}){if(!enabled)return;watch(()=>route?.fullPath,()=>{feedback?.clear?.();fieldBag?.clear?.();onClear?.()})}var CRUD_API_ACCESS_AUTHENTICATED=`authenticated`;var CRUD_API_ACCESS_PUBLIC=`public`;var CRUD_API_ACCESS_VALUES=Object.freeze([CRUD_API_ACCESS_AUTHENTICATED,CRUD_API_ACCESS_PUBLIC]);var publicCrudClients=new WeakSet;function normalizeCrudApiAccess(value=``){const normalized=normalizeText(value).toLowerCase()||`authenticated`;if(CRUD_API_ACCESS_VALUES.includes(normalized))return normalized;throw new TypeError(`CRUD resource apiAccess must be one of: ${CRUD_API_ACCESS_VALUES.join(`, `)}. Received: ${String(value||``)||`(empty)`}`)}function resolveCrudHttpClient(resource=null,{client=null}={}){const activeClient=client||getHttpWebClient();if(!activeClient||typeof activeClient.request!==`function`)throw new TypeError(`resolveCrudHttpClient requires a client with request().`);if(normalizeCrudApiAccess(resource?.apiAccess)!==`public`)return activeClient;if(publicCrudClients.has(activeClient))return activeClient;const publicClient=Object.freeze({request(url,options={}){const requestOptions=options&&typeof options===`object`&&!Array.isArray(options)?options:{};return activeClient.request(url,{...requestOptions,csrf:false})}});publicCrudClients.add(publicClient);return publicClient}function useCommand({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,access=`auto`,apiSuffix=``,runPermissions=[],writeMethod=`POST`,client=null,resource:commandResource=null,transport=null,placementSource=`http-web.command`,fallbackRunError=`jskit.http.feedback.actionFailed`,fieldErrorKeys=[],clearOnRouteChange=true,model,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage=false,messages={},realtime=null}={}){const operationScope=useOperationScope({ownershipFilter,surfaceId,access,apiSuffix,model,readEnabled:false,permissionSets:{run:runPermissions},realtime});const routeContext=operationScope.routeContext;const canRun=operationScope.permissionGate(`run`);const endpointResource=useEndpointResource({path:operationScope.apiPath,enabled:false,client:resolveCrudHttpClient(commandResource,{client}),writeMethod,transport,fallbackSaveError:fallbackRunError});const feedback=useUiFeedback({source:`${placementSource}.feedback`});const fieldBag=useFieldErrorBag(fieldErrorKeys);const command=useCommandCore({model,resource:endpointResource,writeMethod,canRun,fieldBag,feedback,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage:Boolean(suppressSuccessMessage),messages:{validation:`jskit.http.feedback.fixInvalidValues`,success:`jskit.http.feedback.completed`,error:String(fallbackRunError||`jskit.http.feedback.actionFailed`),...messages&&typeof messages===`object`?messages:{}}});setupRouteChangeCleanup({enabled:clearOnRouteChange,route:routeContext.route,feedback,fieldBag});const loadError=operationScope.loadError();const isLoading=operationScope.isLoading();setupOperationErrorReporting({source:`${placementSource}.load`,loadError});return proxyRefs({canRun,isLoading,loadError,isRunning:command.running,fieldErrors:command.fieldErrors,message:command.message,messageType:command.messageType,run:command.run,resource:endpointResource})}export{useOperationScope as a,resolveRouteParamNamesInOrder as c,validateOperationInput as d,useFieldErrorBag as i,toRouteParamValue as l,setupOperationErrorReporting as n,createRouteTemplateResolver as o,setupRouteChangeCleanup as r,normalizeRouteParamName as s,useCommand as t,useAccess as u};
|
|
1
|
+
import{Ht as watch,On as unref,g as computed,gn as reactive,hn as proxyRefs}from"./runtime-core.esm-bundler-DGXg_mpN.js";import{r as useShellWebErrorRuntime}from"./error-W1ZAEk4a.js";import{A as useJskitText,C as resolveEnabledRef,S as ROUTE_VISIBILITY_WORKSPACE,_ as resolveApiSuffix,b as resolveQueryKey,d as asPlainObject,f as ensureAccessModeCompatibility,g as resolveAccessModeEnabled,h as normalizePermissions,l as toUiFieldErrors,m as normalizeOwnershipFilter,p as normalizeAccessMode,r as useOperationRealtime,t as useEndpointResource,tt as useQueryClient,v as resolveEnabled,y as resolvePermissionAccess}from"./useEndpointResource-7-YDfAxX.js";import{o as normalizeSurfaceId}from"./returnToPath-gKtcu91D.js";import{f as normalizeText}from"./normalize-BNAdWJYg.js";import{C as validateSchemaPayload,d as getHttpWebClient,m as createValidationFailure,v as hasPermission,y as normalizePermissionList}from"./vibe64ProjectScope.local-l5_-E6pq.js";import{n as resolveScopedRouteBase}from"./surface-DzO5xqc8.js";import{c as useWebPlacementContext,r as resolveSurfaceDefinitionFromPlacementContext}from"./placement-DYM3JJ-F.js";import{r as useSurfaceRouteContext,t as usePaths}from"./usePaths-Y6UuQxmI.js";import{t as useUiFeedback}from"./useUiFeedback-Bd3rao6E.js";var{t:t$3,text:text$1}=useJskitText();function validateOperationInput({input,rawPayload={},fieldBag=null,feedback=null,validationMessage=``}={}){if(!input)return{ok:true,parsedInput:rawPayload};try{return{ok:true,parsedInput:validateSchemaPayload(input,rawPayload,{phase:`input`,context:`operation input`})}}catch(error){if(!error?.fieldErrors||typeof error.fieldErrors!==`object`)throw error;const fieldErrorCodes=error.fieldErrorCodes||error.details?.fieldErrorCodes;const failure={...createValidationFailure({error:text$1(validationMessage)||t$3(`jskit.http.feedback.validationFailed`),code:`validation_failed`,fieldErrors:error?.fieldErrors}),...fieldErrorCodes?{fieldErrorCodes}:{}};fieldBag?.apply?.(toUiFieldErrors(failure));feedback?.error?.(failure,failure.error);return{ok:false,failure,parsedInput:null}}}var{t:t$2,text}=useJskitText();function useCommandCore({model,resource,writeMethod=`POST`,canRun,fieldBag,feedback,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage=false,messages={}}={}){const queryClient=useQueryClient();const normalizedWriteMethod=String(writeMethod||`POST`).trim().toUpperCase();const running=resource?.isSaving;const fieldErrors=fieldBag?.errors;const message=feedback?.message;const messageType=feedback?.messageType;async function run(context={}){if(!canRun?.value||running?.value)return null;feedback?.clear?.();fieldBag?.clear?.();const rawPayload=typeof buildRawPayload===`function`?buildRawPayload(model,{queryClient,resource,context}):{};const validationResult=validateOperationInput({input,rawPayload,fieldBag,feedback,validationMessage:text(messages.validation)||t$2(`jskit.http.feedback.validationFailed`)});if(!validationResult.ok)return null;const{parsedInput}=validationResult;const payload=typeof buildCommandPayload===`function`?buildCommandPayload(parsedInput,{rawPayload,queryClient,resource,context}):normalizedWriteMethod===`DELETE`?void 0:parsedInput;const options=typeof buildCommandOptions===`function`?buildCommandOptions(parsedInput,{rawPayload,queryClient,resource,context}):{};try{const response=await resource.save(payload,options);if(typeof onRunSuccess===`function`)await onRunSuccess(response,{parsed:parsedInput,rawPayload,payload,options,queryClient,resource,context});if(!suppressSuccessMessage)feedback?.success?.(text(messages.success)||t$2(`jskit.http.feedback.completed`));return response}catch(error){fieldBag?.apply?.(toUiFieldErrors(error));if(typeof onRunError===`function`)await onRunError(error,{parsed:parsedInput,rawPayload,payload,options,queryClient,resource,context});feedback?.error?.(error,text(messages.error)||t$2(`jskit.http.feedback.actionFailed`));throw error}}return Object.freeze({running,fieldErrors,message,messageType,run})}var{t:t$1}=useJskitText();function asPermissionList(value){if(Array.isArray(value))return value;if(value===void 0||value===null||value===``)return[];return[value]}function useAccess({enabled=true,access=`always`,hasPermissionRequirements=false}={}){const normalizedAccessMode=normalizeAccessMode(access);const accessRequired=resolveAccessModeEnabled(normalizedAccessMode,{hasPermissionRequirements:hasPermissionRequirements===true});const{context:placementContext}=useWebPlacementContext();const queryEnabled=computed(()=>resolveEnabledRef(enabled)&&accessRequired);const hasPlacementPermissions=computed(()=>{const source=placementContext.value;if(!source||typeof source!==`object`)return false;return Object.hasOwn(source,`permissions`)});const placementPermissions=computed(()=>normalizePermissionList(placementContext.value?.permissions));const permissions=computed(()=>{if(!queryEnabled.value||!hasPlacementPermissions.value)return[];return placementPermissions.value});const permissionsUnavailableError=computed(()=>{if(!queryEnabled.value||hasPlacementPermissions.value)return``;return t$1(`jskit.http.access.permissionsUnavailable`)});const awaitingPlacementPermissions=computed(()=>queryEnabled.value&&!hasPlacementPermissions.value);function can(permission){return hasPermission(permissions.value,permission)}function canAny(requiredPermissions){const list=asPermissionList(requiredPermissions);if(list.length<1)return true;for(const entry of list)if(can(entry))return true;return false}function canAll(requiredPermissions){const list=asPermissionList(requiredPermissions);if(list.length<1)return true;for(const entry of list)if(!can(entry))return false;return true}return Object.freeze({accessMode:normalizedAccessMode,accessRequired,permissions,permissionsUnavailableError,awaitingPlacementPermissions,can,canAny,canAll})}var ROUTE_PARAM_NAME_PATTERN=/^[A-Za-z][A-Za-z0-9_]*$/;function normalizeRouteParamName(value=``,{context=`http-web route param`}={}){const normalizedValue=String(value||``).trim();if(!normalizedValue)throw new TypeError(`${context} must be a non-empty route parameter name.`);if(!ROUTE_PARAM_NAME_PATTERN.test(normalizedValue))throw new TypeError(`${context} "${normalizedValue}" is invalid. Use letters, numbers, and underscores only.`);return normalizedValue}function toRouteParamValue(value){if(Array.isArray(value))return toRouteParamValue(value[0]);if(value==null)return``;return String(value).trim()}function resolveRouteSourceValue(source=null){if(typeof source===`function`)return source();return unref(source)}function resolveRouteParamsSource(source=null){return asPlainObject(resolveRouteSourceValue(source))}function normalizeRouteParamNameList(value=[]){return(Array.isArray(value)?value:[]).map(entry=>String(entry||``).trim()).filter(Boolean)}function resolveRouteParamNamesSource(source=[]){return normalizeRouteParamNameList(resolveRouteSourceValue(source))}function normalizeRoutePathname(value=``){const sanitizedPathname=String(value||``).trim().split(/[?#]/u,1)[0]||``;if(!sanitizedPathname)return`/`;return sanitizedPathname.startsWith(`/`)?sanitizedPathname:`/${sanitizedPathname}`}function resolveRoutePathnameSource(source=``){return normalizeRoutePathname(resolveRouteSourceValue(source))}function segmentMatchesParamValue(segment=``,paramValue=``){const normalizedSegment=String(segment||``).trim();const normalizedParamValue=toRouteParamValue(paramValue);if(!normalizedSegment||!normalizedParamValue)return false;if(normalizedSegment===encodeURIComponent(normalizedParamValue))return true;try{return decodeURIComponent(normalizedSegment)===normalizedParamValue}catch{return false}}function findRouteParamSegmentIndex(segments=[],paramValue=``,fromIndex=0){const source=Array.isArray(segments)?segments:[];const cursor=Number.isInteger(fromIndex)&&fromIndex>0?fromIndex:0;for(let index=cursor;index<source.length;index+=1)if(segmentMatchesParamValue(source[index],paramValue))return index;return-1}function normalizePathPrefix(segments=[],endIndex=-1){const source=Array.isArray(segments)?segments:[];if(!Number.isInteger(endIndex)||endIndex<0)return`/`;return`/${source.slice(0,endIndex+1).join(`/`)}`}function resolveAnchorEndIndex(segmentIndex=-1,totalSegments=0,anchorMode=`at`){const normalizedSegmentIndex=Number.isInteger(segmentIndex)?segmentIndex:-1;if(normalizedSegmentIndex<0)return-1;const normalizedTotalSegments=Number.isInteger(totalSegments)&&totalSegments>0?totalSegments:0;const normalizedMode=String(anchorMode||`at`).trim().toLowerCase();if(normalizedMode===`before`)return normalizedSegmentIndex-1;if(normalizedMode===`after`)return normalizedTotalSegments>0?Math.min(normalizedSegmentIndex+1,normalizedTotalSegments-1):normalizedSegmentIndex+1;return normalizedSegmentIndex}function resolveScopedRoutePathname({currentPathname=`/`,params={},orderedParamNames=[],anchorParamName=``,anchorParamValue=``,anchorMode=`at`}={}){const normalizedCurrentPathname=resolveRoutePathnameSource(currentPathname);const normalizedAnchorParamName=String(anchorParamName||``).trim();if(!normalizedAnchorParamName)return normalizedCurrentPathname;const sourceParams=asPlainObject(params);const segments=normalizedCurrentPathname.split(`/`).filter(Boolean);if(segments.length<1)return normalizedCurrentPathname;const paramNames=resolveRouteParamNamesSource(orderedParamNames);let cursor=0;for(const paramName of paramNames){const segmentIndex=findRouteParamSegmentIndex(segments,sourceParams[paramName],cursor);if(segmentIndex<0)continue;if(paramName===normalizedAnchorParamName)return normalizePathPrefix(segments,resolveAnchorEndIndex(segmentIndex,segments.length,anchorMode));cursor=segmentIndex+1}const fallbackAnchorValue=toRouteParamValue(anchorParamValue)||toRouteParamValue(sourceParams[normalizedAnchorParamName]);if(!fallbackAnchorValue)return normalizedCurrentPathname;const fallbackSegmentIndex=findRouteParamSegmentIndex(segments,fallbackAnchorValue,0);if(fallbackSegmentIndex<0)return normalizedCurrentPathname;return normalizePathPrefix(segments,resolveAnchorEndIndex(fallbackSegmentIndex,segments.length,anchorMode))}function resolveRouteTemplatePath(routeTemplate=``,params={}){const normalizedTemplate=String(routeTemplate||``).trim();if(!normalizedTemplate)return``;const source=asPlainObject(params);const missingParams=[];const resolvedPath=normalizedTemplate.replace(/:([A-Za-z][A-Za-z0-9_]*)/g,(_,key)=>{const value=toRouteParamValue(source[key]);if(!value){missingParams.push(key);return`:${key}`}return encodeURIComponent(value)});if(missingParams.length>0)return``;return resolvedPath}function resolveRouteTemplateLocation(routeTemplate=``,{params={},currentPathname=`/`}={}){const resolvedTemplatePath=resolveRouteTemplatePath(routeTemplate,params);if(!resolvedTemplatePath)return``;if(resolvedTemplatePath.startsWith(`/`))return resolvedTemplatePath;const normalizedCurrentPathname=resolveRoutePathnameSource(currentPathname);const basePathname=normalizedCurrentPathname.endsWith(`/`)?normalizedCurrentPathname:`${normalizedCurrentPathname}/`;const resolvedPathname=new URL(resolvedTemplatePath,`https://jskit.local${basePathname}`).pathname;if(resolvedPathname.length>1&&resolvedPathname.endsWith(`/`))return resolvedPathname.slice(0,-1);return resolvedPathname}function createRouteTemplateResolver({recordIdParam,routeParams=null,routeParamNames=null,routePath=``,routeRecordId=null,anchorMode=`at`,anchorOnTargetRecord=false,fillRecordId=true}={}){function resolveCurrentRecordId(currentRouteParams=resolveRouteParamsSource(routeParams)){const explicitRecordId=toRouteParamValue(resolveRouteSourceValue(routeRecordId));if(explicitRecordId)return explicitRecordId;return toRouteParamValue(currentRouteParams[recordIdParam])}function resolveTemplatePath(urlTemplate=``,extraParams={}){const normalizedTemplate=String(urlTemplate||``).trim();if(!normalizedTemplate)return``;const currentRouteParams=resolveRouteParamsSource(routeParams);const sourceParams={...currentRouteParams,...asPlainObject(extraParams)};const currentRecordId=resolveCurrentRecordId(currentRouteParams);const targetRecordId=toRouteParamValue(sourceParams[recordIdParam])||currentRecordId;if(fillRecordId)sourceParams[recordIdParam]=targetRecordId;return resolveRouteTemplateLocation(normalizedTemplate,{params:sourceParams,currentPathname:resolveScopedRoutePathname({currentPathname:routePath,params:currentRouteParams,orderedParamNames:routeParamNames,anchorParamName:recordIdParam,anchorParamValue:anchorOnTargetRecord?targetRecordId:currentRecordId,anchorMode})})}return Object.freeze({resolveRecordId:()=>resolveCurrentRecordId(),resolveTemplatePath})}function extractRouteParamNames(pathTemplate=``){const normalizedTemplate=String(pathTemplate||``).trim();if(!normalizedTemplate)return[];const names=[];const seen=new Set;const pattern=/:([A-Za-z][A-Za-z0-9_]*)/g;let match=null;while((match=pattern.exec(normalizedTemplate))!=null){const name=String(match[1]||``).trim();if(!name||seen.has(name))continue;seen.add(name);names.push(name)}return names}function resolveRouteParamNamesInOrder(route=null){const sourceRoute=route&&typeof route===`object`?route:{};const matched=Array.isArray(sourceRoute.matched)?sourceRoute.matched:[];const names=[];const seen=new Set;for(const entry of matched){const entryPath=String(entry?.path||``).trim();if(!entryPath)continue;for(const name of extractRouteParamNames(entryPath)){if(seen.has(name))continue;seen.add(name);names.push(name)}}if(names.length>0)return names;return Object.keys(asPlainObject(sourceRoute.params)).map(entry=>String(entry||``).trim()).filter(Boolean)}var{t}=useJskitText();function resolveScopedRouteParamNames(placementContext=null,surfaceId=``){const routeBase=resolveSurfaceDefinitionFromPlacementContext(placementContext,surfaceId)?.routeBase||`/`;return extractRouteParamNames(resolveScopedRouteBase(routeBase))}function useScopeRuntime({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,accessMode=`auto`,hasPermissionRequirements=false}={}){const normalizedOwnershipFilter=normalizeOwnershipFilter(ownershipFilter);const normalizedAccessMode=ensureAccessModeCompatibility({accessMode,hasPermissionRequirements,caller:`useScopeRuntime`});const accessRequired=resolveAccessModeEnabled(normalizedAccessMode,{hasPermissionRequirements});const routeContext=useSurfaceRouteContext();const paths=usePaths({routeContext});const resolvedSurfaceId=computed(()=>{const explicitSurfaceId=normalizeSurfaceId(surfaceId);if(explicitSurfaceId)return explicitSurfaceId;return normalizeSurfaceId(routeContext.currentSurfaceId.value)});const scopedRouteParamNames=computed(()=>resolveScopedRouteParamNames(routeContext.placementContext.value,resolvedSurfaceId.value));const routeScopeParams=computed(()=>{const source=paths.routeParams.value;const next={};for(const paramName of scopedRouteParamNames.value){const paramValue=toRouteParamValue(source[paramName]);if(paramValue)next[paramName]=paramValue}return Object.freeze(next)});const missingScopedRouteParamNames=computed(()=>scopedRouteParamNames.value.filter(paramName=>!routeScopeParams.value[paramName]));const requiresScopedRouteParams=computed(()=>scopedRouteParamNames.value.length>0);const hasRequiredRouteScope=computed(()=>missingScopedRouteParamNames.value.length<1);const scopeParamValue=computed(()=>{const[primaryScopeParamName=``]=scopedRouteParamNames.value;return primaryScopeParamName?routeScopeParams.value[primaryScopeParamName]||``:``});const routeScopeError=computed(()=>{if(!requiresScopedRouteParams.value||hasRequiredRouteScope.value)return``;const missingParams=missingScopedRouteParamNames.value.join(`, `);return t(`jskit.http.access.routeParamsRequired`,{params:missingParams,surface:resolvedSurfaceId.value||`<unknown>`})});const accessRuntime=useAccess({enabled:computed(()=>accessRequired&&hasRequiredRouteScope.value),access:normalizedAccessMode,hasPermissionRequirements});function resolveApiPath(apiSuffix=``,context={}){if(routeScopeError.value)return``;const suffix=resolveApiSuffix(apiSuffix,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter,...asPlainObject(context)});return paths.api(suffix,{surface:resolvedSurfaceId.value,params:routeScopeParams.value})}function requireRouteScope(caller=`useScopeRuntime`){if(routeScopeError.value)throw new Error(`${caller}: ${routeScopeError.value}`)}return Object.freeze({normalizedOwnershipFilter,requiresScopedRouteParams:requiresScopedRouteParams.value,resolvedSurfaceId,accessMode:normalizedAccessMode,accessRequired,routeContext,scopedRouteParamNames,routeScopeParams,scopeParamValue,hasRequiredRouteScope,routeScopeError,access:accessRuntime,resolveApiPath,requireRouteScope})}function normalizePermissionSets(permissionSets={}){const source=permissionSets&&typeof permissionSets===`object`&&!Array.isArray(permissionSets)?permissionSets:{};const normalized={};for(const[key,value]of Object.entries(source))normalized[key]=normalizePermissions(value);return normalized}function hasAnyPermissions(permissionSets={}){for(const list of Object.values(permissionSets))if(Array.isArray(list)&&list.length>0)return true;return false}function useOperationScope({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,access=`auto`,apiSuffix=``,model,readEnabled=true,queryKeyFactory=null,permissionSets={},realtime=null}={}){const normalizedPermissionSets=normalizePermissionSets(permissionSets);const scopeRuntime=useScopeRuntime({ownershipFilter,surfaceId,accessMode:access,hasPermissionRequirements:hasAnyPermissions(normalizedPermissionSets)});const normalizedOwnershipFilter=scopeRuntime.normalizedOwnershipFilter;const routeContext=scopeRuntime.routeContext;const scopeParamValue=scopeRuntime.scopeParamValue;const hasRequiredRouteScope=scopeRuntime.hasRequiredRouteScope;const accessRuntime=scopeRuntime.access;const apiPath=computed(()=>scopeRuntime.resolveApiPath(apiSuffix,{model}));const queryEnabled=computed(()=>resolveEnabled(readEnabled,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter,model}));const queryKey=computed(()=>resolveQueryKey(queryKeyFactory,{surfaceId:routeContext.currentSurfaceId.value,scopeParamValue:scopeParamValue.value,ownershipFilter:normalizedOwnershipFilter}));const realtimeBinding=useOperationRealtime({realtime,queryKey:typeof queryKeyFactory===`function`?queryKey:null,enabled:computed(()=>hasRequiredRouteScope.value&&Boolean(apiPath.value))});function queryCanRun(accessGate=true){return computed(()=>queryEnabled.value&&hasRequiredRouteScope.value&&Boolean(apiPath.value)&&Boolean(unref(accessGate)))}function permissionGate(key=``){const list=normalizedPermissionSets[String(key||``)]||[];return computed(()=>resolvePermissionAccess(accessRuntime,list))}function loadError(baseError=``){return computed(()=>{if(scopeRuntime.routeScopeError.value)return scopeRuntime.routeScopeError.value;const permissionsError=String(accessRuntime.permissionsUnavailableError.value||``).trim();if(permissionsError)return permissionsError;if(baseError===void 0||baseError===null||baseError===``)return``;return String(unref(baseError)||``).trim()})}function isLoading(baseLoading=false){return computed(()=>Boolean(unref(baseLoading))||accessRuntime.awaitingPlacementPermissions.value)}return Object.freeze({scopeRuntime,routeContext,normalizedOwnershipFilter,scopeParamValue,hasRequiredRouteScope,access:accessRuntime,apiPath,queryEnabled,queryKey,queryCanRun,realtime:realtimeBinding,permissionGate,loadError,isLoading})}function normalizeFieldErrorKeys(keys){return Array.isArray(keys)?keys.map(entry=>String(entry||``).trim()).filter(Boolean):[]}function useFieldErrorBag(keys=[]){const normalizedKeys=normalizeFieldErrorKeys(keys);const hasFixedKeys=normalizedKeys.length>0;const errors=reactive(Object.fromEntries(normalizedKeys.map(key=>[key,``])));function clear(){const keysToClear=hasFixedKeys?normalizedKeys:Object.keys(errors);for(const key of keysToClear)errors[key]=``}function apply(source={}){const fieldErrorMap=source&&typeof source===`object`?source:{};if(hasFixedKeys){for(const key of normalizedKeys)errors[key]=String(fieldErrorMap[key]||``);return}clear();for(const[field,message]of Object.entries(fieldErrorMap)){const key=String(field||``).trim();if(!key)continue;errors[key]=String(message||``)}}function set(field,message){const key=String(field||``).trim();if(!key)return;if(hasFixedKeys&&!(key in errors))return;errors[key]=String(message||``)}return Object.freeze({errors,clear,apply,set})}function normalizeMessage(value){return String(value||``).trim()}function setupOperationErrorReporting({enabled=true,source=`http-web.operation`,loadError=null,notFoundError=null,loadActionFactory=null,notFoundActionFactory=null,loadChannel=``,notFoundChannel=``,loadSeverity=`error`,notFoundSeverity=`warning`,dedupeWindowMs=2e3}={}){if(!enabled)return;const runtime=useShellWebErrorRuntime();const normalizedSource=normalizeMessage(source)||`http-web.operation`;function watchMessage(value,{kind=`load`,channel=``,intent=`resource-load`,severity=`error`,actionFactory=null}={}){let lastMessage=``;let lastPresentationId=``;watch(()=>normalizeMessage(value?.value),nextMessage=>{if(!nextMessage){lastMessage=``;if(lastPresentationId){runtime.dismiss(lastPresentationId);lastPresentationId=``}return}if(nextMessage===lastMessage)return;lastMessage=nextMessage;const action=typeof actionFactory===`function`?actionFactory({message:nextMessage,kind}):null;const reportResult=runtime.report({source:normalizedSource,message:nextMessage,intent,severity,channel,action,dedupeKey:`${normalizedSource}:${kind}:${nextMessage}`,dedupeWindowMs});const nextPresentationId=String(reportResult?.presentationId||``).trim();if(nextPresentationId){if(lastPresentationId&&lastPresentationId!==nextPresentationId)runtime.dismiss(lastPresentationId);lastPresentationId=nextPresentationId}},{immediate:true})}if(loadError)watchMessage(loadError,{kind:`load`,channel:loadChannel,intent:`resource-load`,severity:loadSeverity,actionFactory:loadActionFactory});if(notFoundError)watchMessage(notFoundError,{kind:`not-found`,channel:notFoundChannel,intent:`resource-load`,severity:notFoundSeverity,actionFactory:notFoundActionFactory})}function setupRouteChangeCleanup({enabled=true,route=null,feedback=null,fieldBag=null,onClear=null}={}){if(!enabled)return;watch(()=>route?.fullPath,()=>{feedback?.clear?.();fieldBag?.clear?.();onClear?.()})}var CRUD_API_ACCESS_AUTHENTICATED=`authenticated`;var CRUD_API_ACCESS_PUBLIC=`public`;var CRUD_API_ACCESS_VALUES=Object.freeze([CRUD_API_ACCESS_AUTHENTICATED,CRUD_API_ACCESS_PUBLIC]);var publicCrudClients=new WeakSet;function normalizeCrudApiAccess(value=``){const normalized=normalizeText(value).toLowerCase()||`authenticated`;if(CRUD_API_ACCESS_VALUES.includes(normalized))return normalized;throw new TypeError(`CRUD resource apiAccess must be one of: ${CRUD_API_ACCESS_VALUES.join(`, `)}. Received: ${String(value||``)||`(empty)`}`)}function resolveCrudHttpClient(resource=null,{client=null}={}){const activeClient=client||getHttpWebClient();if(!activeClient||typeof activeClient.request!==`function`)throw new TypeError(`resolveCrudHttpClient requires a client with request().`);if(normalizeCrudApiAccess(resource?.apiAccess)!==`public`)return activeClient;if(publicCrudClients.has(activeClient))return activeClient;const publicClient=Object.freeze({request(url,options={}){const requestOptions=options&&typeof options===`object`&&!Array.isArray(options)?options:{};return activeClient.request(url,{...requestOptions,csrf:false})}});publicCrudClients.add(publicClient);return publicClient}function useCommand({ownershipFilter=ROUTE_VISIBILITY_WORKSPACE,surfaceId=``,access=`auto`,apiSuffix=``,runPermissions=[],writeMethod=`POST`,client=null,resource:commandResource=null,transport=null,placementSource=`http-web.command`,fallbackRunError=`jskit.http.feedback.actionFailed`,fieldErrorKeys=[],clearOnRouteChange=true,model,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage=false,messages={},realtime=null}={}){const operationScope=useOperationScope({ownershipFilter,surfaceId,access,apiSuffix,model,readEnabled:false,permissionSets:{run:runPermissions},realtime});const routeContext=operationScope.routeContext;const canRun=operationScope.permissionGate(`run`);const endpointResource=useEndpointResource({path:operationScope.apiPath,enabled:false,client:resolveCrudHttpClient(commandResource,{client}),writeMethod,transport,fallbackSaveError:fallbackRunError});const feedback=useUiFeedback({source:`${placementSource}.feedback`});const fieldBag=useFieldErrorBag(fieldErrorKeys);const command=useCommandCore({model,resource:endpointResource,writeMethod,canRun,fieldBag,feedback,input,buildRawPayload,buildCommandPayload,buildCommandOptions,onRunSuccess,onRunError,suppressSuccessMessage:Boolean(suppressSuccessMessage),messages:{validation:`jskit.http.feedback.fixInvalidValues`,success:`jskit.http.feedback.completed`,error:String(fallbackRunError||`jskit.http.feedback.actionFailed`),...messages&&typeof messages===`object`?messages:{}}});setupRouteChangeCleanup({enabled:clearOnRouteChange,route:routeContext.route,feedback,fieldBag});const loadError=operationScope.loadError();const isLoading=operationScope.isLoading();setupOperationErrorReporting({source:`${placementSource}.load`,loadError});return proxyRefs({canRun,isLoading,loadError,isRunning:command.running,fieldErrors:command.fieldErrors,message:command.message,messageType:command.messageType,run:command.run,resource:endpointResource})}export{useOperationScope as a,resolveRouteParamNamesInOrder as c,validateOperationInput as d,useFieldErrorBag as i,toRouteParamValue as l,setupOperationErrorReporting as n,createRouteTemplateResolver as o,setupRouteChangeCleanup as r,normalizeRouteParamName as s,useCommand as t,useAccess as u};
|