@hiai-gg/hiai-docs 0.0.1
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/.all-contributorsrc +18 -0
- package/.claude/settings.local.json +61 -0
- package/.dockerignore +113 -0
- package/.env.example +68 -0
- package/.github/FUNDING.yml +5 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +74 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +78 -0
- package/.github/dependabot.yml +136 -0
- package/.github/pull_request_template.md +96 -0
- package/.github/workflows/ci.yml +283 -0
- package/AGENTS.md +237 -0
- package/CODE_OF_CONDUCT.md +134 -0
- package/CONTRIBUTING.md +77 -0
- package/Caddyfile +50 -0
- package/Dockerfile.backend +60 -0
- package/LICENSE +21 -0
- package/README.md +284 -0
- package/RELEASE_CHECKLIST.md +34 -0
- package/SECURITY.md +60 -0
- package/backend/package.json +43 -0
- package/backend/src/__tests__/auth-helpers.test.ts +51 -0
- package/backend/src/__tests__/chunker.test.ts +65 -0
- package/backend/src/__tests__/config.test.ts +91 -0
- package/backend/src/__tests__/csrf.test.ts +91 -0
- package/backend/src/__tests__/embedding.test.ts +48 -0
- package/backend/src/__tests__/rate-limit.test.ts +46 -0
- package/backend/src/__tests__/routes.test.ts +38 -0
- package/backend/src/__tests__/schema.test.ts +31 -0
- package/backend/src/__tests__/validation.test.ts +556 -0
- package/backend/src/api/middleware/auth.ts +56 -0
- package/backend/src/api/middleware/csrf.ts +91 -0
- package/backend/src/api/middleware/rate-limit.ts +77 -0
- package/backend/src/api/middleware/webhook-verify.ts +22 -0
- package/backend/src/api/routes/attachments.ts +280 -0
- package/backend/src/api/routes/auth.ts +52 -0
- package/backend/src/api/routes/collaboration.ts +121 -0
- package/backend/src/api/routes/documents.ts +664 -0
- package/backend/src/api/routes/folders.ts +226 -0
- package/backend/src/api/routes/search.ts +354 -0
- package/backend/src/api/routes/share.ts +512 -0
- package/backend/src/api/routes/tags.ts +247 -0
- package/backend/src/api/routes/versions.ts +99 -0
- package/backend/src/api/routes/webhooks.ts +43 -0
- package/backend/src/embedding/chunker.ts +74 -0
- package/backend/src/embedding/index.ts +117 -0
- package/backend/src/embedding/providers/ollama.ts +63 -0
- package/backend/src/embedding/providers/openrouter.ts +71 -0
- package/backend/src/embedding/utils.ts +13 -0
- package/backend/src/embedding/worker.ts +89 -0
- package/backend/src/index.ts +147 -0
- package/backend/src/lib/auth-helpers.ts +27 -0
- package/backend/src/lib/auth.ts +35 -0
- package/backend/src/lib/config.ts +73 -0
- package/backend/src/lib/db.ts +7 -0
- package/backend/src/lib/embedding-queue.ts +12 -0
- package/backend/src/lib/logger.ts +18 -0
- package/backend/src/lib/markdown-to-doc.ts +45 -0
- package/backend/src/lib/minio.ts +46 -0
- package/backend/src/lib/redis.ts +19 -0
- package/backend/src/lib/yjs-provider.ts +182 -0
- package/backend/tests/integration/_harness.ts +754 -0
- package/backend/tests/integration/auth.test.ts +296 -0
- package/backend/tests/integration/routes.documents.test.ts +459 -0
- package/backend/tests/integration/routes.folders.test.ts +337 -0
- package/backend/tests/integration/routes.search.test.ts +322 -0
- package/backend/tests/integration/routes.share.test.ts +773 -0
- package/backend/tests/integration/routes.tags.test.ts +425 -0
- package/backend/tests/integration/routes.versions.test.ts +233 -0
- package/backend/tsconfig.json +18 -0
- package/docker-compose.yml +218 -0
- package/docs/API.md +328 -0
- package/docs/ARCHITECTURE.md +75 -0
- package/docs/DEPLOYMENT.md +113 -0
- package/docs/PRODUCTION_STATUS.md +61 -0
- package/docs/openapi.json +385 -0
- package/frontend/.svelte-kit.old/ambient.d.ts +230 -0
- package/frontend/.svelte-kit.old/env.d.ts +1 -0
- package/frontend/.svelte-kit.old/generated/client/app.js +46 -0
- package/frontend/.svelte-kit.old/generated/client/matchers.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/0.js +3 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/1.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/10.js +3 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/2.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/3.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/4.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/5.js +3 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/6.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/7.js +3 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/8.js +1 -0
- package/frontend/.svelte-kit.old/generated/client/nodes/9.js +3 -0
- package/frontend/.svelte-kit.old/generated/root.js +3 -0
- package/frontend/.svelte-kit.old/generated/root.svelte +80 -0
- package/frontend/.svelte-kit.old/generated/server/internal.js +55 -0
- package/frontend/.svelte-kit.old/non-ambient.d.ts +59 -0
- package/frontend/.svelte-kit.old/tsconfig.json +59 -0
- package/frontend/.svelte-kit.old/types/route_meta_data.json +40 -0
- package/frontend/.svelte-kit.old/types/src/routes/$types.d.ts +21 -0
- package/frontend/.svelte-kit.old/types/src/routes/(app)/$types.d.ts +30 -0
- package/frontend/.svelte-kit.old/types/src/routes/(app)/docs/[id]/$types.d.ts +27 -0
- package/frontend/.svelte-kit.old/types/src/routes/(app)/docs/[id]/proxy+page.ts +25 -0
- package/frontend/.svelte-kit.old/types/src/routes/api/[...path]/$types.d.ts +10 -0
- package/frontend/.svelte-kit.old/types/src/routes/folders/[id]/$types.d.ts +27 -0
- package/frontend/.svelte-kit.old/types/src/routes/folders/[id]/proxy+page.ts +15 -0
- package/frontend/.svelte-kit.old/types/src/routes/login/$types.d.ts +17 -0
- package/frontend/.svelte-kit.old/types/src/routes/register/$types.d.ts +17 -0
- package/frontend/.svelte-kit.old/types/src/routes/s/[token]/$types.d.ts +20 -0
- package/frontend/.svelte-kit.old/types/src/routes/s/[token]/proxy+page.ts +6 -0
- package/frontend/.svelte-kit.old/types/src/routes/search/$types.d.ts +19 -0
- package/frontend/.svelte-kit.old/types/src/routes/search/proxy+page.ts +26 -0
- package/frontend/.svelte-kit.old/types/src/routes/settings/$types.d.ts +17 -0
- package/frontend/Dockerfile +44 -0
- package/frontend/biome.json +40 -0
- package/frontend/components.json +18 -0
- package/frontend/messages/en.json +434 -0
- package/frontend/package.json +70 -0
- package/frontend/project.inlang/settings.json +12 -0
- package/frontend/src/app.css +6 -0
- package/frontend/src/app.d.ts +13 -0
- package/frontend/src/app.html +30 -0
- package/frontend/src/hooks.server.ts +10 -0
- package/frontend/src/hooks.ts +10 -0
- package/frontend/src/lib/api/attachments.ts +45 -0
- package/frontend/src/lib/api/client.test.ts +15 -0
- package/frontend/src/lib/api/client.ts +57 -0
- package/frontend/src/lib/api/documents.ts +83 -0
- package/frontend/src/lib/api/folders.ts +180 -0
- package/frontend/src/lib/api/search.test.ts +52 -0
- package/frontend/src/lib/api/search.ts +128 -0
- package/frontend/src/lib/api/settings.ts +95 -0
- package/frontend/src/lib/api/share.ts +71 -0
- package/frontend/src/lib/api/tags.test.ts +91 -0
- package/frontend/src/lib/api/tags.ts +87 -0
- package/frontend/src/lib/auth-client.ts +10 -0
- package/frontend/src/lib/collaboration.ts +63 -0
- package/frontend/src/lib/components/AttachmentUpload.svelte +110 -0
- package/frontend/src/lib/components/DatePicker.svelte +322 -0
- package/frontend/src/lib/components/DocumentCard.svelte +166 -0
- package/frontend/src/lib/components/EmptyState.svelte +49 -0
- package/frontend/src/lib/components/FolderCard.svelte +93 -0
- package/frontend/src/lib/components/ScrollToTop.svelte +72 -0
- package/frontend/src/lib/components/SearchBar.svelte +47 -0
- package/frontend/src/lib/components/SearchResult.svelte +115 -0
- package/frontend/src/lib/components/SettingsDialog.svelte +271 -0
- package/frontend/src/lib/components/ShareDialog.svelte +158 -0
- package/frontend/src/lib/components/ShareLink.svelte +98 -0
- package/frontend/src/lib/components/TagCreateDialog.svelte +284 -0
- package/frontend/src/lib/components/VersionDiff.svelte +55 -0
- package/frontend/src/lib/components/VersionHistory.svelte +96 -0
- package/frontend/src/lib/components/editor/DocumentTitle.svelte +87 -0
- package/frontend/src/lib/components/editor/EditorToolbar.svelte +1367 -0
- package/frontend/src/lib/components/editor/HiAiEditor.svelte +531 -0
- package/frontend/src/lib/components/editor/LinkDialog.svelte +134 -0
- package/frontend/src/lib/components/editor/MarkdownToggle.svelte +88 -0
- package/frontend/src/lib/components/editor/editorExtensions.ts +53 -0
- package/frontend/src/lib/components/editor/markdown.ts +38 -0
- package/frontend/src/lib/components/sidebar/FolderTree.svelte +731 -0
- package/frontend/src/lib/components/sidebar/RecentDocs.svelte +311 -0
- package/frontend/src/lib/components/sidebar/Sidebar.svelte +156 -0
- package/frontend/src/lib/components/sidebar/TagList.svelte +200 -0
- package/frontend/src/lib/components/ui/confirm-dialog/ConfirmDialog.svelte +76 -0
- package/frontend/src/lib/components/ui/confirm-dialog/index.ts +1 -0
- package/frontend/src/lib/stores/tag-store.svelte.ts +56 -0
- package/frontend/src/lib/stores/theme.svelte.ts +97 -0
- package/frontend/src/lib/svelte.d.ts +6 -0
- package/frontend/src/lib/types.ts +44 -0
- package/frontend/src/lib/utils/clipboard.ts +17 -0
- package/frontend/src/lib/utils/strip-markdown.ts +59 -0
- package/frontend/src/lib/utils.ts +33 -0
- package/frontend/src/routes/(app)/+layout.svelte +17 -0
- package/frontend/src/routes/(app)/+page.server.ts +10 -0
- package/frontend/src/routes/(app)/+page.svelte +303 -0
- package/frontend/src/routes/(app)/docs/[id]/+page.server.ts +10 -0
- package/frontend/src/routes/(app)/docs/[id]/+page.svelte +1108 -0
- package/frontend/src/routes/(app)/docs/[id]/+page.ts +24 -0
- package/frontend/src/routes/(app)/search/+page.svelte +593 -0
- package/frontend/src/routes/(app)/search/+page.ts +25 -0
- package/frontend/src/routes/+error.svelte +12 -0
- package/frontend/src/routes/+layout.svelte +18 -0
- package/frontend/src/routes/+layout.ts +2 -0
- package/frontend/src/routes/api/[...path]/+server.ts +111 -0
- package/frontend/src/routes/folders/[id]/+page.server.ts +10 -0
- package/frontend/src/routes/folders/[id]/+page.svelte +319 -0
- package/frontend/src/routes/folders/[id]/+page.ts +14 -0
- package/frontend/src/routes/login/+page.svelte +90 -0
- package/frontend/src/routes/register/+page.svelte +97 -0
- package/frontend/src/routes/s/[token]/+page.svelte +496 -0
- package/frontend/src/routes/s/[token]/+page.ts +5 -0
- package/frontend/src/routes/settings/+page.svelte +175 -0
- package/frontend/static/favicon.png +0 -0
- package/frontend/static/logo.png +0 -0
- package/frontend/svelte.config.js +15 -0
- package/frontend/tsconfig.json +15 -0
- package/frontend/vite.config.ts +25 -0
- package/init.sql +9 -0
- package/logo.png +0 -0
- package/package.json +39 -0
- package/package.public.json +39 -0
- package/packages/db/drizzle.config.ts +10 -0
- package/packages/db/package.json +30 -0
- package/packages/db/src/client.ts +9 -0
- package/packages/db/src/index.ts +2 -0
- package/packages/db/src/migrations/0000_nice_bedlam.sql +165 -0
- package/packages/db/src/migrations/0001_w2_3_test.sql +5 -0
- package/packages/db/src/migrations/0002_rename_content_json.sql +2 -0
- package/packages/db/src/migrations/meta/0000_snapshot.json +1331 -0
- package/packages/db/src/migrations/meta/0001_snapshot.json +1399 -0
- package/packages/db/src/migrations/meta/0002_snapshot.json +1399 -0
- package/packages/db/src/migrations/meta/_journal.json +27 -0
- package/packages/db/src/schema.ts +378 -0
- package/packages/db/tsconfig.json +17 -0
- package/scripts/export-openapi.ts +37 -0
- package/scripts/health-check.sh +75 -0
- package/scripts/migrate.sh +135 -0
- package/scripts/prework_backup.sh +25 -0
- package/scripts/release.sh +83 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# hiai-docs Docker Compose
|
|
2
|
+
# Copy .env.example to .env before running
|
|
3
|
+
|
|
4
|
+
services:
|
|
5
|
+
postgres:
|
|
6
|
+
image: pgvector/pgvector:pg18
|
|
7
|
+
restart: unless-stopped
|
|
8
|
+
ports:
|
|
9
|
+
- "${DB_PORT:-5433}:5432"
|
|
10
|
+
volumes:
|
|
11
|
+
- pgdata:/var/lib/postgresql
|
|
12
|
+
- ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro
|
|
13
|
+
environment:
|
|
14
|
+
POSTGRES_DB: ${DB_NAME:-hiai_docs}
|
|
15
|
+
POSTGRES_USER: ${DB_USER:-aiuser}
|
|
16
|
+
POSTGRES_PASSWORD: ${DB_PASSWORD:-changeme}
|
|
17
|
+
healthcheck:
|
|
18
|
+
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-aiuser} -d ${DB_NAME:-hiai_docs}"]
|
|
19
|
+
interval: 10s
|
|
20
|
+
timeout: 5s
|
|
21
|
+
retries: 5
|
|
22
|
+
networks:
|
|
23
|
+
- hiai-docs-net
|
|
24
|
+
deploy:
|
|
25
|
+
resources:
|
|
26
|
+
limits:
|
|
27
|
+
memory: 2G
|
|
28
|
+
cpus: "2"
|
|
29
|
+
|
|
30
|
+
redis:
|
|
31
|
+
image: redis:8-alpine
|
|
32
|
+
restart: unless-stopped
|
|
33
|
+
ports:
|
|
34
|
+
- "${REDIS_PORT:-6384}:6379"
|
|
35
|
+
volumes:
|
|
36
|
+
- redis_data:/data
|
|
37
|
+
healthcheck:
|
|
38
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
39
|
+
interval: 10s
|
|
40
|
+
timeout: 5s
|
|
41
|
+
retries: 5
|
|
42
|
+
networks:
|
|
43
|
+
- hiai-docs-net
|
|
44
|
+
deploy:
|
|
45
|
+
resources:
|
|
46
|
+
limits:
|
|
47
|
+
memory: 256M
|
|
48
|
+
cpus: "0.5"
|
|
49
|
+
|
|
50
|
+
ollama:
|
|
51
|
+
image: ollama/ollama:0.13.4
|
|
52
|
+
restart: unless-stopped
|
|
53
|
+
# 11435 host: avoids conflict with primary Ollama on 11434
|
|
54
|
+
ports:
|
|
55
|
+
- "11435:11434"
|
|
56
|
+
volumes:
|
|
57
|
+
- ollama_data:/root/.ollama
|
|
58
|
+
healthcheck:
|
|
59
|
+
test: ["CMD", "ollama", "list"]
|
|
60
|
+
interval: 30s
|
|
61
|
+
timeout: 10s
|
|
62
|
+
retries: 3
|
|
63
|
+
start_period: 30s
|
|
64
|
+
networks:
|
|
65
|
+
- hiai-docs-net
|
|
66
|
+
deploy:
|
|
67
|
+
resources:
|
|
68
|
+
limits:
|
|
69
|
+
memory: 2G
|
|
70
|
+
cpus: "2"
|
|
71
|
+
|
|
72
|
+
minio:
|
|
73
|
+
image: minio/minio:RELEASE.2025-06-13T14-19-31Z
|
|
74
|
+
restart: unless-stopped
|
|
75
|
+
# 9021 host: avoids conflict with webs-minio (9001) and ai-shared-minio (9011)
|
|
76
|
+
ports:
|
|
77
|
+
- "9000:9000"
|
|
78
|
+
- "9021:9001"
|
|
79
|
+
volumes:
|
|
80
|
+
- minio_data:/data
|
|
81
|
+
command: server /data --console-address ":9001"
|
|
82
|
+
environment:
|
|
83
|
+
MINIO_ROOT_USER: ${MINIO_ACCESS_KEY:-minioadmin}
|
|
84
|
+
MINIO_ROOT_PASSWORD: ${MINIO_SECRET_KEY:-minioadmin}
|
|
85
|
+
healthcheck:
|
|
86
|
+
test: ["CMD", "mc", "ready", "local"]
|
|
87
|
+
interval: 10s
|
|
88
|
+
timeout: 5s
|
|
89
|
+
retries: 5
|
|
90
|
+
networks:
|
|
91
|
+
- hiai-docs-net
|
|
92
|
+
deploy:
|
|
93
|
+
resources:
|
|
94
|
+
limits:
|
|
95
|
+
memory: 256M
|
|
96
|
+
cpus: "0.5"
|
|
97
|
+
|
|
98
|
+
api:
|
|
99
|
+
build:
|
|
100
|
+
context: .
|
|
101
|
+
dockerfile: Dockerfile.backend
|
|
102
|
+
network: host
|
|
103
|
+
restart: unless-stopped
|
|
104
|
+
ports:
|
|
105
|
+
- "${API_PORT:-50700}:50700"
|
|
106
|
+
depends_on:
|
|
107
|
+
postgres:
|
|
108
|
+
condition: service_healthy
|
|
109
|
+
redis:
|
|
110
|
+
condition: service_healthy
|
|
111
|
+
minio:
|
|
112
|
+
condition: service_healthy
|
|
113
|
+
ollama:
|
|
114
|
+
condition: service_healthy
|
|
115
|
+
healthcheck:
|
|
116
|
+
# $$ escapes compose interpolation so API_PORT is resolved at runtime
|
|
117
|
+
# inside the container (not baked in at compose-parse time).
|
|
118
|
+
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:$${API_PORT}/api/health || exit 1"]
|
|
119
|
+
interval: 15s
|
|
120
|
+
timeout: 5s
|
|
121
|
+
retries: 3
|
|
122
|
+
start_period: 10s
|
|
123
|
+
environment:
|
|
124
|
+
DATABASE_URL: postgresql://${DB_USER:-aiuser}:${DB_PASSWORD:-changeme}@postgres:5432/${DB_NAME:-hiai_docs}
|
|
125
|
+
REDIS_URL: redis://redis:6379
|
|
126
|
+
MINIO_ENDPOINT: minio
|
|
127
|
+
MINIO_PORT: 9000
|
|
128
|
+
MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY:-minioadmin}
|
|
129
|
+
MINIO_SECRET_KEY: ${MINIO_SECRET_KEY:-minioadmin}
|
|
130
|
+
MINIO_BUCKET: ${MINIO_BUCKET:-hiai-docs}
|
|
131
|
+
MINIO_PUBLIC_ENDPOINT: localhost
|
|
132
|
+
MINIO_PUBLIC_PORT: 9000
|
|
133
|
+
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET}
|
|
134
|
+
BETTER_AUTH_URL: ${BETTER_AUTH_URL:-http://localhost:50700}
|
|
135
|
+
CORS_ORIGINS: ${CORS_ORIGINS:-http://localhost:50701,http://127.0.0.1:50701}
|
|
136
|
+
EMBEDDING_PROVIDER: ${EMBEDDING_PROVIDER:-ollama}
|
|
137
|
+
EMBEDDING_MODEL: ${EMBEDDING_MODEL:-nomic-embed-text}
|
|
138
|
+
EMBEDDING_OLLAMA_URL: http://ollama:11434
|
|
139
|
+
EMBEDDING_FALLBACK_PROVIDER: ${EMBEDDING_FALLBACK_PROVIDER:-openrouter}
|
|
140
|
+
EMBEDDING_FALLBACK_MODEL: ${EMBEDDING_FALLBACK_MODEL:-openai/text-embedding-3-small}
|
|
141
|
+
OPENROUTER_API_KEY: ${OPENROUTER_API_KEY}
|
|
142
|
+
API_PORT: ${API_PORT:-50700}
|
|
143
|
+
NODE_ENV: production
|
|
144
|
+
LOG_LEVEL: ${LOG_LEVEL:-info}
|
|
145
|
+
networks:
|
|
146
|
+
- hiai-docs-net
|
|
147
|
+
deploy:
|
|
148
|
+
resources:
|
|
149
|
+
limits:
|
|
150
|
+
memory: 512M
|
|
151
|
+
cpus: "1"
|
|
152
|
+
|
|
153
|
+
web:
|
|
154
|
+
build:
|
|
155
|
+
context: .
|
|
156
|
+
dockerfile: frontend/Dockerfile
|
|
157
|
+
network: host
|
|
158
|
+
restart: unless-stopped
|
|
159
|
+
ports:
|
|
160
|
+
- "${WEB_PORT:-50701}:50701"
|
|
161
|
+
depends_on:
|
|
162
|
+
api:
|
|
163
|
+
condition: service_healthy
|
|
164
|
+
healthcheck:
|
|
165
|
+
# $$ escapes compose interpolation so WEB_PORT is resolved at runtime
|
|
166
|
+
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1:$${WEB_PORT}/ || exit 1"]
|
|
167
|
+
interval: 15s
|
|
168
|
+
timeout: 5s
|
|
169
|
+
retries: 3
|
|
170
|
+
start_period: 10s
|
|
171
|
+
environment:
|
|
172
|
+
API_URL: http://api:${API_PORT:-50700}
|
|
173
|
+
PORT: ${WEB_PORT:-50701}
|
|
174
|
+
WEB_PORT: ${WEB_PORT:-50701}
|
|
175
|
+
networks:
|
|
176
|
+
- hiai-docs-net
|
|
177
|
+
deploy:
|
|
178
|
+
resources:
|
|
179
|
+
limits:
|
|
180
|
+
memory: 512M
|
|
181
|
+
cpus: "1"
|
|
182
|
+
|
|
183
|
+
caddy:
|
|
184
|
+
image: caddy:2-alpine
|
|
185
|
+
restart: unless-stopped
|
|
186
|
+
profiles:
|
|
187
|
+
- caddy
|
|
188
|
+
ports:
|
|
189
|
+
- "50708:80"
|
|
190
|
+
- "50709:443"
|
|
191
|
+
depends_on:
|
|
192
|
+
api:
|
|
193
|
+
condition: service_healthy
|
|
194
|
+
web:
|
|
195
|
+
condition: service_healthy
|
|
196
|
+
volumes:
|
|
197
|
+
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
198
|
+
- caddy_data:/data
|
|
199
|
+
- caddy_config:/config
|
|
200
|
+
networks:
|
|
201
|
+
- hiai-docs-net
|
|
202
|
+
deploy:
|
|
203
|
+
resources:
|
|
204
|
+
limits:
|
|
205
|
+
memory: 256M
|
|
206
|
+
cpus: "0.5"
|
|
207
|
+
|
|
208
|
+
networks:
|
|
209
|
+
hiai-docs-net:
|
|
210
|
+
driver: bridge
|
|
211
|
+
|
|
212
|
+
volumes:
|
|
213
|
+
pgdata:
|
|
214
|
+
redis_data:
|
|
215
|
+
ollama_data:
|
|
216
|
+
minio_data:
|
|
217
|
+
caddy_data:
|
|
218
|
+
caddy_config:
|
package/docs/API.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# API Reference
|
|
2
|
+
|
|
3
|
+
Base URL: `http://localhost:50700`
|
|
4
|
+
|
|
5
|
+
All responses are JSON. Errors follow `{ error: string, details?: unknown }`.
|
|
6
|
+
|
|
7
|
+
## Authentication
|
|
8
|
+
|
|
9
|
+
Most endpoints require a valid Better Auth session cookie. Public endpoints (health check, shared content access) are noted below.
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Sign in (sets session cookie)
|
|
13
|
+
curl -X POST http://localhost:50700/api/auth/sign-in \
|
|
14
|
+
-H "Content-Type: application/json" \
|
|
15
|
+
-d '{"email": "user@example.com", "password": "secret"}'
|
|
16
|
+
|
|
17
|
+
# Sign up
|
|
18
|
+
curl -X POST http://localhost:50700/api/auth/sign-up \
|
|
19
|
+
-H "Content-Type: application/json" \
|
|
20
|
+
-d '{"name": "User", "email": "user@example.com", "password": "secret"}'
|
|
21
|
+
|
|
22
|
+
# Get current session
|
|
23
|
+
curl http://localhost:50700/api/auth/session
|
|
24
|
+
|
|
25
|
+
# Sign out
|
|
26
|
+
curl -X POST http://localhost:50700/api/auth/sign-out
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Health
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
GET /api/health # → { status: "ok", timestamp: "..." }
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Documents
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
GET /api/documents # List (paginated)
|
|
39
|
+
POST /api/documents # Create
|
|
40
|
+
GET /api/documents/:id # Get with tags
|
|
41
|
+
PATCH /api/documents/:id # Update (saves version)
|
|
42
|
+
DELETE /api/documents/:id # Delete (cascade)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### List documents
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
curl "http://localhost:50700/api/documents?page=1&limit=20&folderId=UUID&tag=UUID"
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Response: `{ items: Document[], total: number, page: number, limit: number }`
|
|
52
|
+
|
|
53
|
+
### Create document
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
curl -X POST http://localhost:50700/api/documents \
|
|
57
|
+
-H "Content-Type: application/json" \
|
|
58
|
+
-d '{"title": "My Doc", "content": "Hello world", "folderId": "UUID"}'
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Update document
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
curl -X PATCH http://localhost:50700/api/documents/UUID \
|
|
65
|
+
-H "Content-Type: application/json" \
|
|
66
|
+
-d '{"title": "Updated", "content": "New content"}'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Duplicate document
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
curl -X POST http://localhost:50700/api/documents/UUID/duplicate
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Creates a copy with "(Copy)" suffix, including version snapshot and embedding queue.
|
|
76
|
+
|
|
77
|
+
### Export document
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
curl http://localhost:50700/api/documents/UUID/export
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Returns the document content as a `.md` file download.
|
|
84
|
+
|
|
85
|
+
### Import document
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
# JSON import
|
|
89
|
+
curl -X POST http://localhost:50700/api/documents/import \
|
|
90
|
+
-H "Content-Type: application/json" \
|
|
91
|
+
-d '{"title": "Imported", "content": "# Hello"}'
|
|
92
|
+
|
|
93
|
+
# File upload
|
|
94
|
+
curl -X POST http://localhost:50700/api/documents/import \
|
|
95
|
+
-F "file=@doc.md" \
|
|
96
|
+
-F "folderId=UUID"
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Supports `.md`, `.txt`, `.markdown`, `.json` files (max 10 MB).
|
|
100
|
+
|
|
101
|
+
### Document versions
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
GET /api/documents/:id/versions # List version history
|
|
105
|
+
GET /api/documents/:id/versions/:vid # Get specific version
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Versions are auto-saved on every create/update. Each entry includes `id, content, contentJson, createdBy, createdAt`.
|
|
109
|
+
|
|
110
|
+
## Document Attachments
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
POST /api/documents/:id/attachments # Upload image attachment
|
|
114
|
+
GET /api/documents/:id/attachments # List attachments
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Image uploads are stored in MinIO with integrity verification. Max file size: 10 MB. Only `image/*` MIME types accepted.
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
curl -X POST http://localhost:50700/api/documents/UUID/attachments \
|
|
121
|
+
-F "file=@screenshot.png"
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Response includes `id, filename, mimeType, size, url` (presigned S3 URL, 24h expiry).
|
|
125
|
+
|
|
126
|
+
## Collaboration (WebSocket)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
WS /ws/collab/:documentId # Real-time collaborative editing
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Uses Yjs for CRDT-based conflict resolution. Authentication via query param `?token=<session_token_or_api_key>`.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
# Connect via wscat (install: npm install -g wscat)
|
|
136
|
+
wscat -c "ws://localhost:50700/ws/collab/DOCUMENT_ID?token=API_KEY"
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Messages are JSON: `{ type: "sync" | "update" | "ping", update?: "base64", state?: "base64", clientId: number }`.
|
|
140
|
+
|
|
141
|
+
## Webhooks
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
POST /api/webhooks/minio # MinIO bucket event webhook
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Verifies `x-minio-signature` header against `WEBHOOK_SECRET`. Currently handles `s3:ObjectRemoved:Delete` events to sync attachment DB records.
|
|
148
|
+
|
|
149
|
+
## Folders
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
GET /api/folders # List (tree, root-level unless ?parentId=UUID)
|
|
153
|
+
GET /api/folders/:id # Get single folder
|
|
154
|
+
POST /api/folders # Create
|
|
155
|
+
PATCH /api/folders/:id # Rename/move
|
|
156
|
+
DELETE /api/folders/:id # Delete
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### List folders
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
curl "http://localhost:50700/api/folders?parentId=UUID"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Returns root folders when `parentId` is omitted.
|
|
166
|
+
|
|
167
|
+
### Create folder
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
curl -X POST http://localhost:50700/api/folders \
|
|
171
|
+
-H "Content-Type: application/json" \
|
|
172
|
+
-d '{"name": "My Folder", "parentId": "UUID"}'
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
## Search
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
GET /api/search # Full-text + semantic search (PUBLIC)
|
|
179
|
+
GET /api/search/suggest # Quick title suggestions (PUBLIC)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Full search
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
curl "http://localhost:50700/api/search?q=query&folder=UUID&tags=tag1,tag2&dateFrom=2026-01-01&dateTo=2026-12-31&sort=relevance&page=1&limit=20"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Query parameters:
|
|
189
|
+
|
|
190
|
+
| Param | Type | Description |
|
|
191
|
+
|-------|------|-------------|
|
|
192
|
+
| `q` | string | Search query |
|
|
193
|
+
| `folder` | UUID | Filter by folder |
|
|
194
|
+
| `tags` | string | Comma-separated tag names (ANY match) |
|
|
195
|
+
| `dateFrom` | ISO date | Filter docs created after |
|
|
196
|
+
| `dateTo` | ISO date | Filter docs created before |
|
|
197
|
+
| `sort` | enum | `relevance`, `date_desc`, `date_asc`, `name_asc`, `name_desc` |
|
|
198
|
+
| `page` | int | Page number (default 1) |
|
|
199
|
+
| `limit` | int | Per page (default 20, max 100) |
|
|
200
|
+
|
|
201
|
+
Response: `{ items: SearchResult[], total, page, limit }` where each item has `id, title, snippet, score, folderId, createdAt, updatedAt`.
|
|
202
|
+
|
|
203
|
+
### Quick suggest
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
curl "http://localhost:50700/api/search/suggest?q=deploy"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Returns top 5 title matches with similarity scores.
|
|
210
|
+
|
|
211
|
+
## Share Links
|
|
212
|
+
|
|
213
|
+
```
|
|
214
|
+
GET /api/share # List user's share links
|
|
215
|
+
POST /api/share # Create link
|
|
216
|
+
GET /api/share/:token # Access shared content (PUBLIC)
|
|
217
|
+
DELETE /api/share/:id # Revoke link
|
|
218
|
+
POST /api/share/:id/guests # Add guest email
|
|
219
|
+
DELETE /api/share/:id/guests/:email # Remove guest access
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Create share link
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
curl -X POST http://localhost:50700/api/share \
|
|
226
|
+
-H "Content-Type: application/json" \
|
|
227
|
+
-d '{"documentId": "UUID", "password": "optional", "expiresIn": "7d"}'
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Expires options: `1h`, `1d`, `7d`, `30d`, `never`.
|
|
231
|
+
|
|
232
|
+
### Access shared content
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Public — no auth required. Rate limited: 10 req/min per IP.
|
|
236
|
+
curl http://localhost:50700/api/share/TOKEN
|
|
237
|
+
|
|
238
|
+
# With password
|
|
239
|
+
curl http://localhost:50700/api/share/TOKEN \
|
|
240
|
+
-H "x-share-password: secret"
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
Returns 410 Gone if expired, 401 if password required/invalid.
|
|
244
|
+
|
|
245
|
+
## Tags
|
|
246
|
+
|
|
247
|
+
```
|
|
248
|
+
GET /api/tags # List tags with counts
|
|
249
|
+
POST /api/tags # Create tag
|
|
250
|
+
PATCH /api/tags/:id # Update tag
|
|
251
|
+
DELETE /api/tags/:id # Delete tag
|
|
252
|
+
POST /api/documents/:docId/tags # Tag document
|
|
253
|
+
DELETE /api/documents/:docId/tags/:tagId # Untag document
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Agent Integration
|
|
257
|
+
|
|
258
|
+
hiai-docs is designed for AI agent integration via its REST API. Use API key authentication for programmatic access.
|
|
259
|
+
|
|
260
|
+
### API Key Auth
|
|
261
|
+
|
|
262
|
+
Set `HIAI_DOCS_API_KEY` in your `.env` file. All API requests use Bearer token:
|
|
263
|
+
|
|
264
|
+
```bash
|
|
265
|
+
curl -H "Authorization: Bearer $HIAI_DOCS_API_KEY" \
|
|
266
|
+
http://localhost:50700/api/documents
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Semantic Search (RAG)
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Search documents by meaning (hybrid full-text + vector)
|
|
273
|
+
curl -H "Authorization: Bearer $HIAI_DOCS_API_KEY" \
|
|
274
|
+
"http://localhost:50700/api/search?q=how+to+deploy+docker"
|
|
275
|
+
|
|
276
|
+
# Response includes relevance scores:
|
|
277
|
+
# { items: [{ id, title, content, score, rank }] }
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Document CRUD for Agents
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Create document
|
|
284
|
+
curl -X POST http://localhost:50700/api/documents \
|
|
285
|
+
-H "Authorization: Bearer $HIAI_DOCS_API_KEY" \
|
|
286
|
+
-H "Content-Type: application/json" \
|
|
287
|
+
-d '{"title": "Agent Note", "content": "Important finding..."}'
|
|
288
|
+
|
|
289
|
+
# Read document
|
|
290
|
+
curl -H "Authorization: Bearer $HIAI_DOCS_API_KEY" \
|
|
291
|
+
http://localhost:50700/api/documents/UUID
|
|
292
|
+
|
|
293
|
+
# Update document
|
|
294
|
+
curl -X PATCH http://localhost:50700/api/documents/UUID \
|
|
295
|
+
-H "Authorization: Bearer $HIAI_DOCS_API_KEY" \
|
|
296
|
+
-H "Content-Type: application/json" \
|
|
297
|
+
-d '{"content": "Updated with new findings..."}'
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Mastra Integration
|
|
301
|
+
|
|
302
|
+
```typescript
|
|
303
|
+
import { Mastra } from "@mastra/core";
|
|
304
|
+
|
|
305
|
+
const docsTool = {
|
|
306
|
+
name: "search_knowledge",
|
|
307
|
+
description: "Search the knowledge base for relevant documents",
|
|
308
|
+
execute: async ({ query }) => {
|
|
309
|
+
const res = await fetch(
|
|
310
|
+
`http://localhost:50700/api/search?q=${encodeURIComponent(query)}`,
|
|
311
|
+
{ headers: { Authorization: `Bearer ${process.env.HIAI_DOCS_API_KEY}` } }
|
|
312
|
+
);
|
|
313
|
+
return res.json();
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
## Error Codes
|
|
319
|
+
|
|
320
|
+
| Code | Meaning |
|
|
321
|
+
|------|---------|
|
|
322
|
+
| 400 | Validation error (check `details`) |
|
|
323
|
+
| 401 | Not authenticated |
|
|
324
|
+
| 403 | Forbidden (not owner) |
|
|
325
|
+
| 404 | Resource not found |
|
|
326
|
+
| 410 | Share link expired |
|
|
327
|
+
| 429 | Rate limited (check `retry-after` header) |
|
|
328
|
+
| 500 | Internal server error |
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
## Monorepo Structure
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
hiai-docs/
|
|
7
|
+
├── backend/ # Elysia REST API (Bun runtime)
|
|
8
|
+
│ └── src/
|
|
9
|
+
│ ├── api/routes/ # Route handlers (documents, folders, search, share, tags, auth)
|
|
10
|
+
│ ├── api/middleware/# Auth middleware
|
|
11
|
+
│ ├── embedding/ # Embedding pipeline (chunker, providers, queue)
|
|
12
|
+
│ └── lib/ # Shared utilities (db, redis, config, logger, minio)
|
|
13
|
+
├── frontend/ # SvelteKit 2 + Svelte 5 + Tailwind CSS v4
|
|
14
|
+
│ └── src/
|
|
15
|
+
│ ├── routes/ # Pages (+page.svelte per route)
|
|
16
|
+
│ └── lib/
|
|
17
|
+
│ ├── components/ # UI components (sidebar, editor, cards)
|
|
18
|
+
│ ├── components/ui/ # shadcn-svelte primitives
|
|
19
|
+
│ └── api/ # API client functions
|
|
20
|
+
├── packages/db/ # Drizzle ORM schema + migrations (shared)
|
|
21
|
+
│ └── src/
|
|
22
|
+
│ ├── schema.ts # Table definitions + relations
|
|
23
|
+
│ └── client.ts # Database client
|
|
24
|
+
└── docker-compose.yml # Full stack deployment
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Tech Stack
|
|
28
|
+
|
|
29
|
+
| Layer | Technology |
|
|
30
|
+
|-------|-----------|
|
|
31
|
+
| Runtime | Bun 1.3.14+ |
|
|
32
|
+
| Backend | Elysia 1.4.28+ |
|
|
33
|
+
| ORM | Drizzle 0.45.2+ |
|
|
34
|
+
| Database | PostgreSQL 18 + pgvector |
|
|
35
|
+
| Cache | Redis 8.6+ |
|
|
36
|
+
| Auth | Better Auth |
|
|
37
|
+
| Frontend | SvelteKit 2.60+ / Svelte 5.55+ |
|
|
38
|
+
| UI | shadcn-svelte (new-york) + Tailwind v4 |
|
|
39
|
+
| Editor | TipTap + svelte-tiptap |
|
|
40
|
+
| Embeddings | Ollama (configurable) |
|
|
41
|
+
| Storage | MinIO (S3-compatible) |
|
|
42
|
+
|
|
43
|
+
## Data Flow
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
User → SvelteKit Frontend → REST API (Elysia) → PostgreSQL
|
|
47
|
+
→ Redis (queue/cache)
|
|
48
|
+
→ MinIO (attachments)
|
|
49
|
+
→ Ollama (embeddings)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
1. User creates/edits document in TipTap editor
|
|
53
|
+
2. Frontend PATCHes document via API
|
|
54
|
+
3. API saves content + version to PostgreSQL
|
|
55
|
+
4. API enqueues embedding job to Redis
|
|
56
|
+
5. Background worker fetches document, chunks text, generates vector via Ollama
|
|
57
|
+
6. Worker stores vector in pgvector column
|
|
58
|
+
|
|
59
|
+
Search queries run hybrid: full-text (tsvector) + semantic (pgvector cosine).
|
|
60
|
+
|
|
61
|
+
## Module Boundaries
|
|
62
|
+
|
|
63
|
+
- `api/` imports from `lib/` and `embedding/` — never the reverse
|
|
64
|
+
- `embedding/` imports from `lib/` only
|
|
65
|
+
- `lib/` has no imports from `api/` or `embedding/`
|
|
66
|
+
- `packages/db/` is imported by both backend and has no dependencies on either
|
|
67
|
+
|
|
68
|
+
## Security Model
|
|
69
|
+
|
|
70
|
+
- **Data isolation**: every query filters by `ownerId` (user-scoped)
|
|
71
|
+
- **Auth**: Better Auth session cookies (7-day expiry)
|
|
72
|
+
- **Sharing**: token-based links with optional password + expiry
|
|
73
|
+
- **Rate limiting**: 10 req/min per IP on public share endpoints
|
|
74
|
+
- **Validation**: Zod schemas on all API inputs
|
|
75
|
+
- **No secrets in code**: all config via environment variables
|