@promptowl/contextnest-community 1.23.0 → 1.25.0

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.
Files changed (91) hide show
  1. package/API.md +2195 -0
  2. package/CONFIGURATION.md +8 -2
  3. package/README.md +62 -10
  4. package/STEWARDSHIP.md +253 -0
  5. package/dist/{chunk-2YPY2HGZ.js → chunk-2KHM5C7V.js} +40 -5
  6. package/dist/{chunk-XYD6V2LH.js → chunk-32SZCH36.js} +28 -33
  7. package/dist/{chunk-QLXC6542.js → chunk-7FROMOZM.js} +69 -27
  8. package/dist/{chunk-MLQU4I5J.js → chunk-DTLMBF4W.js} +10 -8
  9. package/dist/{chunk-QWNXWRWO.js → chunk-JDAOA5KP.js} +67 -1
  10. package/dist/{chunk-UOMW7TT6.js → chunk-KPGNZLZL.js} +2 -2
  11. package/dist/{chunk-YVMSM7LS.js → chunk-LHWOJPFE.js} +7 -0
  12. package/dist/{chunk-5CVZMHHB.js → chunk-TI7HMP64.js} +99 -12
  13. package/dist/{client-LWDMNKX3.js → client-D44ZHDTJ.js} +1 -1
  14. package/dist/{engine-QFF2IA3G.js → engine-TER6FDBP.js} +3 -3
  15. package/dist/{external-edit-service-F7D3VSA2.js → external-edit-service-CAGENHDJ.js} +4 -4
  16. package/dist/{grants-service-TBGTCO5K.js → grants-service-2OTFS7EH.js} +3 -3
  17. package/dist/index.js +1120 -331
  18. package/dist/{migrations.postgres-APCVSYUE.js → migrations.postgres-23VJJJJX.js} +56 -5
  19. package/dist/{review-service-A7PNLWG5.js → review-service-4G2XUFS6.js} +7 -7
  20. package/dist/{stewardship-service-32UHIRQ5.js → stewardship-service-S22V2JKG.js} +6 -4
  21. package/dist/{version-service-RJ6CWZ3O.js → version-service-X4FAG2OZ.js} +4 -4
  22. package/dist/web3/assets/ActivityTracePage-D2iIbEph.js +1 -0
  23. package/dist/web3/assets/AgentDocsPage-Dkhgb1hk.js +1 -0
  24. package/dist/web3/assets/CollaboratorManager-Bo81D--Q.js +1 -0
  25. package/dist/web3/assets/CollaboratorsTab-DRCitQuX.js +1 -0
  26. package/dist/web3/assets/DocumentEditor-DV2WHYbj.js +36 -0
  27. package/dist/web3/assets/DocumentsTab-BUxBCN8o.js +6 -0
  28. package/dist/web3/assets/ExternalEditsTab-kIBimZyE.js +1 -0
  29. package/dist/web3/assets/MarkdownEditor-CsVusP2d.css +1 -0
  30. package/dist/web3/assets/MarkdownEditor-Dfk5uIE5.js +648 -0
  31. package/dist/web3/assets/NestPageHeader-yOK-OIYZ.js +1 -0
  32. package/dist/web3/assets/NestView-DwIagxwJ.js +68 -0
  33. package/dist/web3/assets/OverviewTab-DFOFMVyE.js +1 -0
  34. package/dist/web3/assets/PersonCombobox-D350WlrJ.js +1 -0
  35. package/dist/web3/assets/ReasonDialog-CN3ECAnQ.js +1 -0
  36. package/dist/web3/assets/ReviewActions-BXDTDPp1.js +6 -0
  37. package/dist/web3/assets/ReviewTab-CZewAYiz.js +1 -0
  38. package/dist/web3/assets/StewardsTab-AagNWcWS.js +1 -0
  39. package/dist/web3/assets/SubmitForReviewModal-BOZJxwRN.js +1 -0
  40. package/dist/web3/assets/alert-dialog-4SiLKlz8.js +7 -0
  41. package/dist/web3/assets/arrow-left-BAgIocLn.js +6 -0
  42. package/dist/web3/assets/backlinks-Cb8Uf8mw.js +24 -0
  43. package/dist/web3/assets/card-UDyMRcps.js +1 -0
  44. package/dist/web3/assets/chevron-left-XR4ReJ9Z.js +6 -0
  45. package/dist/web3/assets/circle-check-CSkZUEFK.js +6 -0
  46. package/dist/web3/assets/circle-x-in2o3aHU.js +6 -0
  47. package/dist/web3/assets/client-attribution-BraarYaP.js +1 -0
  48. package/dist/web3/assets/code-xml-pPQgdctI.js +6 -0
  49. package/dist/web3/assets/corner-down-right-CuxZWscX.js +6 -0
  50. package/dist/web3/assets/count-skeleton-DBWCDhRy.js +1 -0
  51. package/dist/web3/assets/dates-BCxbm4_q.js +1 -0
  52. package/dist/web3/assets/earth-CXOcThqn.js +6 -0
  53. package/dist/web3/assets/file-exclamation-point-CSphs1VD.js +6 -0
  54. package/dist/web3/assets/folder-input-BAwK9tFL.js +11 -0
  55. package/dist/web3/assets/folder-target-CUSWqImF.js +1 -0
  56. package/dist/web3/assets/index-A0_ymcqL.js +29 -0
  57. package/dist/web3/assets/index-B5hLclEq.js +389 -0
  58. package/dist/web3/assets/index-DrUAtoQM.css +1 -0
  59. package/dist/web3/assets/page-BHD4beun.js +1 -0
  60. package/dist/web3/assets/page-BSYUXYmO.js +11 -0
  61. package/dist/web3/assets/page-BYc2DIux.js +45 -0
  62. package/dist/web3/assets/page-BfibLg8e.js +1 -0
  63. package/dist/web3/assets/page-CGe8MtUu.js +9 -0
  64. package/dist/web3/assets/page-CIgPJmG6.js +2 -0
  65. package/dist/web3/assets/page-CUjuSs5Q.js +24 -0
  66. package/dist/web3/assets/page-Ck31nx9b.js +1 -0
  67. package/dist/web3/assets/page-Cpdj_11Y.js +1 -0
  68. package/dist/web3/assets/page-D0sN3GO6.js +1 -0
  69. package/dist/web3/assets/page-DEpH91X2.js +1 -0
  70. package/dist/web3/assets/page-l8-B7CGt.js +1 -0
  71. package/dist/web3/assets/page-mnSHmk6A.js +6 -0
  72. package/dist/web3/assets/page-title-BkqlUA0j.js +1 -0
  73. package/dist/web3/assets/page-xzYqkBUP.js +16 -0
  74. package/dist/web3/assets/play-B8xE9j5f.js +6 -0
  75. package/dist/web3/assets/refresh-cw-CsCtmWwX.js +6 -0
  76. package/dist/web3/assets/scroll-area-CbcH6yrZ.js +1 -0
  77. package/dist/web3/assets/scroll-area-dRWncRqa.css +1 -0
  78. package/dist/web3/assets/select-DrL0mpRN.js +6 -0
  79. package/dist/web3/assets/send-CvAgOUPG.js +6 -0
  80. package/dist/web3/assets/settings-EY4A_DYv.js +6 -0
  81. package/dist/web3/assets/share-2-vGmZUl90.js +6 -0
  82. package/dist/web3/assets/tag-Br_y1f00.js +11 -0
  83. package/dist/web3/assets/trash-2-B4hRXo-p.js +6 -0
  84. package/dist/web3/assets/triangle-alert-CsYGyfGZ.js +6 -0
  85. package/dist/web3/assets/user-plus-4CTYEkd3.js +6 -0
  86. package/dist/web3/assets/x-qxt1WrUi.js +6 -0
  87. package/dist/web3/assets/zap-BcsKR0ef.js +16 -0
  88. package/dist/web3/index.html +2 -2
  89. package/package.json +5 -3
  90. package/dist/web3/assets/index-BJ-LRNis.js +0 -1382
  91. package/dist/web3/assets/index-DPMEt-A_.css +0 -1
@@ -49,7 +49,9 @@ var HISTORICAL_MIGRATIONS = [
49
49
  "038_nest_archive",
50
50
  "039_nest_pins",
51
51
  "041_nest_visibility_org",
52
- "042_community_sites"
52
+ "042_community_sites",
53
+ "043_node_suggestion_details",
54
+ "044_client_attribution"
53
55
  ];
54
56
  async function runPostgresMigrations(db) {
55
57
  await db.exec(`
@@ -83,6 +85,7 @@ async function runPostgresMigrations(db) {
83
85
  allow_self_approve INTEGER NOT NULL DEFAULT 0,
84
86
  prime_only_review INTEGER NOT NULL DEFAULT 0,
85
87
  prime_tags TEXT NOT NULL DEFAULT 'prime-document',
88
+ creator_is_reviewer INTEGER NOT NULL DEFAULT 0,
86
89
  shared_teams TEXT NOT NULL DEFAULT '[]',
87
90
  index_synced_at TEXT,
88
91
  reader_mode INTEGER NOT NULL DEFAULT 0,
@@ -231,9 +234,14 @@ async function runPostgresMigrations(db) {
231
234
  CHECK(status IN ('draft', 'pending_review', 'approved', 'published', 'rejected')),
232
235
  change_note TEXT,
233
236
  tags_json TEXT,
237
+ -- Caller attribution (spec \xA79.4, migration 044): which agent/session made
238
+ -- the write that sealed this version. Annotation only \u2014 never hashed,
239
+ -- never authorized from, NULL when the call carried none.
240
+ client_json TEXT,
234
241
  created_at TEXT NOT NULL DEFAULT ${NOW},
235
242
  UNIQUE(nest_id, node_id, version)
236
243
  );
244
+ ALTER TABLE node_versions ADD COLUMN IF NOT EXISTS client_json TEXT;
237
245
  CREATE INDEX IF NOT EXISTS idx_versions_node ON node_versions(nest_id, node_id);
238
246
  -- Migration 034 (SQLite): the /me/drafts lookup \u2014 author + status.
239
247
  CREATE INDEX IF NOT EXISTS idx_versions_author_status
@@ -274,13 +282,26 @@ async function runPostgresMigrations(db) {
274
282
  CREATE INDEX IF NOT EXISTS idx_node_index_folder
275
283
  ON node_index(nest_id, folder);
276
284
 
277
- -- node_suggestions (migration 036). Which documents have an external edit
278
- -- staged \u2014 so the listing's pending badge is a SELECT, not a vault walk.
285
+ -- node_suggestions (migrations 036 + 043). One row per staged external
286
+ -- edit with the suggestion itself \u2014 so the External Edits list and its
287
+ -- badge are a SELECT, not a vault walk, and old vs new is detected_at.
279
288
  CREATE TABLE IF NOT EXISTS node_suggestions (
280
289
  nest_id TEXT NOT NULL REFERENCES nests(id) ON DELETE CASCADE,
281
290
  node_id TEXT NOT NULL,
282
- PRIMARY KEY (nest_id, node_id)
291
+ suggestion_id TEXT NOT NULL,
292
+ source TEXT NOT NULL,
293
+ actor TEXT NOT NULL,
294
+ detected_at TEXT NOT NULL,
295
+ target_hash TEXT NOT NULL,
296
+ proposed_hash TEXT NOT NULL,
297
+ note TEXT,
298
+ created_at TEXT NOT NULL DEFAULT ${NOW},
299
+ PRIMARY KEY (nest_id, node_id, suggestion_id)
283
300
  );
301
+ -- idx_node_suggestions_nest_detected is created after the 043 parity
302
+ -- check below: a pre-043 database already has node_suggestions without
303
+ -- detected_at, so CREATE TABLE IF NOT EXISTS is a no-op and indexing the
304
+ -- column here aborts the whole bootstrap before the rebuild can run.
284
305
 
285
306
  -- sessions (migration 003).
286
307
  CREATE TABLE IF NOT EXISTS sessions (
@@ -413,6 +434,7 @@ async function runPostgresMigrations(db) {
413
434
  -- created before prime shipped still gets the columns on upgrade.
414
435
  ALTER TABLE nests ADD COLUMN IF NOT EXISTS prime_only_review INTEGER NOT NULL DEFAULT 0;
415
436
  ALTER TABLE nests ADD COLUMN IF NOT EXISTS prime_tags TEXT NOT NULL DEFAULT 'prime-document';
437
+ ALTER TABLE nests ADD COLUMN IF NOT EXISTS creator_is_reviewer INTEGER NOT NULL DEFAULT 0;
416
438
 
417
439
  -- node_index freshness stamp: same inline-plus-explicit-ALTER pattern. The
418
440
  -- inline declaration only reaches a database created after it shipped, and
@@ -585,8 +607,10 @@ async function runPostgresMigrations(db) {
585
607
  user_id TEXT,
586
608
  user_email TEXT,
587
609
  status INTEGER, -- HTTP status (api + mcp rows)
588
- duration_ms INTEGER
610
+ duration_ms INTEGER,
611
+ client_json TEXT -- caller attribution (\xA79.4, migration 044)
589
612
  );
613
+ ALTER TABLE api_events ADD COLUMN IF NOT EXISTS client_json TEXT;
590
614
  CREATE INDEX IF NOT EXISTS idx_api_events_ts ON api_events(ts);
591
615
  -- (nest_id, id) composite (migration 026): the per-nest trace view
592
616
  -- (GET /nests/:id/trace) filters by nest_id and pages newest-first by id.
@@ -725,6 +749,33 @@ async function runPostgresMigrations(db) {
725
749
  "ALTER TABLE nests ADD CONSTRAINT nests_visibility_check CHECK (visibility IN ('private', 'org', 'public'))"
726
750
  );
727
751
  }
752
+ const suggestionIdCol = await db.get(
753
+ `SELECT 1 AS ok FROM information_schema.columns
754
+ WHERE table_name = 'node_suggestions' AND column_name = 'suggestion_id'`
755
+ );
756
+ if (!suggestionIdCol?.ok) {
757
+ await db.exec(`
758
+ DROP TABLE IF EXISTS node_suggestions;
759
+ CREATE TABLE node_suggestions (
760
+ nest_id TEXT NOT NULL REFERENCES nests(id) ON DELETE CASCADE,
761
+ node_id TEXT NOT NULL,
762
+ suggestion_id TEXT NOT NULL,
763
+ source TEXT NOT NULL,
764
+ actor TEXT NOT NULL,
765
+ detected_at TEXT NOT NULL,
766
+ target_hash TEXT NOT NULL,
767
+ proposed_hash TEXT NOT NULL,
768
+ note TEXT,
769
+ created_at TEXT NOT NULL DEFAULT ${NOW},
770
+ PRIMARY KEY (nest_id, node_id, suggestion_id)
771
+ );
772
+ UPDATE nests SET index_synced_at = NULL;
773
+ `);
774
+ }
775
+ await db.exec(`
776
+ CREATE INDEX IF NOT EXISTS idx_node_suggestions_nest_detected
777
+ ON node_suggestions(nest_id, detected_at DESC);
778
+ `);
728
779
  await db.run(
729
780
  "UPDATE nests SET visibility = 'public' WHERE user_id = ? AND visibility = 'private'",
730
781
  [ANON_USER_ID]
@@ -17,15 +17,15 @@ import {
17
17
  requestDeletion,
18
18
  submitForReview,
19
19
  withdrawDeletionRequest
20
- } from "./chunk-MLQU4I5J.js";
20
+ } from "./chunk-DTLMBF4W.js";
21
21
  import {
22
22
  canUserApprove
23
- } from "./chunk-2YPY2HGZ.js";
24
- import "./chunk-UOMW7TT6.js";
25
- import "./chunk-5CVZMHHB.js";
26
- import "./chunk-QLXC6542.js";
27
- import "./chunk-YVMSM7LS.js";
28
- import "./chunk-QWNXWRWO.js";
23
+ } from "./chunk-2KHM5C7V.js";
24
+ import "./chunk-KPGNZLZL.js";
25
+ import "./chunk-TI7HMP64.js";
26
+ import "./chunk-7FROMOZM.js";
27
+ import "./chunk-LHWOJPFE.js";
28
+ import "./chunk-JDAOA5KP.js";
29
29
  import "./chunk-YB3LKF7U.js";
30
30
  import "./chunk-FRQJWGN3.js";
31
31
  export {
@@ -20,13 +20,14 @@ import {
20
20
  resolveStewardsWithFallback,
21
21
  resolveUserRoles,
22
22
  stewardCoverageForUser,
23
+ stewardDocumentCreator,
23
24
  syncFromConfig,
24
25
  updateSteward,
25
26
  updateStewardRole
26
- } from "./chunk-2YPY2HGZ.js";
27
- import "./chunk-QLXC6542.js";
28
- import "./chunk-YVMSM7LS.js";
29
- import "./chunk-QWNXWRWO.js";
27
+ } from "./chunk-2KHM5C7V.js";
28
+ import "./chunk-7FROMOZM.js";
29
+ import "./chunk-LHWOJPFE.js";
30
+ import "./chunk-JDAOA5KP.js";
30
31
  import "./chunk-YB3LKF7U.js";
31
32
  import "./chunk-FRQJWGN3.js";
32
33
  export {
@@ -51,6 +52,7 @@ export {
51
52
  resolveStewardsWithFallback,
52
53
  resolveUserRoles,
53
54
  stewardCoverageForUser,
55
+ stewardDocumentCreator,
54
56
  syncFromConfig,
55
57
  updateSteward,
56
58
  updateStewardRole
@@ -20,10 +20,10 @@ import {
20
20
  setApprovedVersion,
21
21
  systemAuthor,
22
22
  upsertVersion
23
- } from "./chunk-5CVZMHHB.js";
24
- import "./chunk-QLXC6542.js";
25
- import "./chunk-YVMSM7LS.js";
26
- import "./chunk-QWNXWRWO.js";
23
+ } from "./chunk-TI7HMP64.js";
24
+ import "./chunk-7FROMOZM.js";
25
+ import "./chunk-LHWOJPFE.js";
26
+ import "./chunk-JDAOA5KP.js";
27
27
  import "./chunk-YB3LKF7U.js";
28
28
  import "./chunk-FRQJWGN3.js";
29
29
  export {
@@ -0,0 +1 @@
1
+ import{r as s,dD as z,dE as D,j as e,B as m,dF as F,bw as _,I as q,L as K,bx as M}from"./index-B5hLclEq.js";import{P as U}from"./page-title-BkqlUA0j.js";import{S as B,a as V,b as $,c as G,d as p}from"./select-DrL0mpRN.js";import{f as Z}from"./dates-BCxbm4_q.js";import{f as y}from"./client-attribution-BraarYaP.js";import{A as H}from"./arrow-left-BAgIocLn.js";import{R as I}from"./refresh-cw-CsCtmWwX.js";import{C as J}from"./chevron-left-XR4ReJ9Z.js";const i=25;function ae({onBack:f,nestId:a}){const[g,C]=s.useState([]),[o,k]=s.useState(0),[l,h]=s.useState(0),[n,N]=s.useState(!0),[v,w]=s.useState(null),[c,E]=s.useState("all"),[d,T]=s.useState(""),[u,b]=s.useState(""),x=s.useRef(0);s.useEffect(()=>{const t=setTimeout(()=>b(d),300);return()=>clearTimeout(t)},[d]),s.useEffect(()=>{h(0)},[c,u]);const j=s.useCallback(async()=>{const t=++x.current;N(!0),w(null);try{const r={kind:c==="all"?void 0:c,user:u.trim()||void 0,limit:i,offset:l*i},S=a?await z(a,r):await D(r);if(t!==x.current)return;C(S.events),k(S.total)}catch(r){if(t!==x.current)return;w((r==null?void 0:r.message)||"Failed to load trace")}finally{t===x.current&&N(!1)}},[c,u,l,a]);s.useEffect(()=>{j()},[j]);const A=o===0?0:l*i+1,P=Math.min((l+1)*i,o),R=l>0,L=(l+1)*i<o;return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-start gap-2",children:[f&&e.jsxs(m,{variant:"ghost",size:"sm",onClick:f,className:"mt-1",children:[e.jsx(H,{className:"h-4 w-4 mr-1"})," Back"]}),e.jsx(U,{icon:F,title:"Activity trace",className:"mb-0 flex-1",actions:e.jsxs(e.Fragment,{children:[e.jsxs(B,{value:c,onValueChange:t=>E(t),children:[e.jsx(V,{className:"h-8 w-28",children:e.jsx($,{})}),e.jsxs(G,{children:[e.jsx(p,{value:"all",children:"All"}),e.jsx(p,{value:"api",children:"API"}),e.jsx(p,{value:"mcp",children:"MCP"})]})]}),e.jsxs("div",{className:"relative",children:[e.jsx(_,{className:"absolute left-2.5 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground pointer-events-none"}),e.jsx(q,{value:d,onChange:t=>T(t.target.value),onKeyDown:t=>t.key==="Enter"&&b(d),placeholder:"Filter by user…",className:"h-8 pl-8 w-48"})]}),e.jsx(m,{variant:"outline",size:"sm",onClick:j,disabled:n,children:n?e.jsx(K,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(I,{className:"h-3.5 w-3.5"})})]})})]}),v&&e.jsx("p",{className:"text-sm text-red-500",children:v}),e.jsx("div",{className:"border border-border rounded-lg overflow-x-auto",children:e.jsxs("table",{className:"w-full text-xs",children:[e.jsx("thead",{className:"bg-muted/50 text-muted-foreground",children:e.jsxs("tr",{className:"[&>th]:px-3 [&>th]:py-2 [&>th]:text-left [&>th]:font-medium",children:[e.jsx("th",{children:"Time"}),e.jsx("th",{children:"Kind"}),e.jsx("th",{children:"Call"}),!a&&e.jsx("th",{children:"Nest"}),e.jsx("th",{children:"Caller"}),e.jsx("th",{children:"Status"}),e.jsx("th",{className:"text-right",children:"ms"})]})}),e.jsxs("tbody",{children:[g.length===0&&!n&&e.jsx("tr",{children:e.jsx("td",{colSpan:a?6:7,className:"px-3 py-8 text-center text-muted-foreground",children:"No activity recorded yet."})}),g.map(t=>e.jsxs("tr",{className:"border-t border-border [&>td]:px-3 [&>td]:py-1.5",children:[e.jsx("td",{className:"whitespace-nowrap text-muted-foreground",children:Z(t.ts)}),e.jsx("td",{children:e.jsx("span",{className:t.kind==="mcp"?"rounded bg-violet-50 text-violet-700 px-1.5 py-0.5":"rounded bg-blue-50 text-blue-700 px-1.5 py-0.5",children:t.kind})}),e.jsx("td",{className:"font-mono max-w-[340px] truncate",title:t.path||t.tool||"",children:t.kind==="mcp"?t.tool:`${t.method} ${t.path}`}),!a&&e.jsx("td",{className:"font-mono max-w-[120px] truncate",title:t.nest_id||"",children:t.nest_id||"—"}),e.jsxs("td",{className:"max-w-[180px] truncate",title:t.caller||"",children:[t.caller||"—",t.client&&e.jsx("div",{className:"text-[11px] text-muted-foreground truncate font-mono",title:y(t.client),children:y(t.client)})]}),e.jsx("td",{children:t.status==null?"—":e.jsx("span",{className:t.status>=400?"text-red-600":"text-green-700",children:t.status})}),e.jsx("td",{className:"text-right text-muted-foreground",children:t.duration_ms??"—"})]},t.id))]})]})}),e.jsxs("div",{className:"flex flex-wrap items-center justify-between gap-2 text-xs text-muted-foreground",children:[e.jsx("span",{children:"Rolling retention window (server setting), newest first."}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs("span",{children:[A,"–",P," of ",o]}),e.jsx(m,{variant:"outline",size:"sm",className:"h-7 px-2",disabled:!R||n,onClick:()=>h(t=>Math.max(t-1,0)),children:e.jsx(J,{className:"h-3.5 w-3.5"})}),e.jsx(m,{variant:"outline",size:"sm",className:"h-7 px-2",disabled:!L||n,onClick:()=>h(t=>t+1),children:e.jsx(M,{className:"h-3.5 w-3.5"})})]})]})]})}export{ae as ActivityTracePage};
@@ -0,0 +1 @@
1
+ import{r as o,j as e,aE as m,v as c,aF as x,aG as u,L as h}from"./index-B5hLclEq.js";import{P as p}from"./page-title-BkqlUA0j.js";import{C as f}from"./code-xml-pPQgdctI.js";import{M as g,r as j}from"./index-A0_ymcqL.js";const w=[[x,"Connect an MCP client","Claude Code, Cursor, VS Code or Claude Desktop talk to a nest directly. See “MCP” below."],[f,"Call the REST API","Every read is deterministic: same selector, same context. See “Deterministic retrieval API” below."],[u,"Use the ctx CLI","Query a hosted nest from a terminal or a script. See “From the ctx CLI” below."]];function v({onOpenGuide:n}){const[r,l]=o.useState(null),[a,i]=o.useState(null);return o.useEffect(()=>{let s=!1;return fetch("/llms.txt").then(t=>{if(!t.ok)throw new Error(`Failed to load manual (${t.status})`);return t.text()}).then(t=>!s&&l(t)).catch(t=>!s&&i((t==null?void 0:t.message)||"Failed to load")),()=>{s=!0}},[]),e.jsxs("div",{className:"w-full space-y-6",children:[e.jsx(p,{icon:m,title:"Docs",description:"How agents talk to this server: keys, endpoints, MCP tools and the CLI.",className:"mb-0",actions:e.jsxs("a",{href:"/llms.txt",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground",children:["Raw llms.txt (for agents)",e.jsx(c,{className:"h-3 w-3"})]})}),e.jsxs("div",{className:"rounded-lg border-l-2 border-primary bg-muted/40 p-4 text-sm text-muted-foreground",children:["This is the manual an agent reads when you point it at"," ",e.jsx("code",{className:"rounded bg-muted px-1 py-0.5 text-xs",children:"/llms.txt"}),". It documents shapes, never data. Looking for how to use the app yourself?"," ",e.jsx("button",{type:"button",onClick:n,className:"font-medium text-foreground underline underline-offset-2",children:"Start with How it works"}),"."]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-3",children:w.map(([s,t,d])=>e.jsxs("div",{className:"rounded-lg border bg-card p-3",children:[e.jsxs("div",{className:"mb-1 flex items-center gap-2 text-sm font-semibold",children:[e.jsx(s,{className:"h-4 w-4 text-primary"}),t]}),e.jsx("p",{className:"text-xs leading-relaxed text-muted-foreground",children:d})]},t))}),a&&e.jsx("p",{className:"text-sm text-red-500",children:a}),!r&&!a&&e.jsxs("div",{className:"flex items-center justify-center py-16 text-muted-foreground",children:[e.jsx(h,{className:"h-5 w-5 animate-spin mr-2"})," Loading docs…"]}),r&&e.jsx("article",{className:"prose prose-sm dark:prose-invert max-w-none",children:e.jsx(g,{remarkPlugins:[j],children:r})})]})}export{v as AgentDocsPage};
@@ -0,0 +1 @@
1
+ import{r as n,O as ve,u as de,W as ge,j as e,J as M,ah as fe,ai as be,L as z,a9 as te,aa as ie,ab as le,aj as je,ak as ye,am as we,C as Ne,bC as Ce,a8 as Se,bQ as Ae,A as Te,K as De,a as ke,U as ne,B as A,e as _,i as E,N as Pe,f as re,bB as Fe,dM as Re,M as Le,dN as Me,dO as ze}from"./index-B5hLclEq.js";import{S as X,a as Z,b as ee,c as se,d as O}from"./select-DrL0mpRN.js";import{A as Oe,a as Be,b as Ue,c as Ve,d as $e,e as qe,f as Qe,g as We}from"./alert-dialog-4SiLKlz8.js";import{T as He}from"./scroll-area-CbcH6yrZ.js";import{x as Ie,w as ce,y as Ke,S as Ye}from"./MarkdownEditor-Dfk5uIE5.js";import{P as _e}from"./PersonCombobox-D350WlrJ.js";import{U as Ee}from"./user-plus-4CTYEkd3.js";import{S as Ge}from"./share-2-vGmZUl90.js";import{T as oe}from"./trash-2-B4hRXo-p.js";const G=[{value:"private",label:"Private"},{value:"org",label:"Organization"},{value:"public",label:"Public"}];function ns({nestId:d,onChanged:B,onError:l,variant:W="card"}){var S,V,$,q;const[x,p]=n.useState("private"),v=x==="public",f=x==="org",[N,U]=n.useState(!1),[g,b]=n.useState(null),{sharedDeployment:T}=ve(),j={sharedDeployment:T},D=de(),[C,k]=n.useState(""),P=ge(d),y=(V=(S=P.data)==null?void 0:S.nest)==null?void 0:V.visibility,w=((q=($=P.data)==null?void 0:$.nest)==null?void 0:q.description)??"";n.useEffect(()=>{y&&p(y)},[y]);const F=async(a,h)=>{const u=x;p(a),U(!0),l==null||l(null);try{const i=await Ae(d,a,h);if(p(i.visibility||a),i.visibility!==a){l==null||l("Server did not accept the change. You may not have admin access to this nest.");return}B()}catch(i){p(u),l==null||l((i==null?void 0:i.message)||"Failed to change visibility")}finally{U(!1)}},R=async a=>{if(a!==x){if(a!=="private"&&Ke(a,j)){k(w),b(a);return}await F(a)}},c=async()=>{const a=g;if(!a)return;b(null);const h=C.trim();if(h&&h!==w.trim())try{await Ce(d,{description:h}),D.invalidateQueries({queryKey:Se.nest(d)})}catch(u){l==null||l((u==null?void 0:u.message)||"Failed to save the description")}await F(a,!0)},o=g?Ie(g,j):null,L=e.jsx(Oe,{open:g!==null,onOpenChange:a=>{a||b(null)},children:e.jsxs(Be,{children:[e.jsxs(Ue,{children:[e.jsx(Ve,{children:o==null?void 0:o.title}),e.jsx($e,{children:o==null?void 0:o.body})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(M,{htmlFor:"visibility-description",className:"text-xs",children:w.trim()?"Description readers will see":"This nest has no description — readers will only see its name. Add one? (optional)"}),e.jsx(He,{id:"visibility-description",value:C,onChange:a=>k(a.target.value),placeholder:"What this nest is for, and who it's meant for",rows:2,"data-testid":"visibility-description"})]}),e.jsxs(qe,{children:[e.jsx(Qe,{children:"Cancel"}),e.jsx(We,{onClick:()=>void c(),"data-testid":"visibility-confirm",children:o==null?void 0:o.confirm})]})]})});if(W==="compact"){if(!y)return null;const a=v?te:f?ie:le,h=G.find(i=>i.value===x)??G[0],u=ce(x,j);return e.jsxs(e.Fragment,{children:[e.jsxs(fe,{children:[e.jsx(be,{asChild:!0,children:e.jsxs("button",{type:"button",disabled:N,className:"inline-flex h-8 items-center gap-1 rounded-md px-2 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground disabled:opacity-60",title:`${h.label} — ${u}. Click to change.`,"aria-label":`Nest visibility: ${h.label}`,"data-testid":"nest-visibility-compact",children:[N?e.jsx(z,{className:"h-3.5 w-3.5 animate-spin"}):e.jsx(a,{className:`h-3.5 w-3.5 ${v?"text-green-600":f?"text-blue-600":""}`}),e.jsx("span",{className:"hidden sm:inline",children:h.label}),e.jsx(je,{className:"h-3 w-3 opacity-60"})]})}),e.jsx(ye,{align:"end",className:"w-64",children:G.map(i=>e.jsxs(we,{onClick:()=>void R(i.value),className:"flex items-start gap-2",children:[i.value===x?e.jsx(Ne,{className:"mt-0.5 h-4 w-4 shrink-0"}):e.jsx("span",{className:"w-4 shrink-0"}),e.jsxs("span",{className:"flex flex-col",children:[e.jsx("span",{className:"text-sm",children:i.label}),e.jsx("span",{className:"text-xs text-muted-foreground",children:ce(i.value,j)})]})]},i.value))})]}),L]})}return e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-4",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsxs(M,{className:"flex items-center gap-2 text-sm font-medium",children:[v?e.jsx(te,{className:"h-4 w-4 text-green-600"}):f?e.jsx(ie,{className:"h-4 w-4 text-blue-600"}):e.jsx(le,{className:"h-4 w-4"}),v?"Public":f?"Organization":"Private"]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:v?T?"Anyone on the internet with the URL can read this nest — including every account on this server, other organizations too. Editing still requires being added below.":"Anyone on the internet with the URL can read this nest. Editing still requires being added below.":f?T?"Every account on this server can read this nest — other organizations included, not just yours. Editing still requires being added below.":"Everyone signed in to this deployment can read this nest. Editing still requires being added below.":"Only people added below (and the owner) can see this nest."})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[N&&e.jsx(z,{className:"h-3.5 w-3.5 animate-spin text-muted-foreground"}),e.jsxs(X,{value:x,onValueChange:a=>void R(a),disabled:N,children:[e.jsx(Z,{className:"h-8 w-[150px]","aria-label":"Nest visibility",children:e.jsx(ee,{})}),e.jsxs(se,{children:[e.jsx(O,{value:"private",children:"Private"}),e.jsx(O,{value:"org",children:"Organization"}),e.jsx(O,{value:"public",children:"Public"})]})]})]})]}),L]})}const J=[{value:"read",label:"Viewer",hint:"Read only"},{value:"write",label:"Editor",hint:"Read and edit documents"},{value:"admin",label:"Admin",hint:"Full access except deleting the nest"}],Q={read:1,write:2,admin:3,owner:4};function rs({nestId:d,nestName:B,onChanged:l,currentUserEmail:W,callerPermission:x="admin",showTeams:p=!1}){const v=(W||"").toLowerCase(),f=Q[x]??Q.read,N=f>=Q.admin,U=J.filter(s=>Q[s.value]<=f),[g,b]=n.useState([]),[T,j]=n.useState(!0),D=de(),[C,k]=n.useState(""),[P,y]=n.useState("read"),[w,F]=n.useState(!1),[R,c]=n.useState(null),[o,L]=n.useState("person"),[S,V]=n.useState([]),[$,q]=n.useState([]),[a,h]=n.useState(""),[u,i]=n.useState(!1),H=async()=>{j(!0);try{const{collaborators:s}=await D.fetchQuery(E.collaborators(d));b(s)}catch(s){c((s==null?void 0:s.message)||"Failed to load collaborators")}finally{j(!1)}},I=async()=>{try{const[s,r]=await Promise.all([D.fetchQuery(E.nestTeams(d)),D.fetchQuery(E.teamList()).catch(()=>({teams:[]}))]);V(s.teams),q(r.teams)}catch(s){c((s==null?void 0:s.message)||"Failed to load teams")}};n.useEffect(()=>{H(),p&&I()},[d]);const ae=async()=>{const s=C.trim();if(s){if(!Fe(s)){c("Enter a valid email address.");return}F(!0),c(null);try{await Re(d,{email:s,permission:P}),k(""),y("read"),await H(),l()}catch(r){c((r==null?void 0:r.message)||"Failed to add collaborator")}finally{F(!1)}}},me=s=>{s.preventDefault(),ae()},K=$.filter(s=>!S.some(r=>r.teamId===s.id)),he=async()=>{if(a){i(!0),c(null);try{await Pe(d,a),h(""),re.success("Team shared"),await I(),l()}catch(s){c((s==null?void 0:s.message)||"Failed to share team")}finally{i(!1)}}},ue=async(s,r)=>{if(window.confirm(`Unshare "${r}" from "${B}"? Its members lose the access this share granted.`)){i(!0),c(null);try{await Le(d,s),await I(),l()}catch(m){c((m==null?void 0:m.message)||"Failed to unshare team")}finally{i(!1)}}},xe=async(s,r)=>{const t=g.find(m=>m.id===s);if(t&&(t.email||"").toLowerCase()===v){re.error("You can't change your own access level.");return}c(null),b(m=>m.map(Y=>Y.id===s?{...Y,permission:r}:Y));try{await Me(d,s,r),l()}catch(m){c((m==null?void 0:m.message)||"Failed to update permission"),await H()}},pe=async s=>{if(window.confirm(`Remove ${s.email||"this collaborator"}'s access to "${B}"? They keep their account; only their access to this nest is revoked.`)){c(null);try{await ze(d,s.id),b(t=>t.filter(m=>m.id!==s.id)),l()}catch(t){c((t==null?void 0:t.message)||"Failed to remove collaborator")}}};return e.jsxs("div",{className:"space-y-4",children:[R&&e.jsxs(Te,{variant:"destructive",children:[e.jsx(De,{className:"h-4 w-4"}),e.jsx(ke,{children:R})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx(M,{className:"flex items-center gap-2 text-sm font-medium",children:p&&o==="team"?e.jsxs(e.Fragment,{children:[e.jsx(ne,{className:"h-4 w-4"}),"Add a team"]}):e.jsxs(e.Fragment,{children:[e.jsx(Ee,{className:"h-4 w-4"}),"Add a person"]})}),p&&e.jsxs("div",{className:"flex gap-1",children:[e.jsx(A,{type:"button",size:"sm",variant:o==="person"?"secondary":"ghost",className:"h-7 px-2 text-xs",onClick:()=>L("person"),children:"Person"}),e.jsx(A,{type:"button",size:"sm",variant:o==="team"?"secondary":"ghost",className:"h-7 px-2 text-xs",onClick:()=>L("team"),children:"Team"})]})]}),p&&o==="team"?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx("div",{className:"flex-1",children:e.jsx(Ye,{value:a,onChange:h,options:K.map(s=>({value:s.id,label:s.name})),disabled:K.length===0,placeholder:K.length===0?"No teams available to share":"Select a team…",searchPlaceholder:"Search teams…",emptyText:"No teams match.",testId:"collab-team-select"})}),e.jsx(A,{onClick:he,disabled:u||!a,children:u?e.jsx(z,{className:"h-4 w-4 animate-spin"}):e.jsxs(e.Fragment,{children:[e.jsx(Ge,{className:"h-4 w-4 mr-1"}),"Share"]})})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"Every member gets the role you gave them on the Teams page. Manage members there."})]}):e.jsxs("form",{onSubmit:me,className:"space-y-3",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row gap-2",children:[e.jsx(_e,{value:C,onChange:k,onSubmit:ae,placeholder:"teammate@example.com",disabled:w,className:"flex-1",exclude:g.map(s=>s.email||"").filter(Boolean),testId:"collab-person-input"}),e.jsxs(X,{value:P,onValueChange:s=>y(s),children:[e.jsx(Z,{className:"w-full sm:w-[130px]",children:e.jsx(ee,{})}),e.jsx(se,{children:U.map(s=>e.jsx(O,{value:s.value,children:s.label},s.value))})]}),e.jsx(A,{type:"submit",disabled:w||!C.trim(),children:w?e.jsx(z,{className:"h-4 w-4 animate-spin"}):"Add"})]}),e.jsx("p",{className:"text-xs text-muted-foreground",children:"If they don't have an account yet, they'll get access when they register with this email."})]})]}),p&&S.length>0&&e.jsxs("div",{className:"rounded-lg border p-4 space-y-2",children:[e.jsxs(M,{className:"text-sm font-medium flex items-center gap-2",children:[e.jsx(ne,{className:"h-4 w-4"}),"Teams with access"]}),e.jsx("div",{className:"space-y-1",children:S.map(s=>e.jsxs("div",{className:"flex items-center gap-2 py-1.5",children:[e.jsx("span",{className:"flex-1 min-w-0 truncate text-sm",children:s.teamName}),e.jsxs(_,{variant:"secondary",className:"text-[11px]",children:[s.members.length," member",s.members.length===1?"":"s"]}),e.jsx(A,{variant:"ghost",size:"sm",disabled:u,onClick:()=>ue(s.teamId,s.teamName),title:"Unshare team",className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:e.jsx(oe,{className:"h-3.5 w-3.5"})})]},s.teamId))})]}),e.jsxs("div",{className:"rounded-lg border p-4 space-y-2",children:[e.jsx(M,{className:"text-sm font-medium",children:"People with access"}),T?e.jsx("div",{className:"flex items-center justify-center py-4",children:e.jsx(z,{className:"h-5 w-5 animate-spin text-muted-foreground"})}):g.length===0?e.jsx("p",{className:"text-xs text-muted-foreground py-2",children:"Nobody's been added yet. The owner always has full access."}):e.jsx("div",{className:"space-y-1",children:g.map(s=>{var r;return e.jsxs("div",{className:"flex items-center gap-2 py-1.5","data-testid":`collaborator-row-${s.id}`,children:[e.jsx("span",{className:"flex-1 min-w-0 truncate text-sm",children:s.email||s.user_id}),(s.stewardRoles??[]).map(t=>e.jsx(_,{variant:"outline",className:"text-[10px] px-1.5 py-0 capitalize",title:"Steward role — manage in the Stewards tab",children:t},t)),N?e.jsxs(e.Fragment,{children:[e.jsxs(X,{value:s.permission,disabled:(s.email||"").toLowerCase()===v,onValueChange:t=>xe(s.id,t),children:[e.jsx(Z,{className:"w-[120px] h-8",title:(s.email||"").toLowerCase()===v?"You can't change your own access level":void 0,children:e.jsx(ee,{})}),e.jsx(se,{children:J.map(t=>e.jsx(O,{value:t.value,children:t.label},t.value))})]}),(s.email||"").toLowerCase()!==v&&e.jsx(A,{variant:"ghost",size:"sm",onClick:()=>pe(s),title:"Remove access",className:"text-destructive hover:text-destructive hover:bg-destructive/10",children:e.jsx(oe,{className:"h-3.5 w-3.5"})})]}):e.jsx(_,{variant:"secondary",className:"text-[11px] capitalize",children:((r=J.find(t=>t.value===s.permission))==null?void 0:r.label)??s.permission})]},s.id)})})]})]})}export{rs as C,ns as N};
@@ -0,0 +1 @@
1
+ import{j as s,f as c}from"./index-B5hLclEq.js";import{N as p,C as h}from"./CollaboratorManager-Bo81D--Q.js";import{C as x,a as f,c as u,b as j,d as b}from"./card-UDyMRcps.js";import"./select-DrL0mpRN.js";import"./alert-dialog-4SiLKlz8.js";import"./scroll-area-CbcH6yrZ.js";import"./MarkdownEditor-Dfk5uIE5.js";import"./zap-BcsKR0ef.js";import"./triangle-alert-CsYGyfGZ.js";import"./index-A0_ymcqL.js";import"./arrow-left-BAgIocLn.js";import"./trash-2-B4hRXo-p.js";import"./x-qxt1WrUi.js";import"./PersonCombobox-D350WlrJ.js";import"./user-plus-4CTYEkd3.js";import"./share-2-vGmZUl90.js";function R({nestId:r,nestName:t,canManage:a,canManageGovernance:i,stewardshipEnabled:n,currentUserEmail:l,callerPermission:m,onOpenSettings:d,onChanged:e}){return s.jsxs(x,{children:[s.jsxs(f,{className:"pb-3",children:[s.jsx(u,{className:"text-lg",children:"Collaborators"}),s.jsxs(j,{className:"space-y-1",children:[s.jsxs("span",{className:"block",children:[s.jsx("strong",{className:"font-medium text-foreground",children:"Who can access this nest"})," ","— visibility and access for people and teams. Sharing grants viewer, editor or admin access."]}),s.jsxs("span",{className:"block",children:[s.jsx("strong",{className:"font-medium text-foreground",children:"Stewardship"})," — sharing does not make anyone a steward.",n?" Stewards are assigned on the Stewards tab.":i?s.jsxs(s.Fragment,{children:[" ","Turn on Stewardship & Approval Workflow in"," ",s.jsx("button",{type:"button",onClick:d,className:"font-medium text-foreground underline underline-offset-2 hover:no-underline",children:"Nest settings"})," ","to use stewards."]}):" Stewardship & Approval Workflow is off for this nest — an owner or admin can turn it on in Nest settings."]})]})]}),s.jsxs(b,{className:"space-y-4",children:[a&&s.jsx(p,{nestId:r,onChanged:e,onError:o=>o&&c.error(o)}),s.jsx(h,{nestId:r,nestName:t,onChanged:e,currentUserEmail:l,callerPermission:m,showTeams:!0})]})]})}export{R as CollaboratorsTab};