fuli-context 0.8.1 → 0.8.2

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.
@@ -0,0 +1,2 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SharedJefaReportPage-CbFtrDCY.js","assets/i18n-BtOOoyJd.js","assets/GrowthLoading-Bu_kH-I8.js","assets/_plugin-vue_export-helper-BDNMzG2s.js","assets/GrowthLoading-B_Hh0CRS.css","assets/useApi-CROJJdhE-raNlHRDl.js","assets/shared-report-BFUJqqQe.js","assets/client-CEHkJJ-5.js","assets/ProjectScopePicker-DVHfXX1f.js","assets/ProjectScopePicker-BvaGTMFx.css","assets/shared-report-ezeb8dW4.css","assets/SharedJefaReportPage-DXbj_JhO.css","assets/OverviewPage-BreX_kb4.js","assets/console--CZxc3PW.js","assets/vue-router-JFYBLXB1.js","assets/paths-CDREouhi.js","assets/PersonalProfilePage-CX1a6_E3.js","assets/useModalDialog-CroGk2Cs.js","assets/SearchableSelect-BZtyYmZN.js","assets/KnowledgeInspector-Ct5hl2--.js","assets/model-CGpllrds.js","assets/conversation-launcher-settings-Co1RlTFH.js","assets/KnowledgeInspector--1NujtXW.css","assets/KnowledgeEditDialog-BTwXXRCD.js","assets/identity-CsowvtIm.js","assets/KnowledgeEditDialog-D9NuRHvp.css","assets/personal-profile-graph-BNTG4PSY.js","assets/PersonalProfilePage-L8T5xMEC.css","assets/WritingTastePage-B7lSzs2z.js","assets/WritingTastePage-Bzg6AvnB.css","assets/PersonalProjectsPage-Br1S8ETM.js","assets/KnowledgeWorkspace-DmHIc0jb.js","assets/KnowledgeWorkspace-sb8OJ97I.css","assets/KnowledgeOrganizerPage-DMC8Hh43.js","assets/KnowledgeOrganizerPage-h2iKvQpO.css","assets/AgentsDirectoryPage-CKZfrcuD.js","assets/AgentHand-CMZk5GjY.js","assets/AgentHand-D9sQu2vc.css","assets/profile-model-BQO4zNs9.js","assets/AgentName-DRZHAIB2.js","assets/AgentName-Cydd0UI4.css","assets/agent-profile.css_vue_type_style_index_0_src_true_lang-C22UdfU0.js","assets/task-evidence-BUu7yYIn.js","assets/agent-profile-CdKOh5xw.css","assets/EmployeeRecruitDialog-BLTpjCcK.js","assets/catalog-DU4Kfd-N.js","assets/EmployeeRecruitDialog-B59X3rOi.css","assets/AgentProfilePage-BPQEfMhB.js","assets/ProjectAgentsPage-CA04h1Uf.js","assets/ProjectAgentsPage-CZWWV4Kw.css","assets/EmployeeWorkbenchPage-HUd-gne2.js","assets/EmployeeWorkbenchPage-CQwZnTA0.css","assets/employee-dialog-Bh5ccIbK.css","assets/PublicProjectsPage-CtctKml1.js","assets/KnowledgePage-uXW1Eovz.js","assets/ReviewPage-DUqaK-do.js","assets/ConnectionsPage-COb56qnk.js","assets/ConnectionsPage-CBHAdZXT.css","assets/SettingsPage-CB4ymLr8.js","assets/SettingsPage-Brl-SL33.css","assets/AboutPage-fBq5VFoQ.js","assets/fuli-logo-Bu9WBuQe.js","assets/AboutPage-vYIBifKw.css","assets/NotFoundPage-C0yOR9T9.js"])))=>i.map(i=>d[i]);
2
+ import{$ as e,A as t,B as n,C as r,F as i,H as a,L as o,M as s,N as c,T as l,V as u,Z as d,_ as f,a as p,at as m,b as h,d as g,g as _,h as v,i as y,j as b,m as x,n as S,nt as C,p as w,r as T,rt as E,s as D,t as O,v as k,w as A,x as j,y as M,z as N}from"./i18n-BtOOoyJd.js";import{n as P,t as F}from"./console--CZxc3PW.js";import{t as I}from"./GrowthLoading-Bu_kH-I8.js";import{t as L}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{m as R}from"./useApi-CROJJdhE-raNlHRDl.js";import{i as z,n as B,r as V,t as H}from"./vue-router-JFYBLXB1.js";import{t as U}from"./fuli-logo-Bu9WBuQe.js";import{n as W}from"./client-CEHkJJ-5.js";import{a as G,s as K}from"./catalog-DU4Kfd-N.js";import{i as q,n as ee,r as te,t as J}from"./AgentHand-CMZk5GjY.js";import{n as ne}from"./profile-model-BQO4zNs9.js";import{t as re}from"./useModalDialog-CroGk2Cs.js";/* empty css */import{n as ie,t as ae}from"./paths-CDREouhi.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var Y={name:`fuli-context`,version:`0.8.2`,description:`Local-first collaboration relationship graph for AI agents.`,type:`module`,files:[`README.zh-CN.md`,`npm-shrinkwrap.json`,`src/`,`dist/web/`,`docs/external-knowledge-architecture.md`,`docs/public-personal-architecture.md`,`docs/project-agent-memory.md`,`docs/agent-conversations-and-collaboration.md`,`docs/employee-agents.md`,`docs/agent-interface-architecture.md`,`examples/external-knowledge/markdown-folder.mjs`,`graph-provider/Dockerfile`,`graph-provider/pyproject.toml`,`graph-provider/fuli_graph/*.py`,`graph-provider/fuli_graph/**/*.py`,`skills/`,`compose.graphiti.yml`],bin:{fl:`src/cli.js`,fuli:`src/cli.js`},keywords:[`ai-agent`,`mcp`,`context`,`knowledge-graph`,`local-first`,`codex`,`claude-code`],scripts:{mcp:`node src/mcp-server.js`,dev:`run-p dev:server dev:web`,"dev:server":`node src/server.js`,"dev:web":`vite`,build:`run-s typecheck:web build:web`,"build:web":`vite build`,"typecheck:web":`vue-tsc --noEmit -p tsconfig.app.json`,"test:node":`node --test`,"test:web":`vitest run --config vitest.config.ts`,"test:package":`node scripts/package-smoke.js`,"test:knowledge:live":`node acceptance/knowledge-live.js`,"test:external-knowledge:live":`node scripts/validate-external-knowledge-live.js`,start:`node src/server.js`,"graph:setup":`node src/graphiti/setup.js`,"graph:up":`docker compose -f compose.graphiti.yml up -d --build`,"graph:down":`docker compose -f compose.graphiti.yml down`,"test:structure":`node --test test/source-structure.test.js`,pretest:`npm run build:web`,test:`run-s typecheck:web test:node test:web`,prepack:`npm run build`,prepublishOnly:`npm test`},engines:{node:`>=24.12`},repository:{type:`git`,url:`git+https://github.com/JevonsCode/fuli.git`},homepage:`https://github.com/JevonsCode/fuli#readme`,bugs:{url:`https://github.com/JevonsCode/fuli/issues`},publishConfig:{access:`public`},license:`Apache-2.0`,dependencies:{"@hono/node-server":`2.0.12`,"@modelcontextprotocol/sdk":`^1.29.0`,zod:`^4.4.3`},devDependencies:{"@types/d3":`^7.4.3`,"@types/node":`^24.13.3`,"@vitejs/plugin-vue":`^6.0.8`,"@vue/test-utils":`^2.4.11`,"brace-expansion":`5.0.12`,d3:`^7.9.0`,jsdom:`^29.1.1`,linkedom:`^0.18.12`,"npm-run-all2":`^9.0.2`,pinia:`^4.0.2`,typescript:`~6.0.0`,vite:`^8.1.5`,vitest:`^4.1.10`,vue:`^3.5.40`,"vue-i18n":`^11.4.8`,"vue-router":`^5.2.0`,"vue-tsc":`^3.3.8`},overrides:{"@modelcontextprotocol/sdk":{"@hono/node-server":`2.0.12`},"brace-expansion":`$brace-expansion`,"fast-uri":`3.1.8`,qs:`6.16.0`}}.version,oe=[`aria-label`],se={class:`brand-mark-wrap`},ce=[`src`],le={class:`brand-copy`},ue={class:`brand-title-row`},de={class:`brand-name`},fe=[`aria-label`,`aria-expanded`],pe={class:`brand-version`},me={key:1,class:`brand-version`},he={class:`brand-title-row`},ge={class:`brand-name`},_e={class:`brand-version`},ve=[`aria-label`],ye=[`href`],be=L(l({__name:`BrandEasterEgg`,setup(e){let n=d(null),r=d(null),i=d(0),a=d(!1),o=d(!1),l=d(!1),u=d(null),g=f(()=>u.value?.status===`ready`&&u.value.updateAvailable&&!!u.value.latestVersion),_=f(()=>u.value?.latestVersion??``),v=f(()=>u.value?.packageUrl??`https://www.npmjs.com/package/fuli-context`),y=new AbortController,S=!1;function w(){i.value+=1,a.value=!0}function T(){a.value=!1}function D(){g.value&&(l.value=!l.value)}function O(e){S=!1,o.value=!1,l.value&&!n.value?.contains(e.target)&&(l.value=!1)}function A(e){e.key===`Tab`&&(S=!0),e.key===`Escape`&&l.value&&(e.preventDefault(),l.value=!1,t(()=>r.value?.focus()))}function M(){o.value=S}function N(){o.value=!1}return s(()=>{window.addEventListener(`pointerdown`,O,!0),window.addEventListener(`keydown`,A,!0),W(`/api/system/version`,{signal:y.signal}).then(e=>{u.value=e}).catch(()=>{})}),b(()=>{y.abort(),window.removeEventListener(`pointerdown`,O,!0),window.removeEventListener(`keydown`,A,!0)}),(e,t)=>(c(),j(`div`,{ref_key:`root`,ref:n,class:E([`brand-block`,{"is-sparkling":a.value,"is-keyboard-focused":o.value}])},[k(`button`,{class:`brand-effect-button`,type:`button`,"aria-label":C(p)(`console.brandEffect.aria`),onClick:w,onFocus:M,onBlur:N},[k(`span`,se,[k(`img`,{class:`brand-mark`,src:C(U),alt:``,"aria-hidden":`true`},null,8,ce),a.value?(c(),j(`span`,{key:`orbit-${i.value}`,class:`brand-orbit`,"aria-hidden":`true`})):h(``,!0)])],40,oe),k(`span`,le,[k(`span`,ue,[k(`span`,de,m(C(p)(`common.brand`)),1),g.value?(c(),j(`button`,{key:0,ref_key:`versionButton`,ref:r,class:`brand-version-button`,type:`button`,"aria-label":C(p)(`console.update.aria`,{version:_.value}),"aria-expanded":l.value,"aria-controls":`brand-update-details`,onClick:D},[k(`span`,pe,`v`+m(C(Y)),1),t[0]||=k(`span`,{class:`brand-update-dot`,"aria-hidden":`true`},null,-1)],8,fe)):(c(),j(`span`,me,`v`+m(C(Y)),1))]),t[1]||=k(`span`,{class:`brand-subtitle`},`Context Graph`,-1),a.value?(c(),j(`span`,{key:`copy-reflection-${i.value}`,class:`brand-copy-reflection`,"aria-hidden":`true`,onAnimationend:x(T,[`self`])},[k(`span`,he,[k(`span`,ge,m(C(p)(`common.brand`)),1),k(`span`,_e,`v`+m(C(Y)),1)])],32)):h(``,!0)]),l.value?(c(),j(`div`,{key:0,id:`brand-update-details`,class:`brand-update-popover`,role:`dialog`,"aria-label":C(p)(`console.update.title`,{version:_.value})},[k(`strong`,null,m(C(p)(`console.update.title`,{version:_.value})),1),k(`p`,null,m(C(p)(`console.update.copy`)),1),t[2]||=k(`code`,null,`fuli update --yes`,-1),k(`a`,{href:v.value,target:`_blank`,rel:`noopener noreferrer`},m(C(p)(`console.update.npmLink`)),9,ye)],8,ve)):h(``,!0)],2))}}),[[`__scopeId`,`data-v-3ccab825`]]),xe=[`aria-label`],Se=[`lang`,`aria-label`,`aria-pressed`,`onClick`],Ce=l({__name:`LocaleSwitcher`,setup(e){let t=f(()=>S()),n={"zh-CN":`中`,"en-US":`EN`};function r(e){e!==t.value&&y(e)}return(e,a)=>(c(),j(`div`,{class:`locale-switcher`,role:`group`,"aria-label":C(p)(`common.language.label`)},[(c(!0),j(v,null,i(C(O),e=>(c(),j(`button`,{key:e,type:`button`,lang:e,"aria-label":C(p)(e===`zh-CN`?`common.language.chinese`:`common.language.english`),"aria-pressed":t.value===e,onClick:t=>r(e)},m(n[e]),9,Se))),128))],8,xe))}}),X=e(null);function we(e){let t=e.onError((t,n)=>{let r=e.resolve(n).href;!r.startsWith(`/`)||r.startsWith(`//`)||(X.value={href:r,resourceFailure:/dynamically imported module|module script|loading chunk|preload css|importing a module/i.test(String(t))})}),n=e.afterEach((e,t,n)=>{n||(X.value=null)});return()=>{t(),n()}}var Te={key:0,class:`navigation-recovery`,role:`alert`},Ee=[`href`],De=L(l({__name:`NavigationRecovery`,setup(e){return(e,t)=>C(X)?(c(),j(`div`,Te,[k(`div`,null,[k(`strong`,null,m(C(p)(`routes.loadFailure.title`)),1),k(`p`,null,m(C(p)(C(X).resourceFailure?`routes.loadFailure.resources`:`routes.loadFailure.message`)),1)]),k(`a`,{href:C(X).href,class:`quiet-button`},m(C(p)(`routes.loadFailure.reload`)),9,Ee),k(`button`,{type:`button`,class:`navigation-recovery-dismiss`,onClick:t[0]||=e=>X.value=null},m(C(p)(`routes.loadFailure.dismiss`)),1)])):h(``,!0)}}),[[`__scopeId`,`data-v-83dee1c5`]]),Oe={class:`nav-section-label`},ke={class:`employee-nav-mark`,"aria-hidden":`true`},Ae=[`src`],je={class:`nav-copy`},Me=L(l({__name:`EmployeeNavigation`,props:{personalSpaceId:{}},setup(e){let t=e;N(()=>t.personalSpaceId,e=>{K(e===`current`?``:e)},{immediate:!0});let n=f(()=>G.value.filter(e=>e.agentId&&e.agentStatus===`active`&&(e.runtime||e.workbench?.kind===`native`)));return(t,a)=>n.value.length?(c(),j(v,{key:0},[k(`p`,Oe,m(C(p)(`employees.directory`)),1),(c(!0),j(v,null,i(n.value,t=>(c(),j(`div`,{key:t.id,class:`employee-nav-row`},[A(C(H),{to:C(ne)(e.personalSpaceId,t.agentId),class:`space-nav-button employee-nav`,"active-class":`is-active`},{default:u(()=>[k(`span`,ke,[C(q)(t.id)?(c(),j(`img`,{key:0,src:C(q)(t.id),alt:``},null,8,Ae)):(c(),j(v,{key:1},[r(m(t.name.slice(0,1)),1)],64))]),k(`span`,je,[k(`strong`,null,m(t.name),1),k(`small`,null,m(t.role),1)])]),_:2},1032,[`to`]),A(C(H),{class:`employee-workbench-link`,to:`/employees/${encodeURIComponent(t.id)}`,"aria-label":`${t.name} · ${C(p)(`agentProfiles.workbench`)}`,title:C(p)(`agentProfiles.workbench`)},{default:u(()=>[...a[0]||=[k(`svg`,{viewBox:`0 0 20 20`,width:`16`,height:`16`,"aria-hidden":`true`},[k(`path`,{d:`M3 4h14v12H3zM3 8h14M8 8v8`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.4`})],-1)]]),_:1},8,[`to`,`aria-label`,`title`]),A(J,{"agent-id":t.agentId},null,8,[`agent-id`])]))),128))],64)):h(``,!0)}}),[[`__scopeId`,`data-v-8788995d`]]),Ne=[`title`],Pe={class:`employee-dialog-shell`},Fe={id:`attention-title`},Ie=[`disabled`,`aria-label`],Le={class:`employee-dialog-body`},Re={class:`attention-toolbar`},ze=[`disabled`],Be={key:0,role:`alert`,class:`employee-dialog-error`},Ve={key:1,role:`alert`,class:`employee-dialog-error`},He={key:4},Ue={class:`attention-meta`},We={class:`attention-action`},Ge=[`href`],Ke=[`onSubmit`],qe=[`for`],Je=[`id`,`onUpdate:modelValue`,`disabled`],Ye=[`disabled`],Xe={key:1},Ze=[`disabled`],Qe=L(l({__name:`AgentAttentionCenter`,props:{personalSpaceId:{},projects:{}},setup(e){let t=e,n=te(),r=d({}),o=d(!1),l=d({}),u=d(``),y=d(``),S=f(()=>new Map(t.projects.map(e=>[e.project_id,e.profile.name]))),{dialogRef:w,initialFocusRef:T,onCancel:E,onKeydown:D}=re(()=>n.open,()=>{u.value||(n.open=!1)});N(()=>t.personalSpaceId,e=>{r.value={},o.value=!1,l.value={},n.setSpace(e===`current`?``:e)},{immediate:!0}),N(()=>n.open,async e=>{if(!e)return;y.value=``;let t=n.spaceId;o.value=!0;try{let e=await W(`/api/project-agents?${new URLSearchParams({personalSpaceId:t})}`);t===n.spaceId&&(r.value=Object.fromEntries(e.map(e=>[e.agentId,e.profile.displayName||e.profile.name])))}catch{}finally{t===n.spaceId&&(o.value=!1)}});let O;function P(){document.visibilityState===`visible`&&!n.loading&&!n.open&&n.refresh()}s(()=>{O=setInterval(P,3e4),document.addEventListener(`visibilitychange`,P)}),b(()=>{clearInterval(O),document.removeEventListener(`visibilitychange`,P),n.setSpace(``)});async function F(e){if(!(u.value||!l.value[e.requestId]?.trim())){u.value=e.requestId,y.value=``;try{await n.respond(e,l.value[e.requestId].trim()),delete l.value[e.requestId]}catch(e){y.value=e instanceof Error?e.message:String(e),await n.refresh()}finally{u.value=``}}}return(e,t)=>(c(),j(v,null,[k(`button`,{class:`space-nav-button attention-nav`,type:`button`,onClick:t[0]||=e=>C(n).show()},[k(`span`,null,m(C(p)(`attention.title`)),1),A(J,{passive:``}),C(n).error?(c(),j(`span`,{key:0,title:C(p)(`attention.loadError`)},`!`,8,Ne)):h(``,!0)]),(c(),M(_,{to:`body`},[C(n).open?(c(),j(`dialog`,{key:0,ref_key:`dialogRef`,ref:w,class:`employee-dialog attention-dialog`,"aria-labelledby":`attention-title`,onCancel:t[6]||=(...e)=>C(E)&&C(E)(...e),onKeydown:t[7]||=(...e)=>C(D)&&C(D)(...e)},[k(`div`,Pe,[k(`header`,null,[k(`h2`,Fe,m(C(n).agentId&&r.value[C(n).agentId]||C(p)(`attention.title`)),1),k(`button`,{ref_key:`initialFocusRef`,ref:T,type:`button`,disabled:!!u.value,"aria-label":C(p)(`attention.close`),onClick:t[1]||=e=>C(n).open=!1},`×`,8,Ie)]),k(`div`,Le,[k(`div`,Re,[C(n).agentId?(c(),j(`button`,{key:0,type:`button`,onClick:t[2]||=e=>C(n).show()},m(C(p)(`attention.all`)),1)):h(``,!0),k(`button`,{type:`button`,disabled:C(n).loading||!!u.value,onClick:t[3]||=e=>C(n).refresh()},m(C(p)(`attention.refresh`)),9,ze)]),C(n).error?(c(),j(`p`,Be,m(C(p)(`attention.loadError`))+` · `+m(C(n).error),1)):h(``,!0),y.value?(c(),j(`p`,Ve,m(y.value),1)):h(``,!0),o.value?(c(),M(I,{key:2,variant:`inline`,label:C(p)(`attention.loadingAgents`)},null,8,[`label`])):h(``,!0),C(n).loading?(c(),M(I,{key:3,variant:`compact`,label:C(p)(`attention.loading`)},null,8,[`label`])):!C(n).items.length&&!C(n).error?(c(),j(`p`,He,m(C(p)(`attention.empty`)),1)):h(``,!0),(c(!0),j(v,null,i(C(n).items,e=>(c(),j(`article`,{key:e.requestId,class:`attention-item`},[k(`p`,Ue,m(r.value[e.agentId]||e.agentId)+` · `+m(S.value.get(e.personalProjectId)||e.personalProjectId)+` · `+m(C(p)(`attention.kinds.${e.kind}`)),1),k(`h3`,null,m(e.title),1),k(`p`,null,m(e.detail),1),k(`p`,We,m(e.requestedAction),1),e.taskId?(c(),j(`a`,{key:0,href:C(ee)(e),onClick:t[4]||=e=>C(n).open=!1},m(C(p)(`attention.task`)),9,Ge)):h(``,!0),k(`form`,{onSubmit:x(t=>F(e),[`prevent`])},[k(`label`,{for:`attention-${e.requestId}`},m(C(p)(`attention.response`)),9,qe),a(k(`textarea`,{id:`attention-${e.requestId}`,"onUpdate:modelValue":t=>l.value[e.requestId]=t,rows:`2`,maxlength:`4096`,required:``,disabled:!!u.value},null,8,Je),[[g,l.value[e.requestId]]]),k(`button`,{type:`submit`,class:`primary`,disabled:!!u.value||!l.value[e.requestId]?.trim()},[u.value===e.requestId?(c(),M(I,{key:0,variant:`inline`,label:C(p)(`attention.sending`)},null,8,[`label`])):(c(),j(`span`,Xe,m(C(p)(`attention.send`)),1))],8,Ye)],40,Ke)]))),128)),C(n).items.length<C(n).filteredTotal?(c(),j(`button`,{key:5,type:`button`,disabled:C(n).loading,onClick:t[5]||=e=>C(n).more()},m(C(p)(`attention.more`)),9,Ze)):h(``,!0)])])],544)):h(``,!0)]))],64))}}),[[`__scopeId`,`data-v-521df451`]]),$e=[`routes.`,`common.`,`employees.`,`agentProfiles.`];function et(e,t=``){let n=typeof e==`string`&&e?e:t;return $e.some(e=>n.startsWith(e))?p(n):n}function tt(e){if(typeof document>`u`)return;let t=et(e,`routes.overview.title`);document.title=`${t} · ${p(`common.brand`)}`}var nt={class:`app-shell`},rt=[`onKeydown`],it=[`aria-label`],at={class:`nav-section-label`},ot={class:`nav-label`},st={class:`nav-section-label nav-space-label`},ct={class:`nav-copy`},lt={class:`nav-copy`},ut={class:`nav-copy`},dt={class:`nav-copy`},ft={class:`nav-section-label nav-public-label`},pt={class:`nav-copy`},mt={class:`nav-section-label nav-tool-label`},ht={class:`nav-label`},gt={class:`nav-label`},_t={class:`nav-label`},vt={class:`nav-section-label nav-about-label`},yt={class:`nav-label`},bt={class:`nav-label`},xt={class:`sidebar-foot`},St=[`aria-label`],Ct={class:`runtime-status`},wt={class:`runtime-status`},Tt=[`aria-label`],Et=[`inert`],Dt=[`aria-expanded`],Ot={key:0,class:`workbench-host-label`},kt={key:1,class:`topbar-heading`},At={key:2,class:`topbar-actions`},jt={key:0,class:`mode-chip`},Mt=[`disabled`],Nt=[`disabled`],Pt={key:1},Ft=[`aria-label`],It=L(l({__name:`ConsoleLayout`,setup(e){let i=F(),a=R(),l=d(!1),g=d(null),_=d(null),y=f(()=>i.activePersonalSpace?.id??`current`),S=f(()=>ie(y.value,`graph`)),T=f(()=>ae(`personal`,y.value,`directory`)),D=f(()=>et(a.meta.title,`routes.overview.title`)),O=f(()=>a.meta.dedicatedWorkspace===!0),P=f(()=>i.publicRuntimeStatus===`ready`),L=f(()=>i.publicRuntimeStatus===`ready`?p(`console.services.publicReady`):i.publicRuntimeStatus===`error`?p(`console.services.publicError`):p(`console.services.publicOffline`)),z=f(()=>{if(i.publicRuntimeStatus===`ready`){let e=i.state?.capabilities;return e?.browsePublicProjects&&e?.subscribeProject&&!e?.publishProject&&!e?.submitKnowledge&&!e?.reviewProposals?p(`console.services.publicBrowseSubscribe`):p(`console.services.publicAvailable`)}return i.publicRuntimeStatus===`error`?p(`console.services.localUnaffected`):p(`console.services.localOnly`)}),V=f(()=>i.state?.capabilities?.browsePublicProjects!==!1),U=f(()=>{let e=i.state?.capabilities;return e?.submitKnowledge!==!1||e?.reviewProposals===!0});s(()=>{i.runtimeStatus===`idle`&&i.refresh(),window.addEventListener(`resize`,W)}),b(()=>window.removeEventListener(`resize`,W));function W(){window.innerWidth>920&&(l.value=!1)}function G(e){if(!l.value||e.key!==`Tab`)return;let t=[...e.currentTarget.querySelectorAll(`button:not(:disabled), a[href], input:not(:disabled), [tabindex="0"]`)].filter(e=>e.getClientRects().length>0),n=t[0],r=t.at(-1);e.shiftKey&&document.activeElement===n?(e.preventDefault(),r?.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n?.focus())}n(()=>{tt(a.meta.title)}),N(()=>a.fullPath,()=>{l.value=!1});async function K(){l.value=!0,await t(),_.value?.focus({preventScroll:!0})}async function q(){l.value=!1,await t(),g.value?.focus({preventScroll:!0})}return(e,t)=>(c(),j(`div`,nt,[k(`aside`,{id:`console-primary-sidebar`,class:E([`sidebar`,{"is-mobile-open":l.value}]),onKeydown:[w(x(q,[`stop`]),[`esc`]),G]},[k(`button`,{ref_key:`mobileNavCloseRef`,ref:_,class:`mobile-nav-close quiet-button`,type:`button`,onClick:q},m(C(p)(`console.navigation.closeMenu`)),513),A(be),k(`nav`,{class:`primary-nav`,"aria-label":C(p)(`console.navigation.aria`)},[k(`p`,at,m(C(p)(`console.navigation.workspace`)),1),A(C(H),{to:`/`,"exact-active-class":`is-active`},{default:u(()=>[t[2]||=k(`span`,{class:`nav-icon nav-icon-overview`,"aria-hidden":`true`},null,-1),k(`span`,ot,m(C(p)(`console.navigation.overview`)),1)]),_:1}),k(`p`,st,m(C(p)(`console.navigation.personalSpace`)),1),A(C(H),{class:`space-nav-button personal-profile-button`,to:`/preferences`,"active-class":`is-active`},{default:u(()=>[t[3]||=k(`span`,{class:`nav-icon nav-icon-personal-profile`,"aria-hidden":`true`},null,-1),k(`span`,ct,[k(`strong`,null,m(C(p)(`console.navigation.preferences`)),1),k(`small`,null,m(C(p)(`console.navigation.preferencesMeta`)),1)])]),_:1}),A(C(H),{class:`space-nav-button knowledge-organizer-button`,to:`/organize`,"active-class":`is-active`},{default:u(()=>[t[4]||=k(`span`,{class:`nav-icon nav-icon-knowledge-organizer`,"aria-hidden":`true`},null,-1),k(`span`,lt,[k(`strong`,null,m(C(p)(`console.navigation.organizer`)),1),k(`small`,null,m(C(p)(`console.navigation.organizerMeta`)),1)])]),_:1}),A(C(H),{class:`space-nav-button personal-space-button`,to:S.value,"active-class":`is-active`},{default:u(()=>[t[5]||=k(`span`,{class:`nav-icon nav-icon-personal-project`,"aria-hidden":`true`},null,-1),k(`span`,ut,[k(`strong`,null,m(C(p)(`console.navigation.personalProjects`)),1),k(`small`,null,m(C(p)(`console.navigation.personalProjectsMeta`)),1)])]),_:1},8,[`to`]),A(C(H),{class:`space-nav-button project-agents-button`,to:`/project-agents`,"active-class":`is-active`},{default:u(()=>[t[6]||=k(`span`,{class:`nav-icon nav-icon-project-agent`,"aria-hidden":`true`},null,-1),k(`span`,dt,[k(`strong`,null,m(C(p)(`console.navigation.projectAgents`)),1),k(`small`,null,m(C(p)(`console.navigation.projectAgentsMeta`)),1)])]),_:1}),V.value?(c(),j(v,{key:0},[k(`p`,ft,m(C(p)(`console.navigation.publicSpace`)),1),A(C(H),{class:`space-nav-button public-space-button`,to:`/public-projects`,"active-class":`is-active`},{default:u(()=>[t[7]||=k(`span`,{class:`nav-icon nav-icon-public-project`,"aria-hidden":`true`},null,-1),k(`span`,pt,[k(`strong`,null,m(C(p)(`console.navigation.publicProjects`)),1),k(`small`,null,m(C(p)(`console.navigation.publicProjectsMeta`)),1)])]),_:1})],64)):h(``,!0),A(Me,{"personal-space-id":y.value},null,8,[`personal-space-id`]),A(Qe,{"personal-space-id":y.value,projects:C(i).state?.personalProjects??[]},null,8,[`personal-space-id`,`projects`]),k(`p`,mt,m(C(p)(`console.navigation.governance`)),1),A(C(H),{to:T.value,"active-class":`is-active`},{default:u(()=>[t[8]||=k(`span`,{class:`nav-icon nav-icon-knowledge-graph`,"aria-hidden":`true`},null,-1),k(`span`,ht,m(C(p)(`console.navigation.knowledge`)),1)]),_:1},8,[`to`]),U.value?(c(),M(C(H),{key:1,to:`/review`,"active-class":`is-active`},{default:u(()=>[t[9]||=k(`span`,{class:`nav-icon nav-icon-review`,"aria-hidden":`true`},null,-1),k(`span`,gt,m(C(p)(`console.navigation.review`)),1)]),_:1})):h(``,!0),A(C(H),{to:`/connections`,"active-class":`is-active`},{default:u(()=>[t[10]||=k(`span`,{class:`nav-icon nav-icon-connections`,"aria-hidden":`true`},null,-1),k(`span`,_t,m(C(p)(`console.navigation.connections`)),1)]),_:1}),k(`p`,vt,m(C(p)(`console.navigation.aboutSection`)),1),A(C(H),{to:`/settings`,"active-class":`is-active`},{default:u(()=>[t[11]||=k(`span`,{class:`nav-icon nav-icon-settings`,"aria-hidden":`true`},null,-1),k(`span`,yt,m(C(p)(`console.navigation.settings`)),1)]),_:1}),A(C(H),{to:`/about`,"active-class":`is-active`},{default:u(()=>[t[12]||=k(`span`,{class:`nav-icon nav-icon-about`,"aria-hidden":`true`},null,-1),k(`span`,bt,m(C(p)(`console.navigation.about`)),1)]),_:1})],8,it),k(`div`,xt,[k(`div`,{class:`service-runtime-list`,"aria-label":C(p)(`console.services.aria`)},[k(`div`,Ct,[k(`span`,{class:E([`status-dot`,C(i).runtimeStatus])},null,2),k(`div`,null,[k(`strong`,null,m(C(i).runtimeStatus===`ready`?C(p)(`console.services.localReady`):C(i).runtimeStatus===`error`?C(p)(`console.services.localError`):C(p)(`console.services.localConnecting`)),1),t[13]||=k(`small`,null,`Graphiti / Neo4j`,-1)])]),k(`div`,wt,[k(`span`,{class:E([`status-dot`,C(i).publicRuntimeStatus])},null,2),k(`div`,null,[k(`strong`,null,m(L.value),1),k(`small`,null,m(z.value),1)])])],8,St)])],42,rt),l.value?(c(),j(`button`,{key:0,class:`mobile-nav-backdrop`,type:`button`,tabindex:`-1`,"aria-label":C(p)(`console.navigation.closeMenu`),onClick:q},null,8,Tt)):h(``,!0),k(`main`,{class:`workspace`,inert:l.value||void 0},[k(`header`,{class:E([`topbar`,{"topbar--workbench":O.value}])},[k(`button`,{ref_key:`mobileNavToggleRef`,ref:g,class:`mobile-nav-toggle quiet-button`,type:`button`,"aria-controls":`console-primary-sidebar`,"aria-expanded":l.value,onClick:K},[t[14]||=k(`span`,{class:`mobile-nav-icon`,"aria-hidden":`true`},null,-1),r(` `+m(C(p)(`console.navigation.openMenu`)),1)],8,Dt),O.value?(c(),j(`span`,Ot,`FULI`)):(c(),j(`div`,kt,[k(`h2`,null,m(D.value),1)])),O.value?h(``,!0):(c(),j(`div`,At,[P.value?(c(),j(`span`,jt,m(C(p)(`console.publicReady`)),1)):h(``,!0),C(a).name===`settings`?(c(),j(`button`,{key:1,class:`settings-save-button`,disabled:C(i).settingsSaving,form:`settings-form`,type:`submit`},m(C(p)(`settings.save`)),9,Mt)):h(``,!0),A(Ce),k(`button`,{class:`quiet-button`,type:`button`,disabled:C(i).runtimeStatus===`loading`,onClick:t[0]||=(...e)=>C(i).refresh&&C(i).refresh(...e)},[C(i).runtimeStatus===`loading`?(c(),M(I,{key:0,variant:`inline`,label:C(p)(`common.status.loadingConsole`)},null,8,[`label`])):(c(),j(`span`,Pt,m(C(p)(`common.actions.refresh`)),1))],8,Nt)]))],2),A(De),C(i).feedback?(c(),j(`div`,{key:0,class:E([`feedback feedback-message`,{success:C(i).feedback.tone===`success`}]),role:`status`,"aria-live":`polite`},[k(`span`,null,m(C(i).feedback.message),1),k(`button`,{class:`feedback-dismiss`,type:`button`,"aria-label":C(p)(`common.actions.close`),onClick:t[1]||=(...e)=>C(i).clearFeedback&&C(i).clearFeedback(...e)},`×`,8,Ft)],2)):h(``,!0),A(C(B),null,{default:u(({Component:e})=>[(c(),M(o(e)))]),_:1})],8,Et)]))}}),[[`__scopeId`,`data-v-9fe7a62f`]]),Lt=l({__name:`App`,setup(e){let t=R();return(e,n)=>C(t).meta.publicReport?(c(),M(C(B),{key:0})):(c(),M(It,{key:1}))}}),Rt=`modulepreload`,zt=function(e){return`/`+e},Bt={},Z=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=zt(t,n),t=s(t),t in Bt)return;Bt[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:Rt,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function Vt(e){let t=e.match(/^#\/knowledge\/([^/?#]+)\/([^/?#]+)\/(entity|relationship)\/([^/?#]+)(?:\?([^#]*))?$/);if(!t)return null;let[,n,r,i,a,o]=t;return`/knowledge/${n}/${r}/directory/${i}/${a}${o?`?${o}`:``}`}var Q=V({history:z(`/`),routes:[{path:`/reports/jefa`,name:`shared-jefa-report`,component:()=>Z(()=>import(`./SharedJefaReportPage-CbFtrDCY.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11])),meta:{publicReport:!0,title:`employees.share.title`}},{path:`/`,name:`overview`,component:()=>Z(()=>import(`./OverviewPage-BreX_kb4.js`),__vite__mapDeps([12,1,13,7,14,5,15])),meta:{eyebrow:``,title:`routes.overview.title`}},{path:`/preferences`,name:`personal-profile`,component:()=>Z(()=>import(`./PersonalProfilePage-CX1a6_E3.js`),__vite__mapDeps([16,1,13,7,2,3,4,14,5,17,18,19,20,21,22,23,24,25,26,27])),meta:{eyebrow:`PERSONAL LENS`,title:`routes.preferences.title`,description:`routes.preferences.description`}},{path:`/preferences/writing`,name:`writing-taste`,component:()=>Z(()=>import(`./WritingTastePage-B7lSzs2z.js`),__vite__mapDeps([28,1,13,7,2,3,4,14,5,23,17,18,24,20,25,26,29])),meta:{eyebrow:``,title:`routes.writingTaste.title`}},{path:`/personal/:spaceId/projects/:projectId/:mode/:itemKind/:itemId`,name:`personal-project-item`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECT`,title:`routes.personalProjects.title`}},{path:`/personal/:spaceId/projects/:mode/:itemKind/:itemId`,name:`personal-projects-item`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECTS`,title:`routes.personalProjects.title`,description:`routes.personalProjects.description`}},{path:`/personal/:spaceId/projects/:mode`,name:`personal-projects`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECTS`,title:`routes.personalProjects.title`,description:`routes.personalProjects.description`}},{path:`/personal/:spaceId/projects/:projectId/:mode`,name:`personal-project`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECT`,title:`routes.personalProjects.title`}},{path:`/organize`,name:`knowledge-organizer`,component:()=>Z(()=>import(`./KnowledgeOrganizerPage-DMC8Hh43.js`),__vite__mapDeps([33,1,13,7,2,3,4,17,18,24,19,20,21,22,23,25,34])),meta:{eyebrow:`KNOWLEDGE CLASSIFICATION`,title:`routes.organizer.title`}},{path:`/project-agents`,name:`project-agents`,component:()=>Z(()=>import(`./AgentsDirectoryPage-CKZfrcuD.js`),__vite__mapDeps([35,1,13,7,2,3,4,5,14,36,37,38,39,40,41,42,43,8,9,44,45,17,15,18,46])),meta:{eyebrow:``,title:`routes.projectAgents.title`}},{path:`/agents/:spaceId/:agentId`,name:`agent-profile`,component:()=>Z(()=>import(`./AgentProfilePage-BPQEfMhB.js`),__vite__mapDeps([47,1,13,7,2,3,4,5,14,45,38,39,40,42,41,43])),meta:{eyebrow:``,title:`agentProfiles.profile`}},{path:`/project-agents/manage`,name:`agent-management`,component:()=>Z(()=>import(`./ProjectAgentsPage-CA04h1Uf.js`),__vite__mapDeps([48,1,13,7,2,3,4,5,14,45,36,37,17,42,8,9,18,44,15,46,49])),meta:{eyebrow:``,title:`agentProfiles.advanced`}},{path:`/employees/:templateId`,name:`employee-workbench`,component:()=>Z(()=>import(`./EmployeeWorkbenchPage-HUd-gne2.js`),__vite__mapDeps([50,1,13,7,2,3,4,5,14,45,36,37,38,17,39,40,8,9,44,15,18,46,6,10,51,52])),meta:{eyebrow:``,title:`routes.employeeWorkbench.title`,dedicatedWorkspace:!0}},{path:`/public-projects`,name:`public-projects`,component:()=>Z(()=>import(`./PublicProjectsPage-CtctKml1.js`),__vite__mapDeps([53,1,13,7,2,3,4,5,17,15,18,24])),meta:{eyebrow:`PUBLIC PROJECTS`,title:`routes.publicProjects.title`,description:`routes.publicProjects.description`}},{path:`/knowledge`,name:`knowledge-default`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:projectId/:mode/:itemKind/:itemId`,name:`project-knowledge-item`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:mode/:itemKind/:itemId`,name:`knowledge-item`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:projectId/:mode`,name:`project-knowledge`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:mode`,name:`knowledge`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/review`,name:`review`,component:()=>Z(()=>import(`./ReviewPage-DUqaK-do.js`),__vite__mapDeps([55,1,13,7,2,3,4,18,24,20])),meta:{eyebrow:`REVIEW WORKSPACE`,title:`routes.review.title`,description:`routes.review.description`}},{path:`/connections`,name:`connections`,component:()=>Z(()=>import(`./ConnectionsPage-COb56qnk.js`),__vite__mapDeps([56,1,13,7,2,3,4,18,24,57])),meta:{eyebrow:`SERVICE CONNECTIONS`,title:`routes.connections.title`,description:`routes.connections.description`}},{path:`/settings`,name:`settings`,component:()=>Z(()=>import(`./SettingsPage-CB4ymLr8.js`),__vite__mapDeps([58,1,13,7,2,3,4,18,21,59])),meta:{eyebrow:``,title:`routes.settings.title`}},{path:`/about`,name:`about`,component:()=>Z(()=>import(`./AboutPage-fBq5VFoQ.js`),__vite__mapDeps([60,1,3,61,62])),meta:{eyebrow:`FULI`,title:`routes.about.title`}},{path:`/:pathMatch(.*)*`,name:`not-found`,component:()=>Z(()=>import(`./NotFoundPage-C0yOR9T9.js`),__vite__mapDeps([63,1,14,5])),meta:{title:`common.errors.pageNotFound`}}],scrollBehavior:(e,t,n)=>n??(e.path!==t.path&&{top:0})});we(Q),Q.beforeEach(e=>e.path!==`/`||typeof window>`u`?!0:Vt(window.location.hash)??!0),Q.afterEach(e=>{tt(e.meta.title)});var $=D(Lt);$.use(P()),$.use(T),$.use(Q),await Q.isReady().catch(()=>void 0),$.mount(`#app`);
@@ -9,7 +9,7 @@
9
9
  />
10
10
  <link rel="icon" type="image/png" href="/assets/fuli-logo-ER1wQ8Kk.png" />
11
11
  <title>复利 · Context Graph</title>
12
- <script type="module" crossorigin src="/assets/index-MKmHNBtc.js"></script>
12
+ <script type="module" crossorigin src="/assets/index-7X3LGByg.js"></script>
13
13
  <link rel="modulepreload" crossorigin href="/assets/i18n-BtOOoyJd.js">
14
14
  <link rel="modulepreload" crossorigin href="/assets/client-CEHkJJ-5.js">
15
15
  <link rel="modulepreload" crossorigin href="/assets/console--CZxc3PW.js">
@@ -61,6 +61,23 @@ An Agent should:
61
61
 
62
62
  The bundled `operating-fuli` Skill teaches this sequence and is installed by `fuli setup` for supported Agents. Browser automation is permitted only as optional visual verification after a structured operation, never as a data-mutation fallback.
63
63
 
64
+ ## Bounded context and exact contracts
65
+
66
+ Task entry through either the hook or `get_collaboration_preferences` returns the same compact
67
+ context shape: full active preference instructions, bounded working-memory previews and explicit
68
+ instructions to read complete memory before writing. Duplicate evidence wrappers are omitted.
69
+ `view_project_agent_task` supports `includeEvents: false` to omit event history while retaining
70
+ the derived execution summary and observed worker evidence. Detailed reads remain the default.
71
+
72
+ Summary limits must not alter executable tool schemas. Employee discovery uses a separate exact
73
+ catalog projection with explicit size errors; ordinary summaries retain their configured item
74
+ and byte budgets without applying a second fixed 20-item limit during byte reduction.
75
+
76
+ Knowledge retrieval requires current scope evidence. An old unscoped episode cannot make a
77
+ currently project-assigned item globally accessible. Explicit project references, opted-in
78
+ inheritance and genuine personal-global knowledge keep their existing scope rules; records
79
+ without scope metadata fail closed.
80
+
64
81
  ## Human-only boundaries
65
82
 
66
83
  The following operations intentionally remain local-user-only:
@@ -81,7 +81,20 @@ The reserved identity is `employee.<template-id>`, recognized by the generic `fu
81
81
 
82
82
  The host serves `/api/employee-templates`, recruitment/workspace/tool endpoints below it, and `/employee-workspaces/<template-id>/<project-id>/…`. Existing Host/Origin, JSON-body and LAN authorization checks apply. All workbench requests require an active matching identity and authorized responsibility policy, including assets and Agent discovery. Selected mode additionally requires an active assignment; all mode includes future active projects but enforces explicit exclusions and ended assignments before reaching the runtime.
83
83
 
84
- The existing FULI MCP exposes `list_employee_templates`, `recruit_employee`, `list_employee_tools`, and `call_employee_tool`. Workbench operations resolve an exact registered `projectPath`; unresolved or mismatched projects fail closed. Clients need to rediscover tools after upgrading the FULI installation they launch. Editing a source checkout does not update an already installed server or active MCP session.
84
+ The existing FULI MCP exposes `list_employee_templates`, `recruit_employee`, `list_employee_tools`, and `call_employee_tool`. Workbench operations resolve an exact registered project from its path or an authorized explicit project ID; unresolved or mismatched projects fail closed. Clients need to rediscover tools after upgrading the FULI installation they launch. Editing a source checkout does not update an already installed server or active MCP session.
85
+
86
+ Employee tool discovery preserves complete JSON Schema contracts, including deeply nested
87
+ fields and enums. Use `includeSchemas: false` for a compact list, then `toolName` to read one
88
+ complete contract. The catalog has a 64 KiB response limit; an oversized catalog returns a
89
+ controlled error with this recovery sequence instead of a partially usable schema. Only tools
90
+ allowed by the installed employee manifest are returned.
91
+
92
+ Discovery and invocation accept either `projectPath` or an already resolved `personalProjectId`.
93
+ When directory resolution is unavailable, pass the known ID and omit the path. If both are
94
+ provided, the path must resolve to that same project. The selected project must exist, be
95
+ active and be assigned to the employee under the current management policy; an explicit ID
96
+ does not bypass these checks. This supports remote directories and arbitrary checkout names
97
+ without inventing a second project or guessing from its description.
85
98
 
86
99
  Recruitment accepts an exact `projectPath` (MCP), a legacy `personalProjectId`/`personalProjectIds` selection, or a `management` policy; legacy project selectors cannot be mixed with a policy. Policy shape: `{ mode, projectIds, excludedProjectIds, titleMode, titleStyle }`. `all` stores exclusions and no inclusion list; `selected` stores a fixed project list and no exclusions. Omission for a new identity uses the template default; explicit empty selection recruits without an assignment. Arrays are deduplicated and bounded to 500 entries, and validated before writes. Existing policy replacement requires `replaceAssignments: true` plus the last-read `expectedAssignmentsVersion`. A stale selection fails with `assignment_scope_conflict`; an identical retry is idempotent. Changes preserve customized preferences, role, and executor policies.
87
100
 
@@ -46,7 +46,8 @@ Provider 读取已授权的员工和项目记录。切换客户端不会复制
46
46
 
47
47
  ## 任务入口与首次接管
48
48
 
49
- 1. 根据当前目录精确解析项目。项目 ID 使用仓库或目录名称;工作区存在多个候选时不猜测。
49
+ 1. 根据当前目录解析项目:先匹配精确 ID,再允许唯一的大小写等价 ID。工作树以原仓库
50
+ 为准,不以任意工作树文件夹名覆盖原项目;多个候选或相近但不同的名字不猜测。
50
51
  2. 选择具有有效任职、允许当前客户端的员工,并恢复职责、项目简介、近期任务、工作记录和记忆。
51
52
  3. 开始持久化的任务上下文,返回 `taskContextToken` 和当前记忆 revision。
52
53
  4. 如果任务入口尚无员工,协调时传入当前 token。新招的小组长可以接管同一任务;
@@ -110,6 +111,10 @@ Codex 的最终 Stop 兜底同样保留未完成状态。
110
111
  - `src/agents/`:客户端适配,保留各宿主的事件协议差异。
111
112
 
112
113
  Provider 是持久化事实源;Node 负责接口编排;前端消费相同的读取边界。
114
+ 生产任务上下文只使用 `ProviderTaskContextRegistry`,进程内实现仅作为测试夹具。
115
+ 共享宿主任务的 worker 只汇报工作活动和结果,主协调者整合后统一提交任务检查点;
116
+ 分发上下文包含这一生命周期策略,不转交主任务 token。独立宿主任务仍拥有自己的
117
+ 检查点。共享 MCP 没有可信子进程身份时,这属于宿主协作协议,不能当作服务端强隔离。
113
118
  角色恢复、任务协调和实际 worker 执行分别记录,不以选择结果代替执行证据。
114
119
  MCP 上下文有长度上限。被截断时必须显式补读完整记忆后再合并,不能宣称已完整恢复。
115
120
 
@@ -496,21 +496,6 @@ def _item_scope_metadata(
496
496
  project_scopes: dict[str, dict],
497
497
  include_personal_global: bool,
498
498
  ) -> dict | None:
499
- if not any(
500
- field in record
501
- for field in (
502
- 'profile_aspect',
503
- 'preference_agent_id',
504
- 'assignment_project_id',
505
- 'episode_project_ids',
506
- 'episode_project_agent_ids',
507
- 'reference_project_ids',
508
- 'has_global_episode',
509
- )
510
- ):
511
- # Backward-compatible projection for older Provider clients that returned
512
- # only already-filtered item IDs.
513
- return _global_scope_metadata()
514
499
  profile_aspect = record.get('profile_aspect')
515
500
  if profile_aspect:
516
501
  preference_scope = record.get('preference_scope') or 'global'
@@ -592,7 +577,14 @@ def _item_scope_metadata(
592
577
  ),
593
578
  )
594
579
  return _project_scope_metadata(project_id, scope)
595
- if include_personal_global and record.get('has_global_episode'):
580
+ # A later project assignment, or an existing project origin, takes
581
+ # precedence over a historical unscoped episode. It is not global access.
582
+ if (
583
+ include_personal_global
584
+ and record.get('has_global_episode')
585
+ and not assignment_project_id
586
+ and not episode_project_ids
587
+ ):
596
588
  return _global_scope_metadata()
597
589
  return None
598
590
 
@@ -253,13 +253,17 @@ def register_project_agent_routes(
253
253
  str | None,
254
254
  Query(min_length=1, max_length=128),
255
255
  ] = None,
256
+ include_events: bool = True,
256
257
  ) -> ProjectAgentTaskRecord:
257
- return await store.get_project_agent_task(
258
+ task = await store.get_project_agent_task(
258
259
  actor,
259
260
  personal_space_id,
260
261
  task_id,
261
262
  personal_project_id=personal_project_id,
262
263
  )
264
+ # Derive execution evidence before omitting history from the response.
265
+ # Never mutate the durable record or erase worker state in compact reads.
266
+ return task if include_events else task.model_copy(update={'events': []})
263
267
 
264
268
  @application.post(
265
269
  '/v1/project-agent-tasks/{task_id}/events',
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "fuli-graph-provider"
3
- version = "0.8.1"
3
+ version = "0.8.2"
4
4
  description = "Graphiti-backed personal and shared project provider for Fuli."
5
5
  requires-python = ">=3.12"
6
6
  dependencies = [
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "fuli-context",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "fuli-context",
9
- "version": "0.8.1",
9
+ "version": "0.8.2",
10
10
  "license": "Apache-2.0",
11
11
  "dependencies": {
12
12
  "@hono/node-server": "2.0.12",
@@ -22,7 +22,7 @@
22
22
  "@types/node": "^24.13.3",
23
23
  "@vitejs/plugin-vue": "^6.0.8",
24
24
  "@vue/test-utils": "^2.4.11",
25
- "brace-expansion": "5.0.9",
25
+ "brace-expansion": "5.0.12",
26
26
  "d3": "^7.9.0",
27
27
  "jsdom": "^29.1.1",
28
28
  "linkedom": "^0.18.12",
@@ -1867,9 +1867,9 @@
1867
1867
  "license": "ISC"
1868
1868
  },
1869
1869
  "node_modules/brace-expansion": {
1870
- "version": "5.0.9",
1871
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz",
1872
- "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==",
1870
+ "version": "5.0.12",
1871
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz",
1872
+ "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==",
1873
1873
  "dev": true,
1874
1874
  "license": "MIT",
1875
1875
  "dependencies": {
@@ -2949,9 +2949,9 @@
2949
2949
  "license": "MIT"
2950
2950
  },
2951
2951
  "node_modules/fast-uri": {
2952
- "version": "3.1.7",
2953
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.7.tgz",
2954
- "integrity": "sha512-dOvZVzjdZdz7phd9v6jCbwxrBW3fK6n8Rc0CtdmM4bumzMnxywBYhuph6J819RRw/ku+rLbelwfMunktuzVVHg==",
2952
+ "version": "3.1.8",
2953
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz",
2954
+ "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==",
2955
2955
  "funding": [
2956
2956
  {
2957
2957
  "type": "github",
@@ -3285,9 +3285,9 @@
3285
3285
  }
3286
3286
  },
3287
3287
  "node_modules/ip-address": {
3288
- "version": "10.3.1",
3289
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.3.1.tgz",
3290
- "integrity": "sha512-1e9d3kb97NHJTIJDZW9rKqW2h6+dFa50Dy0fpPSMQp2ADje5gvKsXmdiK6dwY5t76TaTt5+P5N1Y/LoToIxP6g==",
3288
+ "version": "10.7.2",
3289
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.2.tgz",
3290
+ "integrity": "sha512-7H/2gFSIitxc0hG3nOI1glS8QLo/EHBFFLk8vEUjXY/xu0AdL8jZ9U1IzO2PUm0d2D/ofQcAifb0g6OBkt8U7w==",
3291
3291
  "license": "MIT",
3292
3292
  "engines": {
3293
3293
  "node": ">= 12"
@@ -5077,9 +5077,9 @@
5077
5077
  "license": "ISC"
5078
5078
  },
5079
5079
  "node_modules/undici": {
5080
- "version": "7.29.0",
5081
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz",
5082
- "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==",
5080
+ "version": "7.30.0",
5081
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz",
5082
+ "integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==",
5083
5083
  "dev": true,
5084
5084
  "license": "MIT",
5085
5085
  "engines": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fuli-context",
3
- "version": "0.8.1",
3
+ "version": "0.8.2",
4
4
  "description": "Local-first collaboration relationship graph for AI agents.",
5
5
  "type": "module",
6
6
  "files": [
@@ -83,7 +83,7 @@
83
83
  "@types/node": "^24.13.3",
84
84
  "@vitejs/plugin-vue": "^6.0.8",
85
85
  "@vue/test-utils": "^2.4.11",
86
- "brace-expansion": "5.0.9",
86
+ "brace-expansion": "5.0.12",
87
87
  "d3": "^7.9.0",
88
88
  "jsdom": "^29.1.1",
89
89
  "linkedom": "^0.18.12",
@@ -102,7 +102,7 @@
102
102
  "@hono/node-server": "2.0.12"
103
103
  },
104
104
  "brace-expansion": "$brace-expansion",
105
- "fast-uri": "3.1.7",
105
+ "fast-uri": "3.1.8",
106
106
  "qs": "6.16.0"
107
107
  }
108
108
  }
@@ -9,6 +9,13 @@ Accumulate reusable knowledge without interrupting the user's normal work. Keep
9
9
 
10
10
  ## Establish Task Context
11
11
 
12
+ For a coordinated worker sharing its parent's host task, use the isolated context and lifecycle
13
+ policy supplied by the coordinator. An inherited task token belongs to the parent: do not call
14
+ `begin_task_context`, `checkpoint_task_knowledge`, or write the parent's Agent memory. Return
15
+ your result, evidence and proposed work summary to the coordinator for integration. Worker
16
+ activity uses `record_project_agent_task_activity`. A separately created host task/session has
17
+ its own lifecycle and follows the normal entry and checkpoint rules below.
18
+
12
19
  At the start of every user task, first use the lifecycle context supplied by the host when one
13
20
  exists. A Claude Code `UserPromptSubmit` hook calls `begin_task_context`, which already loads
14
21
  collaboration preferences and resolves the exact local personal project from the current working
@@ -230,9 +237,11 @@ project history. Explicit user-selected Agents and locked policies remain higher
230
237
  Treat the returned durable Agent identity and a host worker as different things. A durable Agent
231
238
  keeps its project assignment, preferences, task history, and Agent-scoped graph memory while idle;
232
239
  the host creates an execution process only when needed. Start only entries in `worker_plan`, give
233
- each worker only its returned isolated `context`, role, and workstream boundary, and never expose
240
+ each worker only its returned isolated `context` (including `lifecycle`), role, and workstream boundary, and never expose
234
241
  another Agent's private context. Fuli is the control plane and does not itself prove that a native
235
242
  worker started.
243
+ Do not forward the parent's task token. The coordinator alone checkpoints the shared host task
244
+ after integrating worker results; a worker's completion is not that task's completion.
236
245
 
237
246
  The host adapter must keep an adaptive-runtime graph lease for the whole worker run, and an
238
247
  executor lease when Fuli manages that executor. Call `acquire_runtime_lease` before starting
@@ -243,6 +252,14 @@ including concrete worker identity. Call `record_project_agent_executor_actual`
243
252
  executor/model use. If the host cannot start a worker, report the task as blocked or failed and do
244
253
  not fabricate an execution-summary row. The Provider's `executionSummary` remains authoritative.
245
254
 
255
+ `workerStatus` requires `workerId` and the participating `agentId`. Structured actual executor,
256
+ provider and model form one report and must match authorized preflight evidence. When that
257
+ evidence is missing or inconsistent, omit all three; preserve the observed `workerRuntime`,
258
+ terminal status and mismatch in the summary. Do not guess a provider or rewrite preflight to
259
+ make history fit. Valid terminal activity automatically creates its routing outcome. Additional
260
+ user/test outcome evidence needs a matching recorded execution, the task's exact work kind and
261
+ model strategy, and real references; a CLI session ID alone does not establish that execution.
262
+
246
263
  Keep per-worker completion separate from the global task transition. While parallel work is still
247
264
  being integrated, report each worker's terminal result in `workerStatus` and keep the task status
248
265
  `running`; this preserves one terminal execution-summary row per actual worker. Only after every
@@ -388,7 +405,8 @@ If `capture_session_knowledge` or automatic project creation returns `capture_di
388
405
  user has disabled automatic capture. Do not retry, do not create a fallback record elsewhere,
389
406
  and do not describe the skipped batch as stored. Existing knowledge may still be queried.
390
407
 
391
- Before sending the final response, perform one checkpoint. For a hook-managed task, call
408
+ Before sending the final response for a task you own, perform one checkpoint. A coordinated
409
+ worker returns its result to the owner instead of checkpointing an inherited token. For a hook-managed task, call
392
410
  `checkpoint_task_knowledge` exactly once with either `capture_candidates` and the bounded durable
393
411
  batch, or `retain_nothing`. For a prompt-only Agent, either flush the durable batch directly or
394
412
  determine that the turn produced no reusable knowledge. Do not finish a reusable project decision
@@ -3,6 +3,7 @@ import { booleanSchema, objectSchema, stringSchema } from './schema.js';
3
3
  const id = { ...stringSchema(), minLength: 1, maxLength: 256 };
4
4
  const projectPath = { ...stringSchema(), minLength: 1, maxLength: 4096 };
5
5
  const target = { projectPath, templateId: id };
6
+ const workbenchTarget = { ...target, personalProjectId: id };
6
7
 
7
8
  export const EMPLOYEE_TOOL_DEFINITIONS = [
8
9
  {
@@ -29,15 +30,15 @@ export const EMPLOYEE_TOOL_DEFINITIONS = [
29
30
  },
30
31
  {
31
32
  name: 'list_employee_tools', title: 'READ · Employee workbench tools',
32
- description: 'Discover the exact input schemas and permissions for a recruited employee in the current project. Read these schemas before calling a tool; a workbench has to be installed first.',
33
- inputSchema: objectSchema(target, ['projectPath', 'templateId'])
33
+ description: 'Discover complete input schemas and permitted tools for a recruited employee. Supply projectPath, or a previously resolved personalProjectId without projectPath when directory resolution is unavailable. If both are supplied they must resolve to the same project. Existing project and employee authorization always apply. Use includeSchemas=false for a compact name list, then toolName to read one exact schema. Oversized contracts fail explicitly, never return partial schemas. Read the schema before calling; a workbench has to be installed first.',
34
+ inputSchema: objectSchema({ ...workbenchTarget, toolName: id, includeSchemas: booleanSchema() }, ['templateId'])
34
35
  },
35
36
  {
36
37
  name: 'call_employee_tool', title: 'WRITE · Call an employee workbench tool',
37
- description: 'Call a discovered employee tool inside the exact assigned project. May read or change data according to the tool schema. Preserve optimistic concurrency and idempotency keys. Does not grant cross-project access, execute an external model, or confirm task completion for the human.',
38
+ description: 'Call a discovered employee tool inside the exact assigned project. Supply projectPath or a previously resolved personalProjectId; omit projectPath if directory resolution is unavailable. If both are supplied they must resolve to the same project. May read or change data according to the tool schema. Preserve optimistic concurrency and idempotency keys. Does not grant cross-project access, execute an external model, or confirm task completion for the human.',
38
39
  inputSchema: objectSchema({
39
- ...target, tool: id,
40
+ ...workbenchTarget, tool: id,
40
41
  arguments: { type: 'object', additionalProperties: true }
41
- }, ['projectPath', 'templateId', 'tool', 'arguments'])
42
+ }, ['templateId', 'tool', 'arguments'])
42
43
  }
43
44
  ];
@@ -806,7 +806,7 @@ export const GRAPH_TOOL_DEFINITIONS = [
806
806
  {
807
807
  name: 'record_project_agent_task_activity',
808
808
  title: 'WRITE · Record task activity',
809
- description: 'Record one explicit task event, including real terminal activity, actual executor/model/client attribution, and an optional source-labelled cumulative token snapshot for the concrete worker. Never estimate missing usage. Terminal activity is the only source for per-Agent activity summaries.',
809
+ description: 'Record real task/worker activity and optional source-labelled cumulative token usage; never estimate. workerStatus requires workerId and agentId. Report actualExecutorId, actualModelProvider and actualModel together only with matching authorized preflight evidence. Otherwise omit all three, report observed workerRuntime and explain the mismatch in summary. A terminal activity with valid actual execution automatically records its routing outcome.',
810
810
  inputSchema: projectAgentTaskActivityInput
811
811
  },
812
812
  {
@@ -1016,7 +1016,7 @@ export const GRAPH_TOOL_DEFINITIONS = [
1016
1016
  {
1017
1017
  name: 'record_project_agent_task_outcome',
1018
1018
  title: 'WRITE · Record explicit routing outcome evidence',
1019
- description: 'Record only explicit acceptance/satisfaction evidence such as rework_requested, repeated_negative_feedback, explicit_praise, test/acceptance pass or fail, or an explicit rating. Natural-language text is never used to infer satisfaction.',
1019
+ description: 'Record explicit user/test outcome evidence against a matching recorded execution. Use the task workKind and effective modelStrategy plus real referenceIds; a CLI session ID alone is not a recorded run. Terminal routing outcomes are already derived from valid task activity; do not submit them again. Never infer satisfaction or fabricate execution evidence to clear a validation error.',
1020
1020
  inputSchema: projectAgentTaskOutcomeInput
1021
1021
  },
1022
1022
  {
@@ -39,7 +39,14 @@ export function createEmployeeService({ app, runtimeConfigPath, registry: config
39
39
  async function describeTools(input) {
40
40
  const context = await workspace(input);
41
41
  const runtime = await registry.runtime(context.templateId);
42
- return { ...context, tools: await runtime.describeTools() };
42
+ const { manifest } = registry.get(context.templateId);
43
+ let tools = (await runtime.describeTools()).filter(tool => manifest.permissions.includes(tool.permission));
44
+ if (input.toolName) {
45
+ tools = tools.filter(tool => tool.name === input.toolName);
46
+ if (!tools.length) throw new EmployeeError('Employee tool is not available or permitted', 403, 'tool_not_permitted');
47
+ }
48
+ if (input.includeSchemas === false) tools = tools.map(({ inputSchema, ...tool }) => tool);
49
+ return { ...context, tools };
43
50
  }
44
51
 
45
52
  async function callTool(input) {
@@ -69,7 +69,7 @@ export async function beginTaskContext(application, {
69
69
  profile_capture: 'Evaluate durable artifact taste (including writing voice, wording, structure and formatting), stable collaboration personality, and decision preferences separately. Do not default every preference to judgment_preference. Use tasteDomain: writing for writing evidence; retain exact session/turn/time provenance. Agent-inferred personality remains pending. Report actual missing evidence rather than promising automatic progress from use alone.',
70
70
  human_attention: 'When the selected Project Agent needs a human answer, decision, review or permission, use request_agent_attention with the exact current space/project/Agent IDs, a stable idempotency key and a specific requestedAction. Never raise a hand for ordinary running, queueing or automatic retries. Read list_agent_attention with status=resolved for replies; cancel obsolete requests with cancel_agent_attention. A response does not grant permission or accept task completion.',
71
71
  retrieval: 'Inspect task_knowledge_recall before asking for a stable project fact or method again. On a miss, use search_current_project_knowledge with focused action, artifact, target-system, or identifier queries; never use the full conversational request as the only query.',
72
- checkpoint: 'Before finishing, call checkpoint_task_knowledge with capture_candidates or retain_nothing. For an assigned employee include workLog with a concise result summary and truthful status (completed, incomplete, failed, no_change, or reported), even when there is no knowledge to capture. When durable role context changed, also include agentMemory with the loaded revision and bounded merged notes. Do not overwrite from truncated context or store raw transcripts.'
72
+ checkpoint: 'The task owner checkpoints once after integration. Coordinated workers return results and evidence to the coordinator; they must not begin or checkpoint an inherited parent context. Before finishing the owned task, call checkpoint_task_knowledge with capture_candidates or retain_nothing. For an assigned employee include workLog with a concise result summary and truthful status (completed, incomplete, failed, no_change, or reported), even when there is no knowledge to capture. When durable role context changed, also include agentMemory with the loaded revision and bounded merged notes. Do not overwrite from truncated context or store raw transcripts.'
73
73
  }
74
74
  };
75
75
  }
@@ -214,7 +214,14 @@ export async function coordinateProjectAgentTask(
214
214
  assignment_summary: participant.assignmentSummary ?? null,
215
215
  workstream_boundary: boundaries[index] ?? null,
216
216
  context_status: contexts[index]?.status ?? 'unavailable',
217
- context: contexts[index]
217
+ context: {
218
+ ...contexts[index],
219
+ lifecycle: {
220
+ task_checkpoint_owner: 'coordinator',
221
+ completion_tool: 'record_project_agent_task_activity',
222
+ instruction: 'Return the bounded result and evidence to the coordinator. Report only worker activity. Do not begin or checkpoint an inherited parent task context, or write its Agent memory. An independently created host task/session owns its own lifecycle.'
223
+ }
224
+ }
218
225
  }));
219
226
  const contextsReady = workerPlan.every(({ context_status: status }) => status === 'ready');
220
227
  const hostExecutionRequired = route.task.status === 'queued' &&
@@ -249,6 +256,8 @@ export async function coordinateProjectAgentTask(
249
256
  start_only_returned_workers: true,
250
257
  report_worker_start_and_terminal_events: true,
251
258
  report_actual_executor_only_after_real_use: true,
259
+ task_checkpoint_owner: 'coordinator',
260
+ forward_parent_task_context_token: false,
252
261
  release_runtime_lease_in_finally: true
253
262
  },
254
263
  worker_plan: workerPlan,
@@ -47,23 +47,22 @@ export function resolvePersonalProjectPath(projectPath, projects, {
47
47
  pathApi
48
48
  });
49
49
  if (repositoryRoot) {
50
- const repositoryId = pathApi.basename(repositoryRoot);
51
- if (projectIds.has(repositoryId)) {
52
- return matched(repositoryId, 'repository_root');
53
- }
54
50
  const worktreeId = worktreeOriginProjectId(
55
51
  pathApi.join(repositoryRoot, '.git'),
56
52
  { readText, pathApi }
57
53
  );
58
- if (worktreeId && projectIds.has(worktreeId)) {
59
- return matched(worktreeId, 'git_worktree_origin');
54
+ if (worktreeId) {
55
+ // A worktree's folder name is arbitrary; only its original repository
56
+ // identifies the project, even when the folder names another project.
57
+ return resolveProjectId(worktreeId, projectIds, 'git_worktree_origin')
58
+ ?? unresolved('unmatched');
60
59
  }
60
+ const repository = resolveProjectId(pathApi.basename(repositoryRoot), projectIds, 'repository_root');
61
+ if (repository) return repository;
61
62
  }
62
63
 
63
- const directoryId = pathApi.basename(currentPath);
64
- if (projectIds.has(directoryId)) {
65
- return matched(directoryId, 'directory_name');
66
- }
64
+ const directory = resolveProjectId(pathApi.basename(currentPath), projectIds, 'directory_name');
65
+ if (directory) return directory;
67
66
 
68
67
  const childMatches = [...projectIds].filter((projectId) => (
69
68
  CHILD_PROJECT_MARKERS.some((marker) =>
@@ -79,6 +78,14 @@ export function resolvePersonalProjectPath(projectPath, projects, {
79
78
  return unresolved('unmatched');
80
79
  }
81
80
 
81
+ function resolveProjectId(candidate, projectIds, basis) {
82
+ if (projectIds.has(candidate)) return matched(candidate, basis);
83
+ const matches = [...projectIds].filter((id) => id.toLowerCase() === candidate.toLowerCase());
84
+ if (matches.length === 1) return matched(matches[0], `${basis}_case_insensitive`);
85
+ if (matches.length > 1) return unresolved('ambiguous', { candidateCount: matches.length });
86
+ return null;
87
+ }
88
+
82
89
  export function findRepositoryRoot(projectPath, {
83
90
  fileExists = existsSync,
84
91
  pathApi = path
@@ -1,4 +1,5 @@
1
1
  import { compactTaskContext } from '../conversations/task-context-view.js';
2
+ import { employeeToolCatalogResult } from './employee-tool-catalog.js';
2
3
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
3
4
  import {
4
5
  CallToolRequestSchema,
@@ -225,6 +226,9 @@ async function invokeTool(tool, input, requestContext = null) {
225
226
  const value = await tool.invoke(input, requestContext);
226
227
  auditLifecycleTool(tool.definition.name);
227
228
  const limitBytes = TOOL_RESULT_LIMIT_BYTES[tool.definition.name];
229
+ if (tool.definition.name === 'list_employee_tools') {
230
+ return employeeToolCatalogResult(value, { limitBytes });
231
+ }
228
232
  if (tool.definition.name === 'begin_task_context') {
229
233
  return hookAdditionalContextToolResult(compactTaskContext(value), {
230
234
  hookEventName: 'UserPromptSubmit',
@@ -236,7 +240,8 @@ async function invokeTool(tool, input, requestContext = null) {
236
240
  const itemLimit = ({ list_agent_interfaces: 200, list_project_agent_tasks: 200,
237
241
  list_preference_conflicts: 1000, list_external_knowledge_bindings: 200,
238
242
  get_collaboration_preferences: 1000 })[tool.definition.name];
239
- return successToolResult(value, { limitBytes, itemLimit });
243
+ return successToolResult(tool.definition.name === 'get_collaboration_preferences'
244
+ ? compactTaskContext(value) : value, { limitBytes, itemLimit });
240
245
  } catch (error) {
241
246
  return errorToolResult(error);
242
247
  }
@@ -0,0 +1,22 @@
1
+ import { ApplicationError } from '../app/application-error.js';
2
+
3
+ // Schemas are executable contracts. Summary truncation can change their types,
4
+ // required fields or enum values, so return a complete bounded catalog or fail.
5
+ export function employeeToolCatalogResult(value, { limitBytes = 64 * 1024 } = {}) {
6
+ const catalog = pick(value, ['personalSpaceId', 'agentId', 'templateId', 'name',
7
+ 'role', 'runtimeStatus', 'basePath', 'workbenchUrl', 'agentCardUrl']);
8
+ if (value.project) catalog.project = pick(value.project, ['id', 'name', 'description']);
9
+ catalog.tools = (value.tools ?? []).map(tool => pick(tool,
10
+ ['name', 'title', 'description', 'permission', 'inputSchema']));
11
+ const json = JSON.stringify(catalog);
12
+ if (Buffer.byteLength(json, 'utf8') > limitBytes) {
13
+ throw new ApplicationError('tool_catalog_too_large',
14
+ 'Employee tool catalog is too large. Use includeSchemas=false to list names, then toolName to read one complete schema.');
15
+ }
16
+ return { content: [{ type: 'text', text: json }], structuredContent: JSON.parse(json) };
17
+ }
18
+
19
+ function pick(value, keys) {
20
+ return Object.fromEntries(keys.filter(key => value[key] !== undefined)
21
+ .map(key => [key, value[key]]));
22
+ }
@@ -178,7 +178,9 @@ function projectString(value, budget) {
178
178
  function projectArray(value, budget, depth) {
179
179
  const projected = [];
180
180
  let used = 2;
181
- for (const item of value.slice(0, RESULT_ITEM_LIMIT)) {
181
+ // sanitize already applied the caller's item limit. A second default limit
182
+ // here silently drops catalog entries and preferences when bytes are capped.
183
+ for (const item of value) {
182
184
  const separatorBytes = projected.length ? 1 : 0;
183
185
  const child = projectValue(item, budget - used - separatorBytes, depth + 1);
184
186
  if (child === undefined) continue;
@@ -1,2 +0,0 @@
1
- const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/SharedJefaReportPage-CbFtrDCY.js","assets/i18n-BtOOoyJd.js","assets/GrowthLoading-Bu_kH-I8.js","assets/_plugin-vue_export-helper-BDNMzG2s.js","assets/GrowthLoading-B_Hh0CRS.css","assets/useApi-CROJJdhE-raNlHRDl.js","assets/shared-report-BFUJqqQe.js","assets/client-CEHkJJ-5.js","assets/ProjectScopePicker-DVHfXX1f.js","assets/ProjectScopePicker-BvaGTMFx.css","assets/shared-report-ezeb8dW4.css","assets/SharedJefaReportPage-DXbj_JhO.css","assets/OverviewPage-BreX_kb4.js","assets/console--CZxc3PW.js","assets/vue-router-JFYBLXB1.js","assets/paths-CDREouhi.js","assets/PersonalProfilePage-CX1a6_E3.js","assets/useModalDialog-CroGk2Cs.js","assets/SearchableSelect-BZtyYmZN.js","assets/KnowledgeInspector-Ct5hl2--.js","assets/model-CGpllrds.js","assets/conversation-launcher-settings-Co1RlTFH.js","assets/KnowledgeInspector--1NujtXW.css","assets/KnowledgeEditDialog-BTwXXRCD.js","assets/identity-CsowvtIm.js","assets/KnowledgeEditDialog-D9NuRHvp.css","assets/personal-profile-graph-BNTG4PSY.js","assets/PersonalProfilePage-L8T5xMEC.css","assets/WritingTastePage-B7lSzs2z.js","assets/WritingTastePage-Bzg6AvnB.css","assets/PersonalProjectsPage-Br1S8ETM.js","assets/KnowledgeWorkspace-DmHIc0jb.js","assets/KnowledgeWorkspace-sb8OJ97I.css","assets/KnowledgeOrganizerPage-DMC8Hh43.js","assets/KnowledgeOrganizerPage-h2iKvQpO.css","assets/AgentsDirectoryPage-CKZfrcuD.js","assets/AgentHand-CMZk5GjY.js","assets/AgentHand-D9sQu2vc.css","assets/profile-model-BQO4zNs9.js","assets/AgentName-DRZHAIB2.js","assets/AgentName-Cydd0UI4.css","assets/agent-profile.css_vue_type_style_index_0_src_true_lang-C22UdfU0.js","assets/task-evidence-BUu7yYIn.js","assets/agent-profile-CdKOh5xw.css","assets/EmployeeRecruitDialog-BLTpjCcK.js","assets/catalog-DU4Kfd-N.js","assets/EmployeeRecruitDialog-B59X3rOi.css","assets/AgentProfilePage-BPQEfMhB.js","assets/ProjectAgentsPage-CA04h1Uf.js","assets/ProjectAgentsPage-CZWWV4Kw.css","assets/EmployeeWorkbenchPage-HUd-gne2.js","assets/EmployeeWorkbenchPage-CQwZnTA0.css","assets/employee-dialog-Bh5ccIbK.css","assets/PublicProjectsPage-CtctKml1.js","assets/KnowledgePage-uXW1Eovz.js","assets/ReviewPage-DUqaK-do.js","assets/ConnectionsPage-COb56qnk.js","assets/ConnectionsPage-CBHAdZXT.css","assets/SettingsPage-CB4ymLr8.js","assets/SettingsPage-Brl-SL33.css","assets/AboutPage-fBq5VFoQ.js","assets/fuli-logo-Bu9WBuQe.js","assets/AboutPage-vYIBifKw.css","assets/NotFoundPage-C0yOR9T9.js"])))=>i.map(i=>d[i]);
2
- import{$ as e,A as t,B as n,C as r,F as i,H as a,L as o,M as s,N as c,T as l,V as u,Z as d,_ as f,a as p,at as m,b as h,d as g,g as _,h as v,i as y,j as b,m as x,n as S,nt as C,p as w,r as T,rt as E,s as D,t as O,v as k,w as A,x as j,y as M,z as N}from"./i18n-BtOOoyJd.js";import{n as P,t as F}from"./console--CZxc3PW.js";import{t as I}from"./GrowthLoading-Bu_kH-I8.js";import{t as L}from"./_plugin-vue_export-helper-BDNMzG2s.js";import{m as R}from"./useApi-CROJJdhE-raNlHRDl.js";import{i as z,n as B,r as V,t as H}from"./vue-router-JFYBLXB1.js";import{t as U}from"./fuli-logo-Bu9WBuQe.js";import{n as W}from"./client-CEHkJJ-5.js";import{a as G,s as K}from"./catalog-DU4Kfd-N.js";import{i as q,n as ee,r as te,t as J}from"./AgentHand-CMZk5GjY.js";import{n as ne}from"./profile-model-BQO4zNs9.js";import{t as re}from"./useModalDialog-CroGk2Cs.js";/* empty css */import{n as ie,t as ae}from"./paths-CDREouhi.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),e.crossOrigin===`use-credentials`?t.credentials=`include`:e.crossOrigin===`anonymous`?t.credentials=`omit`:t.credentials=`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var Y={name:`fuli-context`,version:`0.8.1`,description:`Local-first collaboration relationship graph for AI agents.`,type:`module`,files:[`README.zh-CN.md`,`npm-shrinkwrap.json`,`src/`,`dist/web/`,`docs/external-knowledge-architecture.md`,`docs/public-personal-architecture.md`,`docs/project-agent-memory.md`,`docs/agent-conversations-and-collaboration.md`,`docs/employee-agents.md`,`docs/agent-interface-architecture.md`,`examples/external-knowledge/markdown-folder.mjs`,`graph-provider/Dockerfile`,`graph-provider/pyproject.toml`,`graph-provider/fuli_graph/*.py`,`graph-provider/fuli_graph/**/*.py`,`skills/`,`compose.graphiti.yml`],bin:{fl:`src/cli.js`,fuli:`src/cli.js`},keywords:[`ai-agent`,`mcp`,`context`,`knowledge-graph`,`local-first`,`codex`,`claude-code`],scripts:{mcp:`node src/mcp-server.js`,dev:`run-p dev:server dev:web`,"dev:server":`node src/server.js`,"dev:web":`vite`,build:`run-s typecheck:web build:web`,"build:web":`vite build`,"typecheck:web":`vue-tsc --noEmit -p tsconfig.app.json`,"test:node":`node --test`,"test:web":`vitest run --config vitest.config.ts`,"test:package":`node scripts/package-smoke.js`,"test:knowledge:live":`node acceptance/knowledge-live.js`,"test:external-knowledge:live":`node scripts/validate-external-knowledge-live.js`,start:`node src/server.js`,"graph:setup":`node src/graphiti/setup.js`,"graph:up":`docker compose -f compose.graphiti.yml up -d --build`,"graph:down":`docker compose -f compose.graphiti.yml down`,"test:structure":`node --test test/source-structure.test.js`,pretest:`npm run build:web`,test:`run-s typecheck:web test:node test:web`,prepack:`npm run build`,prepublishOnly:`npm test`},engines:{node:`>=24.12`},repository:{type:`git`,url:`git+https://github.com/JevonsCode/fuli.git`},homepage:`https://github.com/JevonsCode/fuli#readme`,bugs:{url:`https://github.com/JevonsCode/fuli/issues`},publishConfig:{access:`public`},license:`Apache-2.0`,dependencies:{"@hono/node-server":`2.0.12`,"@modelcontextprotocol/sdk":`^1.29.0`,zod:`^4.4.3`},devDependencies:{"@types/d3":`^7.4.3`,"@types/node":`^24.13.3`,"@vitejs/plugin-vue":`^6.0.8`,"@vue/test-utils":`^2.4.11`,"brace-expansion":`5.0.9`,d3:`^7.9.0`,jsdom:`^29.1.1`,linkedom:`^0.18.12`,"npm-run-all2":`^9.0.2`,pinia:`^4.0.2`,typescript:`~6.0.0`,vite:`^8.1.5`,vitest:`^4.1.10`,vue:`^3.5.40`,"vue-i18n":`^11.4.8`,"vue-router":`^5.2.0`,"vue-tsc":`^3.3.8`},overrides:{"@modelcontextprotocol/sdk":{"@hono/node-server":`2.0.12`},"brace-expansion":`$brace-expansion`,"fast-uri":`3.1.7`,qs:`6.16.0`}}.version,oe=[`aria-label`],se={class:`brand-mark-wrap`},ce=[`src`],le={class:`brand-copy`},ue={class:`brand-title-row`},de={class:`brand-name`},fe=[`aria-label`,`aria-expanded`],pe={class:`brand-version`},me={key:1,class:`brand-version`},he={class:`brand-title-row`},ge={class:`brand-name`},_e={class:`brand-version`},ve=[`aria-label`],ye=[`href`],be=L(l({__name:`BrandEasterEgg`,setup(e){let n=d(null),r=d(null),i=d(0),a=d(!1),o=d(!1),l=d(!1),u=d(null),g=f(()=>u.value?.status===`ready`&&u.value.updateAvailable&&!!u.value.latestVersion),_=f(()=>u.value?.latestVersion??``),v=f(()=>u.value?.packageUrl??`https://www.npmjs.com/package/fuli-context`),y=new AbortController,S=!1;function w(){i.value+=1,a.value=!0}function T(){a.value=!1}function D(){g.value&&(l.value=!l.value)}function O(e){S=!1,o.value=!1,l.value&&!n.value?.contains(e.target)&&(l.value=!1)}function A(e){e.key===`Tab`&&(S=!0),e.key===`Escape`&&l.value&&(e.preventDefault(),l.value=!1,t(()=>r.value?.focus()))}function M(){o.value=S}function N(){o.value=!1}return s(()=>{window.addEventListener(`pointerdown`,O,!0),window.addEventListener(`keydown`,A,!0),W(`/api/system/version`,{signal:y.signal}).then(e=>{u.value=e}).catch(()=>{})}),b(()=>{y.abort(),window.removeEventListener(`pointerdown`,O,!0),window.removeEventListener(`keydown`,A,!0)}),(e,t)=>(c(),j(`div`,{ref_key:`root`,ref:n,class:E([`brand-block`,{"is-sparkling":a.value,"is-keyboard-focused":o.value}])},[k(`button`,{class:`brand-effect-button`,type:`button`,"aria-label":C(p)(`console.brandEffect.aria`),onClick:w,onFocus:M,onBlur:N},[k(`span`,se,[k(`img`,{class:`brand-mark`,src:C(U),alt:``,"aria-hidden":`true`},null,8,ce),a.value?(c(),j(`span`,{key:`orbit-${i.value}`,class:`brand-orbit`,"aria-hidden":`true`})):h(``,!0)])],40,oe),k(`span`,le,[k(`span`,ue,[k(`span`,de,m(C(p)(`common.brand`)),1),g.value?(c(),j(`button`,{key:0,ref_key:`versionButton`,ref:r,class:`brand-version-button`,type:`button`,"aria-label":C(p)(`console.update.aria`,{version:_.value}),"aria-expanded":l.value,"aria-controls":`brand-update-details`,onClick:D},[k(`span`,pe,`v`+m(C(Y)),1),t[0]||=k(`span`,{class:`brand-update-dot`,"aria-hidden":`true`},null,-1)],8,fe)):(c(),j(`span`,me,`v`+m(C(Y)),1))]),t[1]||=k(`span`,{class:`brand-subtitle`},`Context Graph`,-1),a.value?(c(),j(`span`,{key:`copy-reflection-${i.value}`,class:`brand-copy-reflection`,"aria-hidden":`true`,onAnimationend:x(T,[`self`])},[k(`span`,he,[k(`span`,ge,m(C(p)(`common.brand`)),1),k(`span`,_e,`v`+m(C(Y)),1)])],32)):h(``,!0)]),l.value?(c(),j(`div`,{key:0,id:`brand-update-details`,class:`brand-update-popover`,role:`dialog`,"aria-label":C(p)(`console.update.title`,{version:_.value})},[k(`strong`,null,m(C(p)(`console.update.title`,{version:_.value})),1),k(`p`,null,m(C(p)(`console.update.copy`)),1),t[2]||=k(`code`,null,`fuli update --yes`,-1),k(`a`,{href:v.value,target:`_blank`,rel:`noopener noreferrer`},m(C(p)(`console.update.npmLink`)),9,ye)],8,ve)):h(``,!0)],2))}}),[[`__scopeId`,`data-v-3ccab825`]]),xe=[`aria-label`],Se=[`lang`,`aria-label`,`aria-pressed`,`onClick`],Ce=l({__name:`LocaleSwitcher`,setup(e){let t=f(()=>S()),n={"zh-CN":`中`,"en-US":`EN`};function r(e){e!==t.value&&y(e)}return(e,a)=>(c(),j(`div`,{class:`locale-switcher`,role:`group`,"aria-label":C(p)(`common.language.label`)},[(c(!0),j(v,null,i(C(O),e=>(c(),j(`button`,{key:e,type:`button`,lang:e,"aria-label":C(p)(e===`zh-CN`?`common.language.chinese`:`common.language.english`),"aria-pressed":t.value===e,onClick:t=>r(e)},m(n[e]),9,Se))),128))],8,xe))}}),X=e(null);function we(e){let t=e.onError((t,n)=>{let r=e.resolve(n).href;!r.startsWith(`/`)||r.startsWith(`//`)||(X.value={href:r,resourceFailure:/dynamically imported module|module script|loading chunk|preload css|importing a module/i.test(String(t))})}),n=e.afterEach((e,t,n)=>{n||(X.value=null)});return()=>{t(),n()}}var Te={key:0,class:`navigation-recovery`,role:`alert`},Ee=[`href`],De=L(l({__name:`NavigationRecovery`,setup(e){return(e,t)=>C(X)?(c(),j(`div`,Te,[k(`div`,null,[k(`strong`,null,m(C(p)(`routes.loadFailure.title`)),1),k(`p`,null,m(C(p)(C(X).resourceFailure?`routes.loadFailure.resources`:`routes.loadFailure.message`)),1)]),k(`a`,{href:C(X).href,class:`quiet-button`},m(C(p)(`routes.loadFailure.reload`)),9,Ee),k(`button`,{type:`button`,class:`navigation-recovery-dismiss`,onClick:t[0]||=e=>X.value=null},m(C(p)(`routes.loadFailure.dismiss`)),1)])):h(``,!0)}}),[[`__scopeId`,`data-v-83dee1c5`]]),Oe={class:`nav-section-label`},ke={class:`employee-nav-mark`,"aria-hidden":`true`},Ae=[`src`],je={class:`nav-copy`},Me=L(l({__name:`EmployeeNavigation`,props:{personalSpaceId:{}},setup(e){let t=e;N(()=>t.personalSpaceId,e=>{K(e===`current`?``:e)},{immediate:!0});let n=f(()=>G.value.filter(e=>e.agentId&&e.agentStatus===`active`&&(e.runtime||e.workbench?.kind===`native`)));return(t,a)=>n.value.length?(c(),j(v,{key:0},[k(`p`,Oe,m(C(p)(`employees.directory`)),1),(c(!0),j(v,null,i(n.value,t=>(c(),j(`div`,{key:t.id,class:`employee-nav-row`},[A(C(H),{to:C(ne)(e.personalSpaceId,t.agentId),class:`space-nav-button employee-nav`,"active-class":`is-active`},{default:u(()=>[k(`span`,ke,[C(q)(t.id)?(c(),j(`img`,{key:0,src:C(q)(t.id),alt:``},null,8,Ae)):(c(),j(v,{key:1},[r(m(t.name.slice(0,1)),1)],64))]),k(`span`,je,[k(`strong`,null,m(t.name),1),k(`small`,null,m(t.role),1)])]),_:2},1032,[`to`]),A(C(H),{class:`employee-workbench-link`,to:`/employees/${encodeURIComponent(t.id)}`,"aria-label":`${t.name} · ${C(p)(`agentProfiles.workbench`)}`,title:C(p)(`agentProfiles.workbench`)},{default:u(()=>[...a[0]||=[k(`svg`,{viewBox:`0 0 20 20`,width:`16`,height:`16`,"aria-hidden":`true`},[k(`path`,{d:`M3 4h14v12H3zM3 8h14M8 8v8`,fill:`none`,stroke:`currentColor`,"stroke-width":`1.4`})],-1)]]),_:1},8,[`to`,`aria-label`,`title`]),A(J,{"agent-id":t.agentId},null,8,[`agent-id`])]))),128))],64)):h(``,!0)}}),[[`__scopeId`,`data-v-8788995d`]]),Ne=[`title`],Pe={class:`employee-dialog-shell`},Fe={id:`attention-title`},Ie=[`disabled`,`aria-label`],Le={class:`employee-dialog-body`},Re={class:`attention-toolbar`},ze=[`disabled`],Be={key:0,role:`alert`,class:`employee-dialog-error`},Ve={key:1,role:`alert`,class:`employee-dialog-error`},He={key:4},Ue={class:`attention-meta`},We={class:`attention-action`},Ge=[`href`],Ke=[`onSubmit`],qe=[`for`],Je=[`id`,`onUpdate:modelValue`,`disabled`],Ye=[`disabled`],Xe={key:1},Ze=[`disabled`],Qe=L(l({__name:`AgentAttentionCenter`,props:{personalSpaceId:{},projects:{}},setup(e){let t=e,n=te(),r=d({}),o=d(!1),l=d({}),u=d(``),y=d(``),S=f(()=>new Map(t.projects.map(e=>[e.project_id,e.profile.name]))),{dialogRef:w,initialFocusRef:T,onCancel:E,onKeydown:D}=re(()=>n.open,()=>{u.value||(n.open=!1)});N(()=>t.personalSpaceId,e=>{r.value={},o.value=!1,l.value={},n.setSpace(e===`current`?``:e)},{immediate:!0}),N(()=>n.open,async e=>{if(!e)return;y.value=``;let t=n.spaceId;o.value=!0;try{let e=await W(`/api/project-agents?${new URLSearchParams({personalSpaceId:t})}`);t===n.spaceId&&(r.value=Object.fromEntries(e.map(e=>[e.agentId,e.profile.displayName||e.profile.name])))}catch{}finally{t===n.spaceId&&(o.value=!1)}});let O;function P(){document.visibilityState===`visible`&&!n.loading&&!n.open&&n.refresh()}s(()=>{O=setInterval(P,3e4),document.addEventListener(`visibilitychange`,P)}),b(()=>{clearInterval(O),document.removeEventListener(`visibilitychange`,P),n.setSpace(``)});async function F(e){if(!(u.value||!l.value[e.requestId]?.trim())){u.value=e.requestId,y.value=``;try{await n.respond(e,l.value[e.requestId].trim()),delete l.value[e.requestId]}catch(e){y.value=e instanceof Error?e.message:String(e),await n.refresh()}finally{u.value=``}}}return(e,t)=>(c(),j(v,null,[k(`button`,{class:`space-nav-button attention-nav`,type:`button`,onClick:t[0]||=e=>C(n).show()},[k(`span`,null,m(C(p)(`attention.title`)),1),A(J,{passive:``}),C(n).error?(c(),j(`span`,{key:0,title:C(p)(`attention.loadError`)},`!`,8,Ne)):h(``,!0)]),(c(),M(_,{to:`body`},[C(n).open?(c(),j(`dialog`,{key:0,ref_key:`dialogRef`,ref:w,class:`employee-dialog attention-dialog`,"aria-labelledby":`attention-title`,onCancel:t[6]||=(...e)=>C(E)&&C(E)(...e),onKeydown:t[7]||=(...e)=>C(D)&&C(D)(...e)},[k(`div`,Pe,[k(`header`,null,[k(`h2`,Fe,m(C(n).agentId&&r.value[C(n).agentId]||C(p)(`attention.title`)),1),k(`button`,{ref_key:`initialFocusRef`,ref:T,type:`button`,disabled:!!u.value,"aria-label":C(p)(`attention.close`),onClick:t[1]||=e=>C(n).open=!1},`×`,8,Ie)]),k(`div`,Le,[k(`div`,Re,[C(n).agentId?(c(),j(`button`,{key:0,type:`button`,onClick:t[2]||=e=>C(n).show()},m(C(p)(`attention.all`)),1)):h(``,!0),k(`button`,{type:`button`,disabled:C(n).loading||!!u.value,onClick:t[3]||=e=>C(n).refresh()},m(C(p)(`attention.refresh`)),9,ze)]),C(n).error?(c(),j(`p`,Be,m(C(p)(`attention.loadError`))+` · `+m(C(n).error),1)):h(``,!0),y.value?(c(),j(`p`,Ve,m(y.value),1)):h(``,!0),o.value?(c(),M(I,{key:2,variant:`inline`,label:C(p)(`attention.loadingAgents`)},null,8,[`label`])):h(``,!0),C(n).loading?(c(),M(I,{key:3,variant:`compact`,label:C(p)(`attention.loading`)},null,8,[`label`])):!C(n).items.length&&!C(n).error?(c(),j(`p`,He,m(C(p)(`attention.empty`)),1)):h(``,!0),(c(!0),j(v,null,i(C(n).items,e=>(c(),j(`article`,{key:e.requestId,class:`attention-item`},[k(`p`,Ue,m(r.value[e.agentId]||e.agentId)+` · `+m(S.value.get(e.personalProjectId)||e.personalProjectId)+` · `+m(C(p)(`attention.kinds.${e.kind}`)),1),k(`h3`,null,m(e.title),1),k(`p`,null,m(e.detail),1),k(`p`,We,m(e.requestedAction),1),e.taskId?(c(),j(`a`,{key:0,href:C(ee)(e),onClick:t[4]||=e=>C(n).open=!1},m(C(p)(`attention.task`)),9,Ge)):h(``,!0),k(`form`,{onSubmit:x(t=>F(e),[`prevent`])},[k(`label`,{for:`attention-${e.requestId}`},m(C(p)(`attention.response`)),9,qe),a(k(`textarea`,{id:`attention-${e.requestId}`,"onUpdate:modelValue":t=>l.value[e.requestId]=t,rows:`2`,maxlength:`4096`,required:``,disabled:!!u.value},null,8,Je),[[g,l.value[e.requestId]]]),k(`button`,{type:`submit`,class:`primary`,disabled:!!u.value||!l.value[e.requestId]?.trim()},[u.value===e.requestId?(c(),M(I,{key:0,variant:`inline`,label:C(p)(`attention.sending`)},null,8,[`label`])):(c(),j(`span`,Xe,m(C(p)(`attention.send`)),1))],8,Ye)],40,Ke)]))),128)),C(n).items.length<C(n).filteredTotal?(c(),j(`button`,{key:5,type:`button`,disabled:C(n).loading,onClick:t[5]||=e=>C(n).more()},m(C(p)(`attention.more`)),9,Ze)):h(``,!0)])])],544)):h(``,!0)]))],64))}}),[[`__scopeId`,`data-v-521df451`]]),$e=[`routes.`,`common.`,`employees.`,`agentProfiles.`];function et(e,t=``){let n=typeof e==`string`&&e?e:t;return $e.some(e=>n.startsWith(e))?p(n):n}function tt(e){if(typeof document>`u`)return;let t=et(e,`routes.overview.title`);document.title=`${t} · ${p(`common.brand`)}`}var nt={class:`app-shell`},rt=[`onKeydown`],it=[`aria-label`],at={class:`nav-section-label`},ot={class:`nav-label`},st={class:`nav-section-label nav-space-label`},ct={class:`nav-copy`},lt={class:`nav-copy`},ut={class:`nav-copy`},dt={class:`nav-copy`},ft={class:`nav-section-label nav-public-label`},pt={class:`nav-copy`},mt={class:`nav-section-label nav-tool-label`},ht={class:`nav-label`},gt={class:`nav-label`},_t={class:`nav-label`},vt={class:`nav-section-label nav-about-label`},yt={class:`nav-label`},bt={class:`nav-label`},xt={class:`sidebar-foot`},St=[`aria-label`],Ct={class:`runtime-status`},wt={class:`runtime-status`},Tt=[`aria-label`],Et=[`inert`],Dt=[`aria-expanded`],Ot={key:0,class:`workbench-host-label`},kt={key:1,class:`topbar-heading`},At={key:2,class:`topbar-actions`},jt={key:0,class:`mode-chip`},Mt=[`disabled`],Nt=[`disabled`],Pt={key:1},Ft=[`aria-label`],It=L(l({__name:`ConsoleLayout`,setup(e){let i=F(),a=R(),l=d(!1),g=d(null),_=d(null),y=f(()=>i.activePersonalSpace?.id??`current`),S=f(()=>ie(y.value,`graph`)),T=f(()=>ae(`personal`,y.value,`directory`)),D=f(()=>et(a.meta.title,`routes.overview.title`)),O=f(()=>a.meta.dedicatedWorkspace===!0),P=f(()=>i.publicRuntimeStatus===`ready`),L=f(()=>i.publicRuntimeStatus===`ready`?p(`console.services.publicReady`):i.publicRuntimeStatus===`error`?p(`console.services.publicError`):p(`console.services.publicOffline`)),z=f(()=>{if(i.publicRuntimeStatus===`ready`){let e=i.state?.capabilities;return e?.browsePublicProjects&&e?.subscribeProject&&!e?.publishProject&&!e?.submitKnowledge&&!e?.reviewProposals?p(`console.services.publicBrowseSubscribe`):p(`console.services.publicAvailable`)}return i.publicRuntimeStatus===`error`?p(`console.services.localUnaffected`):p(`console.services.localOnly`)}),V=f(()=>i.state?.capabilities?.browsePublicProjects!==!1),U=f(()=>{let e=i.state?.capabilities;return e?.submitKnowledge!==!1||e?.reviewProposals===!0});s(()=>{i.runtimeStatus===`idle`&&i.refresh(),window.addEventListener(`resize`,W)}),b(()=>window.removeEventListener(`resize`,W));function W(){window.innerWidth>920&&(l.value=!1)}function G(e){if(!l.value||e.key!==`Tab`)return;let t=[...e.currentTarget.querySelectorAll(`button:not(:disabled), a[href], input:not(:disabled), [tabindex="0"]`)].filter(e=>e.getClientRects().length>0),n=t[0],r=t.at(-1);e.shiftKey&&document.activeElement===n?(e.preventDefault(),r?.focus()):!e.shiftKey&&document.activeElement===r&&(e.preventDefault(),n?.focus())}n(()=>{tt(a.meta.title)}),N(()=>a.fullPath,()=>{l.value=!1});async function K(){l.value=!0,await t(),_.value?.focus({preventScroll:!0})}async function q(){l.value=!1,await t(),g.value?.focus({preventScroll:!0})}return(e,t)=>(c(),j(`div`,nt,[k(`aside`,{id:`console-primary-sidebar`,class:E([`sidebar`,{"is-mobile-open":l.value}]),onKeydown:[w(x(q,[`stop`]),[`esc`]),G]},[k(`button`,{ref_key:`mobileNavCloseRef`,ref:_,class:`mobile-nav-close quiet-button`,type:`button`,onClick:q},m(C(p)(`console.navigation.closeMenu`)),513),A(be),k(`nav`,{class:`primary-nav`,"aria-label":C(p)(`console.navigation.aria`)},[k(`p`,at,m(C(p)(`console.navigation.workspace`)),1),A(C(H),{to:`/`,"exact-active-class":`is-active`},{default:u(()=>[t[2]||=k(`span`,{class:`nav-icon nav-icon-overview`,"aria-hidden":`true`},null,-1),k(`span`,ot,m(C(p)(`console.navigation.overview`)),1)]),_:1}),k(`p`,st,m(C(p)(`console.navigation.personalSpace`)),1),A(C(H),{class:`space-nav-button personal-profile-button`,to:`/preferences`,"active-class":`is-active`},{default:u(()=>[t[3]||=k(`span`,{class:`nav-icon nav-icon-personal-profile`,"aria-hidden":`true`},null,-1),k(`span`,ct,[k(`strong`,null,m(C(p)(`console.navigation.preferences`)),1),k(`small`,null,m(C(p)(`console.navigation.preferencesMeta`)),1)])]),_:1}),A(C(H),{class:`space-nav-button knowledge-organizer-button`,to:`/organize`,"active-class":`is-active`},{default:u(()=>[t[4]||=k(`span`,{class:`nav-icon nav-icon-knowledge-organizer`,"aria-hidden":`true`},null,-1),k(`span`,lt,[k(`strong`,null,m(C(p)(`console.navigation.organizer`)),1),k(`small`,null,m(C(p)(`console.navigation.organizerMeta`)),1)])]),_:1}),A(C(H),{class:`space-nav-button personal-space-button`,to:S.value,"active-class":`is-active`},{default:u(()=>[t[5]||=k(`span`,{class:`nav-icon nav-icon-personal-project`,"aria-hidden":`true`},null,-1),k(`span`,ut,[k(`strong`,null,m(C(p)(`console.navigation.personalProjects`)),1),k(`small`,null,m(C(p)(`console.navigation.personalProjectsMeta`)),1)])]),_:1},8,[`to`]),A(C(H),{class:`space-nav-button project-agents-button`,to:`/project-agents`,"active-class":`is-active`},{default:u(()=>[t[6]||=k(`span`,{class:`nav-icon nav-icon-project-agent`,"aria-hidden":`true`},null,-1),k(`span`,dt,[k(`strong`,null,m(C(p)(`console.navigation.projectAgents`)),1),k(`small`,null,m(C(p)(`console.navigation.projectAgentsMeta`)),1)])]),_:1}),V.value?(c(),j(v,{key:0},[k(`p`,ft,m(C(p)(`console.navigation.publicSpace`)),1),A(C(H),{class:`space-nav-button public-space-button`,to:`/public-projects`,"active-class":`is-active`},{default:u(()=>[t[7]||=k(`span`,{class:`nav-icon nav-icon-public-project`,"aria-hidden":`true`},null,-1),k(`span`,pt,[k(`strong`,null,m(C(p)(`console.navigation.publicProjects`)),1),k(`small`,null,m(C(p)(`console.navigation.publicProjectsMeta`)),1)])]),_:1})],64)):h(``,!0),A(Me,{"personal-space-id":y.value},null,8,[`personal-space-id`]),A(Qe,{"personal-space-id":y.value,projects:C(i).state?.personalProjects??[]},null,8,[`personal-space-id`,`projects`]),k(`p`,mt,m(C(p)(`console.navigation.governance`)),1),A(C(H),{to:T.value,"active-class":`is-active`},{default:u(()=>[t[8]||=k(`span`,{class:`nav-icon nav-icon-knowledge-graph`,"aria-hidden":`true`},null,-1),k(`span`,ht,m(C(p)(`console.navigation.knowledge`)),1)]),_:1},8,[`to`]),U.value?(c(),M(C(H),{key:1,to:`/review`,"active-class":`is-active`},{default:u(()=>[t[9]||=k(`span`,{class:`nav-icon nav-icon-review`,"aria-hidden":`true`},null,-1),k(`span`,gt,m(C(p)(`console.navigation.review`)),1)]),_:1})):h(``,!0),A(C(H),{to:`/connections`,"active-class":`is-active`},{default:u(()=>[t[10]||=k(`span`,{class:`nav-icon nav-icon-connections`,"aria-hidden":`true`},null,-1),k(`span`,_t,m(C(p)(`console.navigation.connections`)),1)]),_:1}),k(`p`,vt,m(C(p)(`console.navigation.aboutSection`)),1),A(C(H),{to:`/settings`,"active-class":`is-active`},{default:u(()=>[t[11]||=k(`span`,{class:`nav-icon nav-icon-settings`,"aria-hidden":`true`},null,-1),k(`span`,yt,m(C(p)(`console.navigation.settings`)),1)]),_:1}),A(C(H),{to:`/about`,"active-class":`is-active`},{default:u(()=>[t[12]||=k(`span`,{class:`nav-icon nav-icon-about`,"aria-hidden":`true`},null,-1),k(`span`,bt,m(C(p)(`console.navigation.about`)),1)]),_:1})],8,it),k(`div`,xt,[k(`div`,{class:`service-runtime-list`,"aria-label":C(p)(`console.services.aria`)},[k(`div`,Ct,[k(`span`,{class:E([`status-dot`,C(i).runtimeStatus])},null,2),k(`div`,null,[k(`strong`,null,m(C(i).runtimeStatus===`ready`?C(p)(`console.services.localReady`):C(i).runtimeStatus===`error`?C(p)(`console.services.localError`):C(p)(`console.services.localConnecting`)),1),t[13]||=k(`small`,null,`Graphiti / Neo4j`,-1)])]),k(`div`,wt,[k(`span`,{class:E([`status-dot`,C(i).publicRuntimeStatus])},null,2),k(`div`,null,[k(`strong`,null,m(L.value),1),k(`small`,null,m(z.value),1)])])],8,St)])],42,rt),l.value?(c(),j(`button`,{key:0,class:`mobile-nav-backdrop`,type:`button`,tabindex:`-1`,"aria-label":C(p)(`console.navigation.closeMenu`),onClick:q},null,8,Tt)):h(``,!0),k(`main`,{class:`workspace`,inert:l.value||void 0},[k(`header`,{class:E([`topbar`,{"topbar--workbench":O.value}])},[k(`button`,{ref_key:`mobileNavToggleRef`,ref:g,class:`mobile-nav-toggle quiet-button`,type:`button`,"aria-controls":`console-primary-sidebar`,"aria-expanded":l.value,onClick:K},[t[14]||=k(`span`,{class:`mobile-nav-icon`,"aria-hidden":`true`},null,-1),r(` `+m(C(p)(`console.navigation.openMenu`)),1)],8,Dt),O.value?(c(),j(`span`,Ot,`FULI`)):(c(),j(`div`,kt,[k(`h2`,null,m(D.value),1)])),O.value?h(``,!0):(c(),j(`div`,At,[P.value?(c(),j(`span`,jt,m(C(p)(`console.publicReady`)),1)):h(``,!0),C(a).name===`settings`?(c(),j(`button`,{key:1,class:`settings-save-button`,disabled:C(i).settingsSaving,form:`settings-form`,type:`submit`},m(C(p)(`settings.save`)),9,Mt)):h(``,!0),A(Ce),k(`button`,{class:`quiet-button`,type:`button`,disabled:C(i).runtimeStatus===`loading`,onClick:t[0]||=(...e)=>C(i).refresh&&C(i).refresh(...e)},[C(i).runtimeStatus===`loading`?(c(),M(I,{key:0,variant:`inline`,label:C(p)(`common.status.loadingConsole`)},null,8,[`label`])):(c(),j(`span`,Pt,m(C(p)(`common.actions.refresh`)),1))],8,Nt)]))],2),A(De),C(i).feedback?(c(),j(`div`,{key:0,class:E([`feedback feedback-message`,{success:C(i).feedback.tone===`success`}]),role:`status`,"aria-live":`polite`},[k(`span`,null,m(C(i).feedback.message),1),k(`button`,{class:`feedback-dismiss`,type:`button`,"aria-label":C(p)(`common.actions.close`),onClick:t[1]||=(...e)=>C(i).clearFeedback&&C(i).clearFeedback(...e)},`×`,8,Ft)],2)):h(``,!0),A(C(B),null,{default:u(({Component:e})=>[(c(),M(o(e)))]),_:1})],8,Et)]))}}),[[`__scopeId`,`data-v-9fe7a62f`]]),Lt=l({__name:`App`,setup(e){let t=R();return(e,n)=>C(t).meta.publicReport?(c(),M(C(B),{key:0})):(c(),M(It,{key:1}))}}),Rt=`modulepreload`,zt=function(e){return`/`+e},Bt={},Z=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e=document.getElementsByTagName(`link`),i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?import.meta.resolve(e):new URL(e,import.meta.url).href}r=o(t.map(t=>{if(t=zt(t,n),t=s(t),t in Bt)return;Bt[t]=!0;let r=t.endsWith(`.css`);for(let n=e.length-1;n>=0;n--){let i=e[n];if(i.href===t&&(!r||i.rel===`stylesheet`))return}let i=document.createElement(`link`);if(i.rel=r?`stylesheet`:Rt,r||(i.as=`script`),i.crossOrigin=``,i.href=t,a&&i.setAttribute(`nonce`,a),document.head.appendChild(i),r)return new Promise((e,n)=>{i.addEventListener(`load`,e),i.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${t}`)))})}))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})};function Vt(e){let t=e.match(/^#\/knowledge\/([^/?#]+)\/([^/?#]+)\/(entity|relationship)\/([^/?#]+)(?:\?([^#]*))?$/);if(!t)return null;let[,n,r,i,a,o]=t;return`/knowledge/${n}/${r}/directory/${i}/${a}${o?`?${o}`:``}`}var Q=V({history:z(`/`),routes:[{path:`/reports/jefa`,name:`shared-jefa-report`,component:()=>Z(()=>import(`./SharedJefaReportPage-CbFtrDCY.js`),__vite__mapDeps([0,1,2,3,4,5,6,7,8,9,10,11])),meta:{publicReport:!0,title:`employees.share.title`}},{path:`/`,name:`overview`,component:()=>Z(()=>import(`./OverviewPage-BreX_kb4.js`),__vite__mapDeps([12,1,13,7,14,5,15])),meta:{eyebrow:``,title:`routes.overview.title`}},{path:`/preferences`,name:`personal-profile`,component:()=>Z(()=>import(`./PersonalProfilePage-CX1a6_E3.js`),__vite__mapDeps([16,1,13,7,2,3,4,14,5,17,18,19,20,21,22,23,24,25,26,27])),meta:{eyebrow:`PERSONAL LENS`,title:`routes.preferences.title`,description:`routes.preferences.description`}},{path:`/preferences/writing`,name:`writing-taste`,component:()=>Z(()=>import(`./WritingTastePage-B7lSzs2z.js`),__vite__mapDeps([28,1,13,7,2,3,4,14,5,23,17,18,24,20,25,26,29])),meta:{eyebrow:``,title:`routes.writingTaste.title`}},{path:`/personal/:spaceId/projects/:projectId/:mode/:itemKind/:itemId`,name:`personal-project-item`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECT`,title:`routes.personalProjects.title`}},{path:`/personal/:spaceId/projects/:mode/:itemKind/:itemId`,name:`personal-projects-item`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECTS`,title:`routes.personalProjects.title`,description:`routes.personalProjects.description`}},{path:`/personal/:spaceId/projects/:mode`,name:`personal-projects`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECTS`,title:`routes.personalProjects.title`,description:`routes.personalProjects.description`}},{path:`/personal/:spaceId/projects/:projectId/:mode`,name:`personal-project`,component:()=>Z(()=>import(`./PersonalProjectsPage-Br1S8ETM.js`),__vite__mapDeps([30,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`PERSONAL PROJECT`,title:`routes.personalProjects.title`}},{path:`/organize`,name:`knowledge-organizer`,component:()=>Z(()=>import(`./KnowledgeOrganizerPage-DMC8Hh43.js`),__vite__mapDeps([33,1,13,7,2,3,4,17,18,24,19,20,21,22,23,25,34])),meta:{eyebrow:`KNOWLEDGE CLASSIFICATION`,title:`routes.organizer.title`}},{path:`/project-agents`,name:`project-agents`,component:()=>Z(()=>import(`./AgentsDirectoryPage-CKZfrcuD.js`),__vite__mapDeps([35,1,13,7,2,3,4,5,14,36,37,38,39,40,41,42,43,8,9,44,45,17,15,18,46])),meta:{eyebrow:``,title:`routes.projectAgents.title`}},{path:`/agents/:spaceId/:agentId`,name:`agent-profile`,component:()=>Z(()=>import(`./AgentProfilePage-BPQEfMhB.js`),__vite__mapDeps([47,1,13,7,2,3,4,5,14,45,38,39,40,42,41,43])),meta:{eyebrow:``,title:`agentProfiles.profile`}},{path:`/project-agents/manage`,name:`agent-management`,component:()=>Z(()=>import(`./ProjectAgentsPage-CA04h1Uf.js`),__vite__mapDeps([48,1,13,7,2,3,4,5,14,45,36,37,17,42,8,9,18,44,15,46,49])),meta:{eyebrow:``,title:`agentProfiles.advanced`}},{path:`/employees/:templateId`,name:`employee-workbench`,component:()=>Z(()=>import(`./EmployeeWorkbenchPage-HUd-gne2.js`),__vite__mapDeps([50,1,13,7,2,3,4,5,14,45,36,37,38,17,39,40,8,9,44,15,18,46,6,10,51,52])),meta:{eyebrow:``,title:`routes.employeeWorkbench.title`,dedicatedWorkspace:!0}},{path:`/public-projects`,name:`public-projects`,component:()=>Z(()=>import(`./PublicProjectsPage-CtctKml1.js`),__vite__mapDeps([53,1,13,7,2,3,4,5,17,15,18,24])),meta:{eyebrow:`PUBLIC PROJECTS`,title:`routes.publicProjects.title`,description:`routes.publicProjects.description`}},{path:`/knowledge`,name:`knowledge-default`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:projectId/:mode/:itemKind/:itemId`,name:`project-knowledge-item`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:mode/:itemKind/:itemId`,name:`knowledge-item`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:projectId/:mode`,name:`project-knowledge`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/knowledge/:scope/:spaceId/:mode`,name:`knowledge`,component:()=>Z(()=>import(`./KnowledgePage-uXW1Eovz.js`),__vite__mapDeps([54,1,31,13,7,2,3,4,5,14,17,15,18,24,19,20,21,22,23,25,32])),meta:{eyebrow:`KNOWLEDGE BASE`,title:`routes.knowledge.title`}},{path:`/review`,name:`review`,component:()=>Z(()=>import(`./ReviewPage-DUqaK-do.js`),__vite__mapDeps([55,1,13,7,2,3,4,18,24,20])),meta:{eyebrow:`REVIEW WORKSPACE`,title:`routes.review.title`,description:`routes.review.description`}},{path:`/connections`,name:`connections`,component:()=>Z(()=>import(`./ConnectionsPage-COb56qnk.js`),__vite__mapDeps([56,1,13,7,2,3,4,18,24,57])),meta:{eyebrow:`SERVICE CONNECTIONS`,title:`routes.connections.title`,description:`routes.connections.description`}},{path:`/settings`,name:`settings`,component:()=>Z(()=>import(`./SettingsPage-CB4ymLr8.js`),__vite__mapDeps([58,1,13,7,2,3,4,18,21,59])),meta:{eyebrow:``,title:`routes.settings.title`}},{path:`/about`,name:`about`,component:()=>Z(()=>import(`./AboutPage-fBq5VFoQ.js`),__vite__mapDeps([60,1,3,61,62])),meta:{eyebrow:`FULI`,title:`routes.about.title`}},{path:`/:pathMatch(.*)*`,name:`not-found`,component:()=>Z(()=>import(`./NotFoundPage-C0yOR9T9.js`),__vite__mapDeps([63,1,14,5])),meta:{title:`common.errors.pageNotFound`}}],scrollBehavior:(e,t,n)=>n??(e.path!==t.path&&{top:0})});we(Q),Q.beforeEach(e=>e.path!==`/`||typeof window>`u`?!0:Vt(window.location.hash)??!0),Q.afterEach(e=>{tt(e.meta.title)});var $=D(Lt);$.use(P()),$.use(T),$.use(Q),await Q.isReady().catch(()=>void 0),$.mount(`#app`);
@@ -1,165 +0,0 @@
1
- import { randomUUID } from 'node:crypto';
2
-
3
- import { ApplicationError, ApplicationErrorCode } from '../app/application-error.js';
4
-
5
- const MAX_ACTIVE_SESSIONS = 256;
6
-
7
- function unknownTokenError() {
8
- return new ApplicationError(
9
- ApplicationErrorCode.NOT_FOUND,
10
- 'Fuli task context token is unknown or superseded. Call begin_task_context for the current session and use the token it returns.'
11
- );
12
- }
13
-
14
- export class TaskContextRegistry {
15
- constructor({ tokenFactory = () => `fuli-task-${randomUUID()}` } = {}) {
16
- this.tokenFactory = tokenFactory;
17
- this.sessions = new Map();
18
- this.tokens = new Map();
19
- }
20
-
21
- begin({ sessionId, turnId = null, personalProjectId, projectAgentId = null,
22
- sourceApplication = 'other', sourceSessionId = null, memoryRevision = null, workLogRequired = false }) {
23
- assertNonEmpty(sessionId, 'sessionId');
24
- const key = sessionKey(sourceApplication, sessionId);
25
- const previous = this.sessions.get(key) ?? null;
26
- if (!previous) this.#reserveSessionSlot();
27
- if (previous) this.tokens.delete(previous.token);
28
-
29
- const task = {
30
- token: this.tokenFactory(),
31
- sessionId,
32
- turnId,
33
- personalProjectId: personalProjectId ?? null,
34
- projectAgentId,
35
- sourceApplication,
36
- sourceSessionId,
37
- memoryRevision,
38
- workLogRequired,
39
- agentMemory: null,
40
- checkpoint: null
41
- };
42
- this.sessions.delete(key);
43
- this.sessions.set(key, task);
44
- this.tokens.set(task.token, task);
45
- return {
46
- ...snapshot(task),
47
- previousCheckpointMissing: Boolean(previous && (!previous.checkpoint || previous.checkpoint.phase === 'prepare'))
48
- };
49
- }
50
-
51
- checkpoint(token, checkpoint, sourceApplication = 'other') {
52
- const task = this.#task(token, sourceApplication);
53
- if (task.checkpoint?.phase === 'prepare') {
54
- if (!sameCheckpointClaim(task.checkpoint, checkpoint)) {
55
- throw checkpointConflict('Task checkpoint has different input');
56
- }
57
- } else if (task.checkpoint) {
58
- if (sameCheckpoint(task.checkpoint, checkpoint)) return snapshot(task);
59
- throw checkpointConflict(
60
- 'Fuli task context has already been checkpointed with a different disposition'
61
- );
62
- }
63
- task.checkpoint = Object.freeze({ ...checkpoint, phase: 'complete' });
64
- return snapshot(task);
65
- }
66
-
67
- prepare(token, checkpoint, sourceApplication = 'other', agentMemory = null) {
68
- const task = this.#task(token, sourceApplication);
69
- if (agentMemory !== null && agentMemory !== undefined) {
70
- throw new ApplicationError(
71
- ApplicationErrorCode.VALIDATION,
72
- 'The in-memory task context registry cannot atomically persist durable Agent memory'
73
- );
74
- }
75
- if (task.checkpoint && !sameCheckpointClaim(task.checkpoint, checkpoint)) {
76
- throw checkpointConflict('Task checkpoint has different input');
77
- }
78
- if (!task.checkpoint) task.checkpoint = { ...checkpoint, phase: 'prepare' };
79
- return snapshot(task);
80
- }
81
-
82
- context(token, sourceApplication = 'other') {
83
- return snapshot(this.#task(token, sourceApplication));
84
- }
85
-
86
- #task(token, sourceApplication) {
87
- assertNonEmpty(token, 'taskContextToken');
88
- const task = this.tokens.get(token);
89
- if (!task || task.sourceApplication !== sourceApplication) throw unknownTokenError();
90
- const key = sessionKey(task.sourceApplication, task.sessionId);
91
- if (this.sessions.get(key) !== task) throw unknownTokenError();
92
- this.sessions.delete(key);
93
- this.sessions.set(key, task);
94
- return task;
95
- }
96
-
97
- verify(sessionId, sourceApplication = 'other') {
98
- assertNonEmpty(sessionId, 'sessionId');
99
- const task = this.sessions.get(sessionKey(sourceApplication, sessionId));
100
- if (!task) {
101
- return {
102
- status: 'not_started',
103
- guidance: 'No Fuli task context was started; do not block the Agent.'
104
- };
105
- }
106
- if (task.checkpoint && task.checkpoint.phase !== 'prepare') {
107
- return {
108
- status: 'checkpointed',
109
- disposition: task.checkpoint.disposition
110
- };
111
- }
112
- return {
113
- status: 'checkpoint_required',
114
- decision: 'block',
115
- task_context_token: task.token,
116
- reason: `FULI_CHECKPOINT_REQUIRED: ${task.token} Before finishing, call checkpoint_task_knowledge once with either a bounded durable candidate batch or retain_nothing. Do not store raw transcripts, guesses, or temporary output.`
117
- };
118
- }
119
-
120
- #reserveSessionSlot() {
121
- if (this.sessions.size < MAX_ACTIVE_SESSIONS) return;
122
- for (const [key, task] of this.sessions) {
123
- if (task.checkpoint?.phase !== 'complete') continue;
124
- this.sessions.delete(key);
125
- this.tokens.delete(task.token);
126
- return;
127
- }
128
- throw new ApplicationError(
129
- ApplicationErrorCode.VALIDATION,
130
- 'Fuli has too many unfinished in-memory task contexts; finish an existing context or restart this fallback MCP process'
131
- );
132
- }
133
- }
134
-
135
- function snapshot(task) {
136
- return structuredClone(task);
137
- }
138
-
139
- function sessionKey(sourceApplication, sessionId) {
140
- return JSON.stringify([sourceApplication, sessionId]);
141
- }
142
-
143
- function assertNonEmpty(value, label) {
144
- if (typeof value !== 'string' || !value.trim()) {
145
- throw new ApplicationError(
146
- ApplicationErrorCode.VALIDATION,
147
- `${label} must be a nonempty string`
148
- );
149
- }
150
- }
151
-
152
- function sameCheckpoint(left, right) {
153
- return sameCheckpointClaim(left, right)
154
- && left.captureStatus === right.captureStatus;
155
- }
156
-
157
- function sameCheckpointClaim(left, right) {
158
- return left.fingerprint === right.fingerprint
159
- && left.disposition === right.disposition
160
- && left.reason === right.reason;
161
- }
162
-
163
- function checkpointConflict(message) {
164
- return new ApplicationError(ApplicationErrorCode.VALIDATION, message);
165
- }