wiki-viewer 1.14.1 → 1.14.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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +3 -3
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/agent/activity/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/events/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/files/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/file/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/ls/[[...path]]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/fs/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/internal/span/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/settings/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/agent/sidecar/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/assets/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/[token]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/share/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/reveal/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/set-root/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/open/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/refresh/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/[id]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/system/workspaces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/upload/[...path]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/app/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/backlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/content/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/folder/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-branches/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-checkout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-diff/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-file-info/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-history/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/git-pull/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/move/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/new-file/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/outlinks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/page/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/presence/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/search/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/slugs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/wiki/watch/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +3 -3
- package/.next/standalone/.next/server/middleware-manifest.json +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/package.json +1 -1
- package/bin/postbuild.js +21 -0
- package/package.json +1 -1
- package/.next/standalone/.github/workflows/publish.yml +0 -37
- package/.next/standalone/.handoffs/archive/handoff-20260612-113332.md +0 -98
- package/.next/standalone/.handoffs/archive/handoff-20260612-141032.md +0 -73
- package/.next/standalone/.pi/ownership.json +0 -3
- package/.next/standalone/AGENTS.md +0 -114
- package/.next/standalone/DESIGN.md +0 -521
- package/.next/standalone/README.md +0 -821
- package/.next/standalone/TODO.md +0 -20
- package/.next/standalone/agents/bootstrap-prompt.md +0 -14
- package/.next/standalone/agents/wiki-viewer-skill/SKILL.md +0 -456
- package/.next/standalone/bin/postbuild.js +0 -78
- package/.next/standalone/bin/wiki-viewer.js +0 -922
- package/.next/standalone/certificates/localhost-key.pem +0 -28
- package/.next/standalone/certificates/localhost.pem +0 -24
- package/.next/standalone/docs/agent-collab-plan.md +0 -1615
- package/.next/standalone/docs/agent-collab-v2-plan.md +0 -771
- package/.next/standalone/docs/agent-fs-plan.md +0 -232
- package/.next/standalone/docs/editorial-skin-spec.md +0 -242
- package/.next/standalone/docs/file-vs-collab-authority.md +0 -124
- package/.next/standalone/docs/mobile-readiness-spec.md +0 -229
- package/.next/standalone/docs/workspacing-plan.md +0 -364
- package/.next/standalone/packages/wiki-viewer-mcp/README.md +0 -195
- package/.next/standalone/packages/wiki-viewer-mcp/bench-e2e.mjs +0 -166
- package/.next/standalone/packages/wiki-viewer-mcp/bench-latency.mjs +0 -87
- package/.next/standalone/packages/wiki-viewer-mcp/bench-payload.mjs +0 -45
- package/.next/standalone/packages/wiki-viewer-mcp/dist/http-client.js +0 -331
- package/.next/standalone/packages/wiki-viewer-mcp/dist/index.js +0 -531
- package/.next/standalone/packages/wiki-viewer-mcp/dist/register.js +0 -94
- package/.next/standalone/packages/wiki-viewer-mcp/dist/state-cache.js +0 -28
- package/.next/standalone/packages/wiki-viewer-mcp/package-lock.json +0 -1716
- package/.next/standalone/packages/wiki-viewer-mcp/package.json +0 -41
- package/.next/standalone/packages/wiki-viewer-mcp/src/http-client.ts +0 -459
- package/.next/standalone/packages/wiki-viewer-mcp/src/index.ts +0 -638
- package/.next/standalone/packages/wiki-viewer-mcp/src/register.ts +0 -144
- package/.next/standalone/packages/wiki-viewer-mcp/src/state-cache.ts +0 -55
- package/.next/standalone/packages/wiki-viewer-mcp/tsconfig.json +0 -19
- package/.next/standalone/pnpm-lock.yaml +0 -6697
- package/.next/standalone/pnpm-workspace.yaml +0 -8
- package/.next/standalone/postcss.config.mjs +0 -2
- package/.next/standalone/src/app/api/agent/activity/route.ts +0 -59
- package/.next/standalone/src/app/api/agent/admin/agents/[agentId]/revoke/route.ts +0 -40
- package/.next/standalone/src/app/api/agent/admin/agents/route.ts +0 -33
- package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/approve/route.ts +0 -83
- package/.next/standalone/src/app/api/agent/admin/registrations/[regId]/deny/route.ts +0 -36
- package/.next/standalone/src/app/api/agent/admin/registrations/route.ts +0 -27
- package/.next/standalone/src/app/api/agent/events/[...path]/route.ts +0 -148
- package/.next/standalone/src/app/api/agent/files/[...path]/route.ts +0 -219
- package/.next/standalone/src/app/api/agent/fs/file/[...path]/route.ts +0 -446
- package/.next/standalone/src/app/api/agent/fs/ls/[[...path]]/route.ts +0 -152
- package/.next/standalone/src/app/api/agent/fs/move/route.ts +0 -130
- package/.next/standalone/src/app/api/agent/fs/search/route.ts +0 -272
- package/.next/standalone/src/app/api/agent/internal/span/route.ts +0 -121
- package/.next/standalone/src/app/api/agent/register/[regId]/route.ts +0 -50
- package/.next/standalone/src/app/api/agent/register/route.ts +0 -118
- package/.next/standalone/src/app/api/agent/settings/route.ts +0 -34
- package/.next/standalone/src/app/api/agent/settings/token/regenerate/route.ts +0 -20
- package/.next/standalone/src/app/api/agent/sidecar/[...path]/route.ts +0 -53
- package/.next/standalone/src/app/api/agents/install/route.ts +0 -143
- package/.next/standalone/src/app/api/agents/skill/route.ts +0 -20
- package/.next/standalone/src/app/api/agents/skill.tar.gz/route.ts +0 -87
- package/.next/standalone/src/app/api/app-proxy/[...path]/route.ts +0 -247
- package/.next/standalone/src/app/api/assets/[...path]/route.ts +0 -75
- package/.next/standalone/src/app/api/auth/[...all]/route.ts +0 -7
- package/.next/standalone/src/app/api/owner/init/route.ts +0 -14
- package/.next/standalone/src/app/api/share/[token]/route.ts +0 -269
- package/.next/standalone/src/app/api/share/route.ts +0 -127
- package/.next/standalone/src/app/api/system/admins/route.ts +0 -103
- package/.next/standalone/src/app/api/system/auth-config/route.ts +0 -22
- package/.next/standalone/src/app/api/system/auth-settings/route.ts +0 -86
- package/.next/standalone/src/app/api/system/browse/route.ts +0 -82
- package/.next/standalone/src/app/api/system/clear-root/route.ts +0 -16
- package/.next/standalone/src/app/api/system/config/route.ts +0 -14
- package/.next/standalone/src/app/api/system/pins/route.ts +0 -38
- package/.next/standalone/src/app/api/system/reveal/route.ts +0 -36
- package/.next/standalone/src/app/api/system/root-status/route.ts +0 -13
- package/.next/standalone/src/app/api/system/set-root/route.ts +0 -53
- package/.next/standalone/src/app/api/system/users/route.ts +0 -120
- package/.next/standalone/src/app/api/system/workspaces/[id]/open/route.ts +0 -34
- package/.next/standalone/src/app/api/system/workspaces/[id]/refresh/route.ts +0 -32
- package/.next/standalone/src/app/api/system/workspaces/[id]/route.ts +0 -78
- package/.next/standalone/src/app/api/system/workspaces/route.ts +0 -128
- package/.next/standalone/src/app/api/upload/[...path]/route.ts +0 -85
- package/.next/standalone/src/app/api/wiki/app/route.ts +0 -60
- package/.next/standalone/src/app/api/wiki/backlinks/route.ts +0 -29
- package/.next/standalone/src/app/api/wiki/content/route.ts +0 -159
- package/.next/standalone/src/app/api/wiki/download/route.ts +0 -100
- package/.next/standalone/src/app/api/wiki/file/route.ts +0 -57
- package/.next/standalone/src/app/api/wiki/folder/route.ts +0 -34
- package/.next/standalone/src/app/api/wiki/git-branches/route.ts +0 -32
- package/.next/standalone/src/app/api/wiki/git-checkout/route.ts +0 -45
- package/.next/standalone/src/app/api/wiki/git-diff/route.ts +0 -33
- package/.next/standalone/src/app/api/wiki/git-file-info/route.ts +0 -27
- package/.next/standalone/src/app/api/wiki/git-history/route.ts +0 -27
- package/.next/standalone/src/app/api/wiki/git-pull/route.ts +0 -48
- package/.next/standalone/src/app/api/wiki/move/route.ts +0 -61
- package/.next/standalone/src/app/api/wiki/new-file/route.ts +0 -56
- package/.next/standalone/src/app/api/wiki/outlinks/route.ts +0 -76
- package/.next/standalone/src/app/api/wiki/page/route.ts +0 -92
- package/.next/standalone/src/app/api/wiki/presence/route.ts +0 -56
- package/.next/standalone/src/app/api/wiki/route.ts +0 -116
- package/.next/standalone/src/app/api/wiki/search/route.ts +0 -44
- package/.next/standalone/src/app/api/wiki/slugs/route.ts +0 -54
- package/.next/standalone/src/app/api/wiki/upload/route.ts +0 -95
- package/.next/standalone/src/app/api/wiki/watch/route.ts +0 -67
- package/.next/standalone/src/app/globals.css +0 -1249
- package/.next/standalone/src/app/icon.svg +0 -11
- package/.next/standalone/src/app/layout.tsx +0 -78
- package/.next/standalone/src/app/manifest.ts +0 -30
- package/.next/standalone/src/app/page.tsx +0 -3260
- package/.next/standalone/src/app/s/[token]/page.tsx +0 -357
- package/.next/standalone/src/app/signin/page.tsx +0 -16
- package/.next/standalone/src/app/signin/signin-form.tsx +0 -238
- package/.next/standalone/src/components/ai-panel/activity-row.tsx +0 -284
- package/.next/standalone/src/components/ai-panel/ai-panel.tsx +0 -311
- package/.next/standalone/src/components/ai-panel/token-section.tsx +0 -313
- package/.next/standalone/src/components/auth-settings-sheet.tsx +0 -474
- package/.next/standalone/src/components/confirm-dialog.tsx +0 -56
- package/.next/standalone/src/components/dir-picker.tsx +0 -606
- package/.next/standalone/src/components/editor/backlinks-panel.tsx +0 -139
- package/.next/standalone/src/components/editor/bubble-menu.tsx +0 -346
- package/.next/standalone/src/components/editor/callout-extension.ts +0 -36
- package/.next/standalone/src/components/editor/comment-pip.tsx +0 -56
- package/.next/standalone/src/components/editor/comment-thread.tsx +0 -254
- package/.next/standalone/src/components/editor/csv-viewer.tsx +0 -379
- package/.next/standalone/src/components/editor/document-outline.tsx +0 -230
- package/.next/standalone/src/components/editor/editor-toolbar.tsx +0 -564
- package/.next/standalone/src/components/editor/editor.tsx +0 -1327
- package/.next/standalone/src/components/editor/extensions/drag-handle.ts +0 -325
- package/.next/standalone/src/components/editor/extensions/heading-anchors.ts +0 -55
- package/.next/standalone/src/components/editor/extensions/proof-span.ts +0 -60
- package/.next/standalone/src/components/editor/extensions/resizable-image.tsx +0 -159
- package/.next/standalone/src/components/editor/extensions.ts +0 -150
- package/.next/standalone/src/components/editor/file-fallback-viewer.tsx +0 -75
- package/.next/standalone/src/components/editor/folder-index.tsx +0 -236
- package/.next/standalone/src/components/editor/google-doc-viewer.tsx +0 -73
- package/.next/standalone/src/components/editor/image-viewer.tsx +0 -57
- package/.next/standalone/src/components/editor/large-file-gate.tsx +0 -108
- package/.next/standalone/src/components/editor/link-popover.tsx +0 -111
- package/.next/standalone/src/components/editor/media-popover.tsx +0 -212
- package/.next/standalone/src/components/editor/media-viewer.tsx +0 -70
- package/.next/standalone/src/components/editor/mermaid-viewer.tsx +0 -286
- package/.next/standalone/src/components/editor/node-app-viewer.tsx +0 -328
- package/.next/standalone/src/components/editor/notebook-viewer.tsx +0 -371
- package/.next/standalone/src/components/editor/office/docx-viewer.tsx +0 -93
- package/.next/standalone/src/components/editor/office/office-chrome.tsx +0 -83
- package/.next/standalone/src/components/editor/office/pptx-viewer.tsx +0 -104
- package/.next/standalone/src/components/editor/office/xlsx-viewer.tsx +0 -192
- package/.next/standalone/src/components/editor/pdf-viewer.tsx +0 -32
- package/.next/standalone/src/components/editor/proof-span-popover.tsx +0 -162
- package/.next/standalone/src/components/editor/slash-commands.tsx +0 -629
- package/.next/standalone/src/components/editor/source-viewer.tsx +0 -289
- package/.next/standalone/src/components/editor/suggest-edit-popover.tsx +0 -229
- package/.next/standalone/src/components/editor/suggestion-card.tsx +0 -206
- package/.next/standalone/src/components/editor/table-menu.tsx +0 -232
- package/.next/standalone/src/components/editor/view-mode-comment-button.tsx +0 -77
- package/.next/standalone/src/components/editor/website-viewer.tsx +0 -75
- package/.next/standalone/src/components/editor/wiki-link-create-dialog.tsx +0 -189
- package/.next/standalone/src/components/editor/wiki-link-decorator.ts +0 -79
- package/.next/standalone/src/components/editor/wiki-link-extension.ts +0 -120
- package/.next/standalone/src/components/editor/wiki-link-picker.tsx +0 -250
- package/.next/standalone/src/components/layout/viewer-toolbar.tsx +0 -54
- package/.next/standalone/src/components/search/search-command-dialog.tsx +0 -246
- package/.next/standalone/src/components/search/sidebar-search-box.tsx +0 -121
- package/.next/standalone/src/components/search/snippet-text.tsx +0 -48
- package/.next/standalone/src/components/share-dialog.tsx +0 -307
- package/.next/standalone/src/components/theme-provider.tsx +0 -16
- package/.next/standalone/src/components/theme-toggle.tsx +0 -24
- package/.next/standalone/src/components/ui/badge.tsx +0 -35
- package/.next/standalone/src/components/ui/button.tsx +0 -56
- package/.next/standalone/src/components/ui/card.tsx +0 -63
- package/.next/standalone/src/components/ui/collapsible.tsx +0 -9
- package/.next/standalone/src/components/ui/command.tsx +0 -151
- package/.next/standalone/src/components/ui/context-menu.tsx +0 -191
- package/.next/standalone/src/components/ui/dialog.tsx +0 -119
- package/.next/standalone/src/components/ui/dropdown-menu.tsx +0 -194
- package/.next/standalone/src/components/ui/input.tsx +0 -22
- package/.next/standalone/src/components/ui/label.tsx +0 -25
- package/.next/standalone/src/components/ui/popover.tsx +0 -33
- package/.next/standalone/src/components/ui/scroll-area.tsx +0 -47
- package/.next/standalone/src/components/ui/select.tsx +0 -156
- package/.next/standalone/src/components/ui/separator.tsx +0 -30
- package/.next/standalone/src/components/ui/sheet.tsx +0 -140
- package/.next/standalone/src/components/ui/skeleton.tsx +0 -15
- package/.next/standalone/src/components/ui/switch.tsx +0 -28
- package/.next/standalone/src/components/ui/tabs.tsx +0 -54
- package/.next/standalone/src/components/ui/textarea.tsx +0 -21
- package/.next/standalone/src/components/ui/tip.tsx +0 -23
- package/.next/standalone/src/components/ui/toggle-group.tsx +0 -41
- package/.next/standalone/src/components/ui/tooltip.tsx +0 -27
- package/.next/standalone/src/components/view-width-toggle.tsx +0 -70
- package/.next/standalone/src/components/wiki/frontmatter-header.tsx +0 -164
- package/.next/standalone/src/hooks/use-is-mobile.ts +0 -14
- package/.next/standalone/src/lib/app-runner.ts +0 -272
- package/.next/standalone/src/lib/auth/admin.ts +0 -120
- package/.next/standalone/src/lib/auth/allowlist.ts +0 -50
- package/.next/standalone/src/lib/auth/client.ts +0 -4
- package/.next/standalone/src/lib/auth/csrf.ts +0 -68
- package/.next/standalone/src/lib/auth/server.ts +0 -215
- package/.next/standalone/src/lib/cabinets/tree.ts +0 -75
- package/.next/standalone/src/lib/config.ts +0 -114
- package/.next/standalone/src/lib/embeds/detect.ts +0 -142
- package/.next/standalone/src/lib/git-secrets.ts +0 -65
- package/.next/standalone/src/lib/git.ts +0 -503
- package/.next/standalone/src/lib/google/detect.ts +0 -107
- package/.next/standalone/src/lib/markdown/parse-frontmatter.ts +0 -104
- package/.next/standalone/src/lib/markdown/remark-wikilinks.ts +0 -100
- package/.next/standalone/src/lib/markdown/sanitize-schema.ts +0 -106
- package/.next/standalone/src/lib/markdown/to-html.ts +0 -282
- package/.next/standalone/src/lib/markdown/to-markdown.ts +0 -252
- package/.next/standalone/src/lib/proof/activity-shared.ts +0 -31
- package/.next/standalone/src/lib/proof/activity.ts +0 -74
- package/.next/standalone/src/lib/proof/audit.ts +0 -88
- package/.next/standalone/src/lib/proof/auth.ts +0 -143
- package/.next/standalone/src/lib/proof/block-refs.ts +0 -133
- package/.next/standalone/src/lib/proof/blocks.ts +0 -73
- package/.next/standalone/src/lib/proof/client-auth.ts +0 -23
- package/.next/standalone/src/lib/proof/collab-state.ts +0 -81
- package/.next/standalone/src/lib/proof/event-bus.ts +0 -47
- package/.next/standalone/src/lib/proof/file-lock.ts +0 -43
- package/.next/standalone/src/lib/proof/glob.ts +0 -51
- package/.next/standalone/src/lib/proof/idempotency.ts +0 -37
- package/.next/standalone/src/lib/proof/lease.ts +0 -117
- package/.next/standalone/src/lib/proof/mutex.ts +0 -36
- package/.next/standalone/src/lib/proof/ops-applier.ts +0 -727
- package/.next/standalone/src/lib/proof/owner-auth.ts +0 -2
- package/.next/standalone/src/lib/proof/pending.ts +0 -97
- package/.next/standalone/src/lib/proof/proof-span.ts +0 -141
- package/.next/standalone/src/lib/proof/rate-limit.ts +0 -53
- package/.next/standalone/src/lib/proof/raw-fs.ts +0 -197
- package/.next/standalone/src/lib/proof/register-rate-limit.ts +0 -53
- package/.next/standalone/src/lib/proof/registry.ts +0 -195
- package/.next/standalone/src/lib/proof/sidecar.ts +0 -103
- package/.next/standalone/src/lib/proof/suggest-capture.ts +0 -69
- package/.next/standalone/src/lib/proof/types.ts +0 -182
- package/.next/standalone/src/lib/proof-config.ts +0 -14
- package/.next/standalone/src/lib/root-dir.ts +0 -35
- package/.next/standalone/src/lib/search/indexable-exts.ts +0 -25
- package/.next/standalone/src/lib/search/indexer.ts +0 -634
- package/.next/standalone/src/lib/search/sanitize.ts +0 -35
- package/.next/standalone/src/lib/search/search-db.ts +0 -57
- package/.next/standalone/src/lib/search/watcher-pool.ts +0 -79
- package/.next/standalone/src/lib/shared-docs/db.ts +0 -177
- package/.next/standalone/src/lib/toast.ts +0 -9
- package/.next/standalone/src/lib/utils.ts +0 -6
- package/.next/standalone/src/lib/wiki-helpers.ts +0 -36
- package/.next/standalone/src/lib/workspace-client.ts +0 -82
- package/.next/standalone/src/lib/workspace-context.ts +0 -173
- package/.next/standalone/src/lib/workspaces.ts +0 -400
- package/.next/standalone/src/middleware.ts +0 -44
- package/.next/standalone/src/stores/ai-panel-store.ts +0 -79
- package/.next/standalone/src/stores/editor-store.ts +0 -439
- package/.next/standalone/src/stores/pin-store.ts +0 -56
- package/.next/standalone/src/stores/proof-store.ts +0 -124
- package/.next/standalone/src/stores/recent-store.ts +0 -51
- package/.next/standalone/src/stores/search-store.ts +0 -104
- package/.next/standalone/src/stores/show-hidden-store.ts +0 -26
- package/.next/standalone/src/stores/sidebar-width-store.ts +0 -39
- package/.next/standalone/src/stores/skin-store.ts +0 -42
- package/.next/standalone/src/stores/tree-store.ts +0 -52
- package/.next/standalone/src/stores/view-width-store.ts +0 -101
- package/.next/standalone/src/stores/wiki-slugs-store.ts +0 -75
- package/.next/standalone/src/tests/proof/activity-aggregator.test.ts +0 -146
- package/.next/standalone/src/tests/proof/admin-create-user.test.ts +0 -43
- package/.next/standalone/src/tests/proof/agent-fs.test.ts +0 -973
- package/.next/standalone/src/tests/proof/agent-ownership.test.ts +0 -140
- package/.next/standalone/src/tests/proof/agent-workspace-scope.test.ts +0 -134
- package/.next/standalone/src/tests/proof/agents-install.test.ts +0 -110
- package/.next/standalone/src/tests/proof/bench-write.ts +0 -179
- package/.next/standalone/src/tests/proof/better-auth.test.ts +0 -68
- package/.next/standalone/src/tests/proof/block-refs.test.ts +0 -108
- package/.next/standalone/src/tests/proof/blocks.test.ts +0 -92
- package/.next/standalone/src/tests/proof/collab-state.test.ts +0 -501
- package/.next/standalone/src/tests/proof/comments-ops.test.ts +0 -177
- package/.next/standalone/src/tests/proof/editor-roundtrip.test.ts +0 -85
- package/.next/standalone/src/tests/proof/external-edit.test.ts +0 -58
- package/.next/standalone/src/tests/proof/file-lock.test.ts +0 -80
- package/.next/standalone/src/tests/proof/git-branches-checkout.test.ts +0 -136
- package/.next/standalone/src/tests/proof/git-read-features.test.ts +0 -473
- package/.next/standalone/src/tests/proof/git-secrets.test.ts +0 -138
- package/.next/standalone/src/tests/proof/git-sparse.test.ts +0 -257
- package/.next/standalone/src/tests/proof/git-workspace.test.ts +0 -135
- package/.next/standalone/src/tests/proof/git.test.ts +0 -243
- package/.next/standalone/src/tests/proof/glob.test.ts +0 -82
- package/.next/standalone/src/tests/proof/helpers/auth-session.ts +0 -27
- package/.next/standalone/src/tests/proof/markdown-to-html.test.ts +0 -46
- package/.next/standalone/src/tests/proof/ops-applier.test.ts +0 -368
- package/.next/standalone/src/tests/proof/owner-init.test.ts +0 -2
- package/.next/standalone/src/tests/proof/parse-frontmatter.test.ts +0 -60
- package/.next/standalone/src/tests/proof/preload.ts +0 -21
- package/.next/standalone/src/tests/proof/proof-span.test.ts +0 -98
- package/.next/standalone/src/tests/proof/rate-limit.test.ts +0 -54
- package/.next/standalone/src/tests/proof/readonly-enforcement.test.ts +0 -161
- package/.next/standalone/src/tests/proof/reconcile-sidecar.test.ts +0 -195
- package/.next/standalone/src/tests/proof/registration-flow.test.ts +0 -330
- package/.next/standalone/src/tests/proof/registry.test.ts +0 -169
- package/.next/standalone/src/tests/proof/routes.test.ts +0 -516
- package/.next/standalone/src/tests/proof/search-index.test.ts +0 -376
- package/.next/standalone/src/tests/proof/sidecar-lifecycle.test.ts +0 -177
- package/.next/standalone/src/tests/proof/sidecar-trim.test.ts +0 -58
- package/.next/standalone/src/tests/proof/suggestion-ops.test.ts +0 -280
- package/.next/standalone/src/tests/proof/wiki-content-put.test.ts +0 -140
- package/.next/standalone/src/tests/proof/wiki-routes-auth.test.ts +0 -208
- package/.next/standalone/src/tests/proof/workspace-isolation.test.ts +0 -87
- package/.next/standalone/src/tests/proof/workspaces-api.test.ts +0 -227
- package/.next/standalone/src/types/index.ts +0 -47
- package/.next/standalone/tailwind.config.ts +0 -191
- package/.next/standalone/tsconfig.json +0 -41
- package/.next/standalone/tsconfig.tsbuildinfo +0 -1
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{WMOTgfV82apmdovxzgbMx → rRyvFORvJoc5OWbCR2A_P}/_ssgManifest.js +0 -0
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { checkAuth, enforceScope } from "@/lib/proof/auth";
|
|
3
|
-
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
4
|
-
import {
|
|
5
|
-
aggregateActivity,
|
|
6
|
-
ACTIVITY_DEFAULT_LIMIT,
|
|
7
|
-
ACTIVITY_MAX_LIMIT,
|
|
8
|
-
} from "@/lib/proof/activity";
|
|
9
|
-
import { matchGlob } from "@/lib/proof/glob";
|
|
10
|
-
|
|
11
|
-
export const runtime = "nodejs";
|
|
12
|
-
|
|
13
|
-
export async function GET(req: Request): Promise<NextResponse> {
|
|
14
|
-
const auth = await checkAuth(req);
|
|
15
|
-
if (!auth.ok) {
|
|
16
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const wsx = await resolveWorkspaceForAgent(req);
|
|
20
|
-
if (!wsx.ok) {
|
|
21
|
-
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
22
|
-
}
|
|
23
|
-
const { ws, rootDir } = wsx;
|
|
24
|
-
|
|
25
|
-
const scopeCheck = enforceScope(auth.agent, { op: "read", workspaceId: ws.id });
|
|
26
|
-
if (!scopeCheck.ok) {
|
|
27
|
-
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const url = new URL(req.url);
|
|
31
|
-
const rawLimit = url.searchParams.get("limit");
|
|
32
|
-
const fileFilter = url.searchParams.get("file") ?? undefined;
|
|
33
|
-
|
|
34
|
-
// Enforce scope on explicit file query parameter
|
|
35
|
-
if (fileFilter) {
|
|
36
|
-
const fileScope = enforceScope(auth.agent, { filePath: fileFilter, op: "read", workspaceId: ws.id });
|
|
37
|
-
if (!fileScope.ok) {
|
|
38
|
-
return NextResponse.json({ error: fileScope.code, message: fileScope.message }, { status: 403 });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
let limit = ACTIVITY_DEFAULT_LIMIT;
|
|
43
|
-
if (rawLimit !== null) {
|
|
44
|
-
const parsed = parseInt(rawLimit, 10);
|
|
45
|
-
if (!isNaN(parsed) && parsed > 0) {
|
|
46
|
-
limit = Math.min(parsed, ACTIVITY_MAX_LIMIT);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const events = await aggregateActivity(rootDir, { limit, file: fileFilter });
|
|
51
|
-
|
|
52
|
-
// Post-aggregation filter: drop events whose path falls outside agent scope
|
|
53
|
-
const scopedPaths = auth.agent.scope.paths;
|
|
54
|
-
const filtered = events.filter((ev) =>
|
|
55
|
-
scopedPaths.some((pattern) => matchGlob(pattern, ev.path)),
|
|
56
|
-
);
|
|
57
|
-
|
|
58
|
-
return NextResponse.json({ events: filtered, count: filtered.length });
|
|
59
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/agent/admin/agents/:agentId/revoke
|
|
3
|
-
*
|
|
4
|
-
* Revoke (remove) a registered agent. Requires authenticated user session.
|
|
5
|
-
*/
|
|
6
|
-
import { NextResponse } from "next/server";
|
|
7
|
-
import { requireUser } from "@/lib/auth/server";
|
|
8
|
-
import { readRegistry, removeAgent } from "@/lib/proof/registry";
|
|
9
|
-
|
|
10
|
-
export const runtime = "nodejs";
|
|
11
|
-
|
|
12
|
-
export async function POST(
|
|
13
|
-
req: Request,
|
|
14
|
-
{ params }: { params: Promise<{ agentId: string }> },
|
|
15
|
-
): Promise<NextResponse> {
|
|
16
|
-
const owner = await requireUser(req);
|
|
17
|
-
if (!owner.ok) {
|
|
18
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { agentId } = await params;
|
|
22
|
-
|
|
23
|
-
// Check ownership before removal. Legacy agents (no ownerUserId) are
|
|
24
|
-
// revocable by any authenticated user.
|
|
25
|
-
const registry = await readRegistry();
|
|
26
|
-
const agent = (registry?.agents ?? []).find((a) => a.id === agentId);
|
|
27
|
-
if (!agent) {
|
|
28
|
-
return NextResponse.json({ error: "NOT_FOUND", message: "Agent not found" }, { status: 404 });
|
|
29
|
-
}
|
|
30
|
-
if (agent.ownerUserId !== undefined && agent.ownerUserId !== owner.user.id) {
|
|
31
|
-
return NextResponse.json({ error: "FORBIDDEN", message: "You do not own this agent" }, { status: 403 });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const removed = await removeAgent(agentId);
|
|
35
|
-
if (!removed) {
|
|
36
|
-
return NextResponse.json({ error: "NOT_FOUND", message: "Agent not found" }, { status: 404 });
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
return NextResponse.json({ ok: true });
|
|
40
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GET /api/agent/admin/agents
|
|
3
|
-
*
|
|
4
|
-
* List registered agents (no token hashes). Requires authenticated user session.
|
|
5
|
-
*/
|
|
6
|
-
import { NextResponse } from "next/server";
|
|
7
|
-
import { requireUser } from "@/lib/auth/server";
|
|
8
|
-
import { readRegistry } from "@/lib/proof/registry";
|
|
9
|
-
|
|
10
|
-
export const runtime = "nodejs";
|
|
11
|
-
|
|
12
|
-
export async function GET(req: Request): Promise<NextResponse> {
|
|
13
|
-
const owner = await requireUser(req);
|
|
14
|
-
if (!owner.ok) {
|
|
15
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const registry = await readRegistry();
|
|
19
|
-
// Show agents owned by this user. Legacy agents (no ownerUserId) are visible
|
|
20
|
-
// to all authenticated users for back-compat.
|
|
21
|
-
const agents = (registry?.agents ?? [])
|
|
22
|
-
.filter((a) => a.ownerUserId === undefined || a.ownerUserId === owner.user.id)
|
|
23
|
-
.map((a) => ({
|
|
24
|
-
id: a.id,
|
|
25
|
-
displayName: a.displayName,
|
|
26
|
-
scope: a.scope,
|
|
27
|
-
createdAt: a.createdAt,
|
|
28
|
-
lastSeen: a.lastSeen,
|
|
29
|
-
ownerUserId: a.ownerUserId,
|
|
30
|
-
}));
|
|
31
|
-
|
|
32
|
-
return NextResponse.json({ agents });
|
|
33
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/agent/admin/registrations/:regId/approve
|
|
3
|
-
*
|
|
4
|
-
* Approve a pending registration. Mints a token, stores agent, marks for pickup.
|
|
5
|
-
* Requires authenticated user session.
|
|
6
|
-
*
|
|
7
|
-
* Body (optional): { scope?: AgentScope } — override requested scope.
|
|
8
|
-
*/
|
|
9
|
-
import { randomBytes } from "node:crypto";
|
|
10
|
-
import { NextResponse } from "next/server";
|
|
11
|
-
import { requireUser } from "@/lib/auth/server";
|
|
12
|
-
import { getRegistration, approveRegistration } from "@/lib/proof/pending";
|
|
13
|
-
import { addAgent, hashToken } from "@/lib/proof/registry";
|
|
14
|
-
import type { AgentScope } from "@/lib/proof/registry";
|
|
15
|
-
import { validateScope } from "@/app/api/agent/register/route";
|
|
16
|
-
|
|
17
|
-
export const runtime = "nodejs";
|
|
18
|
-
|
|
19
|
-
export async function POST(
|
|
20
|
-
req: Request,
|
|
21
|
-
{ params }: { params: Promise<{ regId: string }> },
|
|
22
|
-
): Promise<NextResponse> {
|
|
23
|
-
const owner = await requireUser(req);
|
|
24
|
-
if (!owner.ok) {
|
|
25
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const { regId } = await params;
|
|
29
|
-
const reg = getRegistration(regId);
|
|
30
|
-
if (!reg) {
|
|
31
|
-
return NextResponse.json({ error: "NOT_FOUND", message: "Registration not found" }, { status: 404 });
|
|
32
|
-
}
|
|
33
|
-
if (reg.status !== "pending") {
|
|
34
|
-
return NextResponse.json(
|
|
35
|
-
{ error: "CONFLICT", message: `Registration is already ${reg.status}` },
|
|
36
|
-
{ status: 409 },
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Optional scope override — validate if present
|
|
41
|
-
let scope: AgentScope = reg.requestedScope;
|
|
42
|
-
try {
|
|
43
|
-
const body = (await req.json()) as { scope?: unknown };
|
|
44
|
-
if (body.scope !== undefined && body.scope !== null) {
|
|
45
|
-
if (typeof body.scope !== "object" || Array.isArray(body.scope)) {
|
|
46
|
-
return NextResponse.json(
|
|
47
|
-
{ error: "INVALID_PAYLOAD", message: "scope must be an object" },
|
|
48
|
-
{ status: 400 },
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
const result = validateScope(body.scope as Record<string, unknown>);
|
|
52
|
-
if ("error" in result) {
|
|
53
|
-
return NextResponse.json(
|
|
54
|
-
{ error: "INVALID_PAYLOAD", message: result.error },
|
|
55
|
-
{ status: 400 },
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
scope = result;
|
|
59
|
-
}
|
|
60
|
-
} catch {
|
|
61
|
-
// No body or invalid JSON — use requestedScope
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// Mint token
|
|
65
|
-
const tokenPlaintext = randomBytes(32).toString("hex");
|
|
66
|
-
const tokenHash = hashToken(tokenPlaintext);
|
|
67
|
-
|
|
68
|
-
// Store agent in registry, bound to the approving user.
|
|
69
|
-
await addAgent({
|
|
70
|
-
id: reg.agentId,
|
|
71
|
-
displayName: reg.displayName,
|
|
72
|
-
tokenHash,
|
|
73
|
-
scope,
|
|
74
|
-
createdAt: new Date().toISOString(),
|
|
75
|
-
lastSeen: new Date().toISOString(),
|
|
76
|
-
ownerUserId: owner.user.id,
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
// Mark as approved with one-shot pickup token
|
|
80
|
-
approveRegistration(regId, tokenPlaintext);
|
|
81
|
-
|
|
82
|
-
return NextResponse.json({ ok: true, agentId: reg.agentId });
|
|
83
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* POST /api/agent/admin/registrations/:regId/deny
|
|
3
|
-
*
|
|
4
|
-
* Deny a pending registration. Requires authenticated user session.
|
|
5
|
-
*/
|
|
6
|
-
import { NextResponse } from "next/server";
|
|
7
|
-
import { requireUser } from "@/lib/auth/server";
|
|
8
|
-
import { getRegistration, denyRegistration } from "@/lib/proof/pending";
|
|
9
|
-
|
|
10
|
-
export const runtime = "nodejs";
|
|
11
|
-
|
|
12
|
-
export async function POST(
|
|
13
|
-
req: Request,
|
|
14
|
-
{ params }: { params: Promise<{ regId: string }> },
|
|
15
|
-
): Promise<NextResponse> {
|
|
16
|
-
const owner = await requireUser(req);
|
|
17
|
-
if (!owner.ok) {
|
|
18
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const { regId } = await params;
|
|
22
|
-
const reg = getRegistration(regId);
|
|
23
|
-
if (!reg) {
|
|
24
|
-
return NextResponse.json({ error: "NOT_FOUND", message: "Registration not found" }, { status: 404 });
|
|
25
|
-
}
|
|
26
|
-
if (reg.status !== "pending") {
|
|
27
|
-
return NextResponse.json(
|
|
28
|
-
{ error: "CONFLICT", message: `Registration is already ${reg.status}` },
|
|
29
|
-
{ status: 409 },
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
denyRegistration(regId);
|
|
34
|
-
|
|
35
|
-
return NextResponse.json({ ok: true });
|
|
36
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GET /api/agent/admin/registrations
|
|
3
|
-
*
|
|
4
|
-
* List pending registrations. Requires authenticated user session.
|
|
5
|
-
*/
|
|
6
|
-
import { NextResponse } from "next/server";
|
|
7
|
-
import { requireUser } from "@/lib/auth/server";
|
|
8
|
-
import { listPendingRegistrations } from "@/lib/proof/pending";
|
|
9
|
-
|
|
10
|
-
export const runtime = "nodejs";
|
|
11
|
-
|
|
12
|
-
export async function GET(req: Request): Promise<NextResponse> {
|
|
13
|
-
const owner = await requireUser(req);
|
|
14
|
-
if (!owner.ok) {
|
|
15
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const pending = listPendingRegistrations().map((r) => ({
|
|
19
|
-
registrationId: r.registrationId,
|
|
20
|
-
agentId: r.agentId,
|
|
21
|
-
displayName: r.displayName,
|
|
22
|
-
requestedScope: r.requestedScope,
|
|
23
|
-
requestedAt: r.requestedAt,
|
|
24
|
-
}));
|
|
25
|
-
|
|
26
|
-
return NextResponse.json({ pending });
|
|
27
|
-
}
|
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { NextResponse } from "next/server";
|
|
2
|
-
import { checkAuth, enforceScope, verifyBy } from "@/lib/proof/auth";
|
|
3
|
-
import { readSidecar, writeSidecar, emptySidecar } from "@/lib/proof/sidecar";
|
|
4
|
-
import { pollEvents } from "@/lib/proof/event-bus";
|
|
5
|
-
import { withFileMutex } from "@/lib/proof/mutex";
|
|
6
|
-
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
7
|
-
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
8
|
-
|
|
9
|
-
export const runtime = "nodejs";
|
|
10
|
-
|
|
11
|
-
const DEFAULT_LIMIT = 100;
|
|
12
|
-
const MAX_LIMIT = 1000;
|
|
13
|
-
|
|
14
|
-
function isMarkdown(p: string): boolean {
|
|
15
|
-
return p.endsWith(".md") || p.endsWith(".markdown");
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function mdPath(segments: string[]): string {
|
|
19
|
-
return segments.join("/");
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// GET /api/agent/events/<path> — poll events since `after`
|
|
23
|
-
export async function GET(
|
|
24
|
-
req: Request,
|
|
25
|
-
{ params }: { params: Promise<{ path: string[] }> },
|
|
26
|
-
): Promise<NextResponse> {
|
|
27
|
-
const auth = await checkAuth(req);
|
|
28
|
-
if (!auth.ok) {
|
|
29
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const wsx = await resolveWorkspaceForAgent(req);
|
|
33
|
-
if (!wsx.ok) {
|
|
34
|
-
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
35
|
-
}
|
|
36
|
-
const { ws, rootDir } = wsx;
|
|
37
|
-
|
|
38
|
-
const { path: segments } = await params;
|
|
39
|
-
const rel = mdPath(segments);
|
|
40
|
-
|
|
41
|
-
if (rel.startsWith(".proof")) {
|
|
42
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must not be under .proof" }, { status: 400 });
|
|
43
|
-
}
|
|
44
|
-
if (!isMarkdown(rel)) {
|
|
45
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const absPath = safeWorkspacePath(rootDir, rel);
|
|
49
|
-
if (!absPath) {
|
|
50
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read", workspaceId: ws.id });
|
|
54
|
-
if (!scopeCheck.ok) {
|
|
55
|
-
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const { searchParams } = new URL(req.url);
|
|
59
|
-
const afterRaw = searchParams.get("after");
|
|
60
|
-
const limitRaw = searchParams.get("limit");
|
|
61
|
-
|
|
62
|
-
const after = afterRaw !== null ? parseInt(afterRaw, 10) : 0;
|
|
63
|
-
let limit = limitRaw !== null ? parseInt(limitRaw, 10) : DEFAULT_LIMIT;
|
|
64
|
-
|
|
65
|
-
if (Number.isNaN(after) || after < 0) {
|
|
66
|
-
return NextResponse.json({ error: "INVALID_PARAM", message: "after must be a non-negative integer" }, { status: 400 });
|
|
67
|
-
}
|
|
68
|
-
if (Number.isNaN(limit) || limit <= 0) {
|
|
69
|
-
limit = DEFAULT_LIMIT;
|
|
70
|
-
}
|
|
71
|
-
if (limit > MAX_LIMIT) {
|
|
72
|
-
limit = MAX_LIMIT;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const sidecar = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
76
|
-
const events = pollEvents(sidecar, after, limit);
|
|
77
|
-
const lastEventId = sidecar.nextEventId - 1;
|
|
78
|
-
|
|
79
|
-
return NextResponse.json({ events, lastEventId });
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// POST /api/agent/events/<path> — acknowledge events up to upToId
|
|
83
|
-
export async function POST(
|
|
84
|
-
req: Request,
|
|
85
|
-
{ params }: { params: Promise<{ path: string[] }> },
|
|
86
|
-
): Promise<NextResponse> {
|
|
87
|
-
const auth = await checkAuth(req);
|
|
88
|
-
if (!auth.ok) {
|
|
89
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
const wsx = await resolveWorkspaceForAgent(req, "write");
|
|
93
|
-
if (!wsx.ok) {
|
|
94
|
-
return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
95
|
-
}
|
|
96
|
-
const { ws, rootDir } = wsx;
|
|
97
|
-
|
|
98
|
-
const { path: segments } = await params;
|
|
99
|
-
const rel = mdPath(segments);
|
|
100
|
-
|
|
101
|
-
if (rel.startsWith(".proof")) {
|
|
102
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must not be under .proof" }, { status: 400 });
|
|
103
|
-
}
|
|
104
|
-
if (!isMarkdown(rel)) {
|
|
105
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const absPath = safeWorkspacePath(rootDir, rel);
|
|
109
|
-
if (!absPath) {
|
|
110
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate", workspaceId: ws.id });
|
|
114
|
-
if (!scopeCheck.ok) {
|
|
115
|
-
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
let body: { upToId?: unknown; by?: unknown };
|
|
119
|
-
try {
|
|
120
|
-
body = (await req.json()) as { upToId?: unknown; by?: unknown };
|
|
121
|
-
} catch {
|
|
122
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "Invalid JSON" }, { status: 400 });
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (typeof body.upToId !== "number") {
|
|
126
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "upToId (number) required" }, { status: 400 });
|
|
127
|
-
}
|
|
128
|
-
if (typeof body.by !== "string" || !body.by) {
|
|
129
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "by (string) required" }, { status: 400 });
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const byCheck = verifyBy(auth.agent, body.by as string);
|
|
133
|
-
if (!byCheck.ok) {
|
|
134
|
-
return NextResponse.json({ error: byCheck.code, message: byCheck.message }, { status: 403 });
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
const upToId = body.upToId as number;
|
|
138
|
-
const by = body.by as string;
|
|
139
|
-
|
|
140
|
-
// Namespace mutex key with rootDir to prevent cross-workspace lock contention.
|
|
141
|
-
await withFileMutex(`${rootDir}\0${rel}`, async () => {
|
|
142
|
-
const sidecar = (await readSidecar(rootDir, rel)) ?? emptySidecar(rel);
|
|
143
|
-
sidecar.lastAck[by] = upToId;
|
|
144
|
-
await writeSidecar(rootDir, rel, sidecar);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
return NextResponse.json({ ok: true });
|
|
148
|
-
}
|
|
@@ -1,219 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Agent files route — GET snapshot, POST apply-ops.
|
|
3
|
-
*
|
|
4
|
-
* Sample curl (§10 step 1 — read snapshot):
|
|
5
|
-
* curl -H "Authorization: Bearer $AGENT_BEARER_TOKEN" \
|
|
6
|
-
* http://localhost:3000/api/agent/files/notes.md
|
|
7
|
-
*
|
|
8
|
-
* Sample curl (§10 step 2 — apply ops):
|
|
9
|
-
* curl -X POST \
|
|
10
|
-
* -H "Authorization: Bearer $AGENT_BEARER_TOKEN" \
|
|
11
|
-
* -H "Content-Type: application/json" \
|
|
12
|
-
* -H "Idempotency-Key: req-$(uuidgen)" \
|
|
13
|
-
* -d '{"baseRevision":0,"by":"ai:claude","ops":[{"type":"block.append","markdown":"Hello world."}]}' \
|
|
14
|
-
* http://localhost:3000/api/agent/files/notes.md
|
|
15
|
-
*/
|
|
16
|
-
import { createHash } from "node:crypto";
|
|
17
|
-
import { NextResponse } from "next/server";
|
|
18
|
-
import { checkAuth, enforceScope, verifyBy } from "@/lib/proof/auth";
|
|
19
|
-
import { applyOps, readSnapshot } from "@/lib/proof/ops-applier";
|
|
20
|
-
import { idempotency } from "@/lib/proof/idempotency";
|
|
21
|
-
import { resolveWorkspaceForAgent } from "@/lib/workspace-context";
|
|
22
|
-
import { safeWorkspacePath } from "@/lib/workspaces";
|
|
23
|
-
import type { Op } from "@/lib/proof/types";
|
|
24
|
-
import { checkAndConsume } from "@/lib/proof/rate-limit";
|
|
25
|
-
import { computeCollabState } from "@/lib/proof/collab-state";
|
|
26
|
-
|
|
27
|
-
export const runtime = "nodejs";
|
|
28
|
-
|
|
29
|
-
function isMarkdown(p: string): boolean {
|
|
30
|
-
return p.endsWith(".md") || p.endsWith(".markdown");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
function mdPath(segments: string[]): string {
|
|
34
|
-
return segments.join("/");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export async function GET(
|
|
38
|
-
req: Request,
|
|
39
|
-
{ params }: { params: Promise<{ path: string[] }> },
|
|
40
|
-
): Promise<NextResponse> {
|
|
41
|
-
const auth = await checkAuth(req);
|
|
42
|
-
if (!auth.ok) {
|
|
43
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const { path: segments } = await params;
|
|
47
|
-
const rel = mdPath(segments);
|
|
48
|
-
|
|
49
|
-
if (rel.startsWith(".proof")) {
|
|
50
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must not be under .proof" }, { status: 400 });
|
|
51
|
-
}
|
|
52
|
-
if (!isMarkdown(rel)) {
|
|
53
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const wsx = await resolveWorkspaceForAgent(req);
|
|
57
|
-
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
58
|
-
const { ws, rootDir } = wsx;
|
|
59
|
-
|
|
60
|
-
const absPath = safeWorkspacePath(rootDir, rel);
|
|
61
|
-
if (!absPath) {
|
|
62
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "read", workspaceId: ws.id });
|
|
66
|
-
if (!scopeCheck.ok) {
|
|
67
|
-
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
const snapshot = await readSnapshot(rootDir, rel);
|
|
71
|
-
if (!snapshot) {
|
|
72
|
-
return NextResponse.json({ error: "NOT_FOUND", message: "File not found" }, { status: 404 });
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const collab = await computeCollabState(rootDir, rel);
|
|
76
|
-
const collabHeaders: Record<string, string> = {
|
|
77
|
-
"X-Collab-State": collab.state,
|
|
78
|
-
"X-Collab-Revision": String(collab.revision),
|
|
79
|
-
};
|
|
80
|
-
if (collab.snapshotUrl) {
|
|
81
|
-
collabHeaders["X-Collab-Snapshot"] = collab.snapshotUrl;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return NextResponse.json(snapshot, { headers: collabHeaders });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export async function POST(
|
|
88
|
-
req: Request,
|
|
89
|
-
{ params }: { params: Promise<{ path: string[] }> },
|
|
90
|
-
): Promise<NextResponse> {
|
|
91
|
-
const auth = await checkAuth(req);
|
|
92
|
-
if (!auth.ok) {
|
|
93
|
-
return NextResponse.json({ error: "UNAUTHORIZED" }, { status: 401 });
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const idempotencyKey = req.headers.get("idempotency-key");
|
|
97
|
-
if (!idempotencyKey) {
|
|
98
|
-
return NextResponse.json(
|
|
99
|
-
{ error: "MISSING_IDEMPOTENCY_KEY", message: "Idempotency-Key header is required" },
|
|
100
|
-
{ status: 400 },
|
|
101
|
-
);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const { path: segments } = await params;
|
|
105
|
-
const rel = mdPath(segments);
|
|
106
|
-
|
|
107
|
-
if (rel.startsWith(".proof")) {
|
|
108
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must not be under .proof" }, { status: 400 });
|
|
109
|
-
}
|
|
110
|
-
if (!isMarkdown(rel)) {
|
|
111
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path must be .md or .markdown" }, { status: 400 });
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const wsx = await resolveWorkspaceForAgent(req, "write");
|
|
115
|
-
if (!wsx.ok) return NextResponse.json({ error: wsx.code }, { status: wsx.status });
|
|
116
|
-
const { ws, rootDir } = wsx;
|
|
117
|
-
|
|
118
|
-
const absPath = safeWorkspacePath(rootDir, rel);
|
|
119
|
-
if (!absPath) {
|
|
120
|
-
return NextResponse.json({ error: "INVALID_PATH", message: "Path traversal rejected" }, { status: 400 });
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Read body for idempotency hash
|
|
124
|
-
let rawBody: string;
|
|
125
|
-
try {
|
|
126
|
-
rawBody = await req.text();
|
|
127
|
-
} catch {
|
|
128
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "Could not read request body" }, { status: 400 });
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
const payloadHash = createHash("sha256").update(rawBody, "utf8").digest("hex");
|
|
132
|
-
|
|
133
|
-
// Check idempotency cache
|
|
134
|
-
const cached = idempotency.get(`${rootDir}\u0000${idempotencyKey}`);
|
|
135
|
-
if (cached) {
|
|
136
|
-
if (cached.payloadHash !== payloadHash) {
|
|
137
|
-
return NextResponse.json(
|
|
138
|
-
{ error: "IDEMPOTENCY_KEY_REUSED", message: "Same key, different payload" },
|
|
139
|
-
{ status: 409 },
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
return new NextResponse(cached.body, {
|
|
143
|
-
status: cached.status,
|
|
144
|
-
headers: { "Content-Type": "application/json" },
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
let body: { baseRevision?: unknown; by?: unknown; ops?: unknown };
|
|
149
|
-
try {
|
|
150
|
-
body = JSON.parse(rawBody) as { baseRevision?: unknown; by?: unknown; ops?: unknown };
|
|
151
|
-
} catch {
|
|
152
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "Invalid JSON" }, { status: 400 });
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (typeof body.baseRevision !== "number") {
|
|
156
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "baseRevision (number) required" }, { status: 400 });
|
|
157
|
-
}
|
|
158
|
-
if (typeof body.by !== "string" || !body.by) {
|
|
159
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "by (string) required" }, { status: 400 });
|
|
160
|
-
}
|
|
161
|
-
if (!Array.isArray(body.ops)) {
|
|
162
|
-
return NextResponse.json({ error: "INVALID_PAYLOAD", message: "ops (array) required" }, { status: 400 });
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
const scopeCheck = enforceScope(auth.agent, { filePath: rel, op: "mutate", workspaceId: ws.id });
|
|
166
|
-
if (!scopeCheck.ok) {
|
|
167
|
-
return NextResponse.json({ error: scopeCheck.code, message: scopeCheck.message }, { status: 403 });
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
const byCheck = verifyBy(auth.agent, body.by as string);
|
|
171
|
-
if (!byCheck.ok) {
|
|
172
|
-
return NextResponse.json({ error: byCheck.code, message: byCheck.message }, { status: 403 });
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Rate-limit mutations: count ops (all ops are mutations in this route)
|
|
176
|
-
const opCount = (body.ops as Op[]).length || 1;
|
|
177
|
-
const rl = checkAndConsume(body.by as string, opCount);
|
|
178
|
-
if (!rl.ok) {
|
|
179
|
-
const retryAfterSec = Math.ceil(rl.retryAfterMs / 1000);
|
|
180
|
-
return new NextResponse(
|
|
181
|
-
JSON.stringify({ error: "RATE_LIMITED", retryAfterMs: rl.retryAfterMs }),
|
|
182
|
-
{
|
|
183
|
-
status: 429,
|
|
184
|
-
headers: {
|
|
185
|
-
"Content-Type": "application/json",
|
|
186
|
-
"Retry-After": String(retryAfterSec),
|
|
187
|
-
},
|
|
188
|
-
},
|
|
189
|
-
);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
const result = await applyOps({
|
|
193
|
-
rootDir,
|
|
194
|
-
mdPath: rel,
|
|
195
|
-
baseRevision: body.baseRevision as number,
|
|
196
|
-
by: body.by as string,
|
|
197
|
-
ops: body.ops as Op[],
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
let responseBody: string;
|
|
201
|
-
let status: number;
|
|
202
|
-
|
|
203
|
-
if (result.ok) {
|
|
204
|
-
status = 200;
|
|
205
|
-
responseBody = JSON.stringify(result.snapshot);
|
|
206
|
-
} else {
|
|
207
|
-
status = result.status;
|
|
208
|
-
const payload: Record<string, unknown> = { error: result.code, message: result.message };
|
|
209
|
-
if (result.snapshot) payload.snapshot = result.snapshot;
|
|
210
|
-
responseBody = JSON.stringify(payload);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
idempotency.set(`${rootDir}\u0000${idempotencyKey}`, { payloadHash, status, body: responseBody });
|
|
214
|
-
|
|
215
|
-
return new NextResponse(responseBody, {
|
|
216
|
-
status,
|
|
217
|
-
headers: { "Content-Type": "application/json" },
|
|
218
|
-
});
|
|
219
|
-
}
|