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.
- package/dist/web/assets/index-7X3LGByg.js +2 -0
- package/dist/web/index.html +1 -1
- package/docs/agent-interface-architecture.md +17 -0
- package/docs/employee-agents.md +14 -1
- package/docs/project-agent-memory.md +6 -1
- package/graph-provider/fuli_graph/knowledge_search.py +8 -16
- package/graph-provider/fuli_graph/project_agent_routes.py +5 -1
- package/graph-provider/pyproject.toml +1 -1
- package/npm-shrinkwrap.json +15 -15
- package/package.json +3 -3
- package/skills/capturing-session-knowledge/SKILL.md +20 -2
- package/src/agent-tools/employee-definitions.js +6 -5
- package/src/agent-tools/graph-definitions.js +2 -2
- package/src/employees/service.js +8 -1
- package/src/graphiti/agent-knowledge-workflows.js +1 -1
- package/src/graphiti/project-agent-workflows.js +10 -1
- package/src/graphiti/project-path-context.js +17 -10
- package/src/mcp/create-mcp-server.js +6 -1
- package/src/mcp/employee-tool-catalog.js +22 -0
- package/src/mcp/tool-result.js +3 -1
- package/dist/web/assets/index-MKmHNBtc.js +0 -2
- package/src/mcp/task-context-registry.js +0 -165
|
@@ -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`);
|
package/dist/web/index.html
CHANGED
|
@@ -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-
|
|
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:
|
package/docs/employee-agents.md
CHANGED
|
@@ -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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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',
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fuli-context",
|
|
3
|
-
"version": "0.8.
|
|
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.
|
|
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.
|
|
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.
|
|
1871
|
-
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.
|
|
1872
|
-
"integrity": "sha512-
|
|
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.
|
|
2953
|
-
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.
|
|
2954
|
-
"integrity": "sha512-
|
|
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.
|
|
3289
|
-
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.
|
|
3290
|
-
"integrity": "sha512-
|
|
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.
|
|
5081
|
-
"resolved": "https://registry.npmjs.org/undici/-/undici-7.
|
|
5082
|
-
"integrity": "sha512-
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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.
|
|
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
|
|
33
|
-
inputSchema: objectSchema(
|
|
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
|
-
...
|
|
40
|
+
...workbenchTarget, tool: id,
|
|
40
41
|
arguments: { type: 'object', additionalProperties: true }
|
|
41
|
-
}, ['
|
|
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
|
|
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
|
|
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
|
{
|
package/src/employees/service.js
CHANGED
|
@@ -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
|
-
|
|
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:
|
|
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
|
|
59
|
-
|
|
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
|
|
64
|
-
if (
|
|
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(
|
|
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
|
+
}
|
package/src/mcp/tool-result.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
}
|