wadi 1.0.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.
- package/.agent/workflows/auto_sync.md +19 -0
- package/.agent/workflows/kivo_pipeline.md +27 -0
- package/.devcontainer/devcontainer.json +27 -0
- package/.github/workflows/kivo-cicd.yml +45 -0
- package/.github/workflows/monorepo-ci.yml +51 -0
- package/.github/workflows/wadi-ci.yml +38 -0
- package/.husky/pre-commit +2 -0
- package/.prettierignore +12 -0
- package/.prettierrc +9 -0
- package/.vscode/settings.json +19 -0
- package/CHANGELOG.md +56 -0
- package/CODE_OF_CONDUCT.md +43 -0
- package/CONTRIBUTING.md +42 -0
- package/DEPLOY_GUIDE.md +143 -0
- package/GO_LIVE_CHECKLIST.md +41 -0
- package/GO_LIVE_COMPLETE_REPORT.md +58 -0
- package/GO_LIVE_VALIDATION.md +39 -0
- package/LEGAL.md +38 -0
- package/MANIFESTO.md +40 -0
- package/MANUAL.md +82 -0
- package/OPS_PLAN.md +90 -0
- package/README.md +126 -0
- package/RELEASE_NOTES.md +51 -0
- package/ROADMAP.md +51 -0
- package/api_listado.txt +2197 -0
- package/apps/api/WADI_PROTOCOL.md +52 -0
- package/apps/api/debug-brain.js +11 -0
- package/apps/api/package.json +21 -0
- package/apps/api/src/core/analisis.js +17 -0
- package/apps/api/src/core/errors.js +31 -0
- package/apps/api/src/core/logger.js +32 -0
- package/apps/api/src/core/prompt-kivo.js +62 -0
- package/apps/api/src/index.js +212 -0
- package/apps/api/src/layers/human_pattern/composeResponse.js +35 -0
- package/apps/api/src/layers/human_pattern/detectPattern.js +39 -0
- package/apps/api/src/layers/human_pattern/heuristics.js +28 -0
- package/apps/api/src/layers/human_pattern/index.js +28 -0
- package/apps/api/src/layers/human_pattern/socialMemory.js +35 -0
- package/apps/api/src/middleware/errorHandler.js +24 -0
- package/apps/api/src/middleware/rateLimiter.js +38 -0
- package/apps/api/src/middleware/requestLogger.js +31 -0
- package/apps/api/src/middleware/upload.js +21 -0
- package/apps/api/src/middleware/validation.js +70 -0
- package/apps/api/src/modules/data.js +25 -0
- package/apps/api/src/modules/marketing.js +54 -0
- package/apps/api/src/modules/projects.js +40 -0
- package/apps/api/src/openai.js +16 -0
- package/apps/api/src/preferences/index.js +20 -0
- package/apps/api/src/register_user.js +22 -0
- package/apps/api/src/routes/kivo.js +58 -0
- package/apps/api/src/routes/monitoring.js +55 -0
- package/apps/api/src/routes.js +656 -0
- package/apps/api/src/supabase.js +17 -0
- package/apps/api/src/tools/index.js +57 -0
- package/apps/api/src/wadi-brain.js +171 -0
- package/apps/api/supabase/migrations/20251218_audit_logs.sql +27 -0
- package/apps/api/supabase/migrations/v2-chat-persistence.sql +83 -0
- package/apps/api/supabase/migrations/v3-cascade-delete.sql +11 -0
- package/apps/api/supabase/migrations/v3-security-fix.sql +90 -0
- package/apps/api/supabase/migrations/v3-storage.sql +36 -0
- package/apps/api/supabase/migrations/v4-gamification.sql +83 -0
- package/apps/api/supabase/migrations/v5-smoke-index.sql +6 -0
- package/apps/api/supabase/migrations/v6-schema-integrity-fix.sql +98 -0
- package/apps/api/supabase/migrations/v7-performance-indexes.sql +5 -0
- package/apps/api/supabase/migrations/v7-security-hardening.sql +132 -0
- package/apps/api/supabase/migrations/v8-security-hardening.sql +79 -0
- package/apps/api/test_human_pattern.js +30 -0
- package/apps/api/test_human_pattern_vague.js +30 -0
- package/apps/api/test_output.txt +76 -0
- package/apps/api/test_vague.js +30 -0
- package/apps/api/test_vague_block.js +30 -0
- package/apps/api/test_wadi.js +31 -0
- package/apps/api/tsconfig.json +13 -0
- package/apps/frontend/.env.local +3 -0
- package/apps/frontend/README.md +73 -0
- package/apps/frontend/eslint.config.js +27 -0
- package/apps/frontend/index.html +49 -0
- package/apps/frontend/package.json +41 -0
- package/apps/frontend/postcss.config.cjs +6 -0
- package/apps/frontend/public/cursors/wadi-neutral.svg +1 -0
- package/apps/frontend/public/cursors/wadi-select.svg +1 -0
- package/apps/frontend/public/icon-192.svg +1 -0
- package/apps/frontend/public/icon-512.svg +1 -0
- package/apps/frontend/public/manifest.webmanifest +23 -0
- package/apps/frontend/public/sw.js +57 -0
- package/apps/frontend/public/vite.svg +1 -0
- package/apps/frontend/public/wadi.svg +5 -0
- package/apps/frontend/src/assets/react.svg +1 -0
- package/apps/frontend/src/components/AuthLoader.tsx +50 -0
- package/apps/frontend/src/components/ChatInput.tsx +272 -0
- package/apps/frontend/src/components/ChatInterface.tsx +202 -0
- package/apps/frontend/src/components/ErrorBoundary.tsx +52 -0
- package/apps/frontend/src/components/InputArea.tsx +201 -0
- package/apps/frontend/src/components/Layout.tsx +73 -0
- package/apps/frontend/src/components/MessageBubble.tsx +66 -0
- package/apps/frontend/src/components/OnboardingModal.tsx +108 -0
- package/apps/frontend/src/components/SettingsModal.tsx +187 -0
- package/apps/frontend/src/components/Sidebar.tsx +171 -0
- package/apps/frontend/src/components/WadiOnboarding.tsx +71 -0
- package/apps/frontend/src/components/auditor/AuditReport.tsx +166 -0
- package/apps/frontend/src/components/auditor/AuditorHeader.tsx +34 -0
- package/apps/frontend/src/components/auditor/ContextPanel.tsx +138 -0
- package/apps/frontend/src/components/auditor/DataDeconstructor.tsx +85 -0
- package/apps/frontend/src/components/auditor/DecisionWall.tsx +65 -0
- package/apps/frontend/src/components/auditor/Dropzone.tsx +137 -0
- package/apps/frontend/src/components/common/Button.tsx +97 -0
- package/apps/frontend/src/components/common/Card.tsx +43 -0
- package/apps/frontend/src/components/common/Input.tsx +73 -0
- package/apps/frontend/src/components/common/Modal.tsx +53 -0
- package/apps/frontend/src/components/ui/Button.tsx +68 -0
- package/apps/frontend/src/components/ui/Card.tsx +86 -0
- package/apps/frontend/src/components/ui/Input.tsx +28 -0
- package/apps/frontend/src/components/ui/LogItem.tsx +64 -0
- package/apps/frontend/src/components/ui/MondayButton.tsx +40 -0
- package/apps/frontend/src/components/ui/MondayCard.tsx +24 -0
- package/apps/frontend/src/components/ui/Scouter.tsx +208 -0
- package/apps/frontend/src/components/ui/TerminalInput.tsx +202 -0
- package/apps/frontend/src/components/ui/Tooltip.tsx +67 -0
- package/apps/frontend/src/config/chatShortcuts.ts +20 -0
- package/apps/frontend/src/config/supabase.ts +6 -0
- package/apps/frontend/src/final_status.txt +3 -0
- package/apps/frontend/src/hooks/useScouter.ts +28 -0
- package/apps/frontend/src/hooks/useStoreHydration.ts +24 -0
- package/apps/frontend/src/improvement_status.txt +5 -0
- package/apps/frontend/src/index.css +88 -0
- package/apps/frontend/src/main.tsx +62 -0
- package/apps/frontend/src/monday_status.txt +7 -0
- package/apps/frontend/src/pages/ChatPage.tsx +201 -0
- package/apps/frontend/src/pages/DashboardPage.tsx +375 -0
- package/apps/frontend/src/pages/IntroWadi.tsx +114 -0
- package/apps/frontend/src/pages/LandingPage.tsx +103 -0
- package/apps/frontend/src/pages/Login.tsx +190 -0
- package/apps/frontend/src/pages/PrivacyPage.tsx +213 -0
- package/apps/frontend/src/pages/ProjectDetail.tsx +80 -0
- package/apps/frontend/src/pages/Projects.tsx +247 -0
- package/apps/frontend/src/pages/TermsPage.tsx +202 -0
- package/apps/frontend/src/router.tsx +83 -0
- package/apps/frontend/src/store/authStore.ts +152 -0
- package/apps/frontend/src/store/chatStore.ts +837 -0
- package/apps/frontend/src/store/documentStore.ts +89 -0
- package/apps/frontend/src/store/projectsStore.ts +111 -0
- package/apps/frontend/src/store/runsStore.ts +98 -0
- package/apps/frontend/src/utils/api.ts +34 -0
- package/apps/frontend/src/vite-env.d.ts +7 -0
- package/apps/frontend/tailwind.config.cjs +32 -0
- package/apps/frontend/tsconfig.app.json +27 -0
- package/apps/frontend/tsconfig.json +7 -0
- package/apps/frontend/tsconfig.node.json +26 -0
- package/apps/frontend/vite.config.ts +25 -0
- package/apps/kivo/.firebase/hosting.d3d3.cache +11 -0
- package/apps/kivo/.firebaserc +5 -0
- package/apps/kivo/BRANDING_GUIDE.md +71 -0
- package/apps/kivo/DEPLOYMENT_READY.md +46 -0
- package/apps/kivo/DEPLOY_URL.md +12 -0
- package/apps/kivo/IMPLEMENTATION_REPORT.md +35 -0
- package/apps/kivo/IMPLEMENTATION_REPORT_FINAL.md +49 -0
- package/apps/kivo/PLAN_MOBILE_2.0.md +44 -0
- package/apps/kivo/PWA_VERIFICATION_GUIDE.md +77 -0
- package/apps/kivo/README.md +28 -0
- package/apps/kivo/REBUILD_REPORT.md +34 -0
- package/apps/kivo/UPGRADE_REPORT.md +35 -0
- package/apps/kivo/android/app/build.gradle +54 -0
- package/apps/kivo/android/app/capacitor.build.gradle +19 -0
- package/apps/kivo/android/app/proguard-rules.pro +21 -0
- package/apps/kivo/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
- package/apps/kivo/android/app/src/main/AndroidManifest.xml +35 -0
- package/apps/kivo/android/app/src/main/java/com/kivo/app/MainActivity.java +5 -0
- package/apps/kivo/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
- package/apps/kivo/android/app/src/main/res/drawable/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-ldpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-hdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-ldpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-mdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-xhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-xxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-night-xxxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-night/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-ldpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-hdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-ldpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-mdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-xhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-xxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-night-xxxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
- package/apps/kivo/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
- package/apps/kivo/android/app/src/main/res/layout/activity_main.xml +12 -0
- package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +9 -0
- package/apps/kivo/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +9 -0
- package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-ldpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_background.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
- package/apps/kivo/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/apps/kivo/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
- package/apps/kivo/android/app/src/main/res/values/strings.xml +7 -0
- package/apps/kivo/android/app/src/main/res/values/styles.xml +22 -0
- package/apps/kivo/android/app/src/main/res/xml/file_paths.xml +5 -0
- package/apps/kivo/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
- package/apps/kivo/android/build.gradle +29 -0
- package/apps/kivo/android/capacitor.settings.gradle +3 -0
- package/apps/kivo/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/apps/kivo/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/apps/kivo/android/gradle.properties +22 -0
- package/apps/kivo/android/gradlew +252 -0
- package/apps/kivo/android/gradlew.bat +94 -0
- package/apps/kivo/android/settings.gradle +5 -0
- package/apps/kivo/android/variables.gradle +16 -0
- package/apps/kivo/assets/icon.png +0 -0
- package/apps/kivo/assets/splash.png +0 -0
- package/apps/kivo/capacitor.config.json +16 -0
- package/apps/kivo/firebase.json +6 -0
- package/apps/kivo/jest.config.js +4 -0
- package/apps/kivo/package.json +26 -0
- package/apps/kivo/tests_disabled/logic.test.js +34 -0
- package/apps/kivo/www/assets/icon-192.png +0 -0
- package/apps/kivo/www/assets/icon-512.png +0 -0
- package/apps/kivo/www/assets/kivo-icon.png +0 -0
- package/apps/kivo/www/assets/pop.mp3 +0 -0
- package/apps/kivo/www/favicon.ico +0 -0
- package/apps/kivo/www/firebase-config.js +75 -0
- package/apps/kivo/www/index.html +38 -0
- package/apps/kivo/www/manifest.json +29 -0
- package/apps/kivo/www/script.js +72 -0
- package/apps/kivo/www/style.css +82 -0
- package/apps/kivo/www/sw.js +46 -0
- package/apps/kivo-brain-api/.env.example +2 -0
- package/apps/kivo-brain-api/KIVO_BACKEND_SETUP.md +27 -0
- package/apps/kivo-brain-api/controllers/kivoController.js +31 -0
- package/apps/kivo-brain-api/index.js +24 -0
- package/apps/kivo-brain-api/package.json +17 -0
- package/apps/kivo-brain-api/routes/message.js +8 -0
- package/apps/kivo-brain-api/services/openaiService.js +64 -0
- package/apps/tests/wadi-tests.js +155 -0
- package/apps/wadi-brain/docs/README_REMOVE_OPTIONS.md +26 -0
- package/cli/commands/deploy.js +10 -0
- package/cli/commands/docs.js +16 -0
- package/cli/commands/explain.js +29 -0
- package/cli/commands/lint.js +14 -0
- package/cli/index.js +26 -0
- package/cli/package.json +12 -0
- package/docs/CNAME +1 -0
- package/docs/README.md +38 -0
- package/docs/USO.md +30 -0
- package/docs/index.html +46 -0
- package/eslint.config.js +101 -0
- package/final_validation.json +27 -0
- package/frontend_listado.txt +33387 -0
- package/listado.txt +12591 -0
- package/package.json +46 -0
- package/packages/logger/index.js +43 -0
- package/packages/logger/package.json +19 -0
- package/packages/logger/test-logger.js +7 -0
- package/packages_listado.txt +801 -0
- package/pnpm-workspace.yaml +6 -0
- package/reseteador_existencial.ps1 +40 -0
- package/scripts/bump-version.js +26 -0
- package/scripts/env.ps1 +13 -0
- package/scripts/setup_android.ps1 +25 -0
- package/scripts/setup_virtual_env.ps1 +77 -0
- package/scripts/smoke-test.js +84 -0
- package/scripts/trigger_render_deploy.ps1 +3 -0
- package/scripts/validate-release.js +34 -0
- package/temp_check.js +57 -0
- package/tsconfig.json +5 -0
- package/validation_report.json +27 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { persist } from "zustand/middleware";
|
|
3
|
+
import { API_URL } from "./chatStore";
|
|
4
|
+
|
|
5
|
+
export interface Document {
|
|
6
|
+
id: string;
|
|
7
|
+
filename: string;
|
|
8
|
+
content: string;
|
|
9
|
+
size: number;
|
|
10
|
+
uploadedAt: string;
|
|
11
|
+
tokens: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface DocumentState {
|
|
15
|
+
documents: Document[];
|
|
16
|
+
currentDocumentId: string | null;
|
|
17
|
+
|
|
18
|
+
addDocument: (doc: Document) => void;
|
|
19
|
+
removeDocument: (id: string) => void;
|
|
20
|
+
setCurrentDocument: (id: string | null) => void;
|
|
21
|
+
clearDocuments: () => void;
|
|
22
|
+
|
|
23
|
+
uploadDocument: (file: File) => Promise<Document>;
|
|
24
|
+
getDocumentContent: (id: string) => string | null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const useDocumentStore = create<DocumentState>()(
|
|
28
|
+
persist(
|
|
29
|
+
(set, get) => ({
|
|
30
|
+
documents: [],
|
|
31
|
+
currentDocumentId: null,
|
|
32
|
+
|
|
33
|
+
addDocument: (doc) =>
|
|
34
|
+
set((state) => ({
|
|
35
|
+
documents: [...state.documents, doc],
|
|
36
|
+
currentDocumentId: doc.id,
|
|
37
|
+
})),
|
|
38
|
+
|
|
39
|
+
removeDocument: (id) =>
|
|
40
|
+
set((state) => ({
|
|
41
|
+
documents: state.documents.filter((d) => d.id !== id),
|
|
42
|
+
currentDocumentId:
|
|
43
|
+
state.currentDocumentId === id ? null : state.currentDocumentId,
|
|
44
|
+
})),
|
|
45
|
+
|
|
46
|
+
setCurrentDocument: (id) => set({ currentDocumentId: id }),
|
|
47
|
+
|
|
48
|
+
clearDocuments: () => set({ documents: [], currentDocumentId: null }),
|
|
49
|
+
|
|
50
|
+
getDocumentContent: (id) => {
|
|
51
|
+
const doc = get().documents.find((d) => d.id === id);
|
|
52
|
+
return doc ? doc.content : null;
|
|
53
|
+
},
|
|
54
|
+
|
|
55
|
+
uploadDocument: async (file: File) => {
|
|
56
|
+
const formData = new FormData();
|
|
57
|
+
formData.append("file", file);
|
|
58
|
+
|
|
59
|
+
// We use the basic upload endpoint
|
|
60
|
+
const res = await fetch(`${API_URL}/api/documents/upload`, {
|
|
61
|
+
method: "POST",
|
|
62
|
+
// headers: { Authorization: ... } // Managed by browser or global auth logic if needed
|
|
63
|
+
body: formData,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
throw new Error("Error subiendo archivo. WADI lo rechazó.");
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const data = await res.json();
|
|
71
|
+
|
|
72
|
+
const newDoc: Document = {
|
|
73
|
+
id: crypto.randomUUID(),
|
|
74
|
+
filename: data.filename,
|
|
75
|
+
content: data.content,
|
|
76
|
+
size: data.size,
|
|
77
|
+
tokens: data.tokens,
|
|
78
|
+
uploadedAt: new Date().toISOString(),
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
get().addDocument(newDoc);
|
|
82
|
+
return newDoc;
|
|
83
|
+
},
|
|
84
|
+
}),
|
|
85
|
+
{
|
|
86
|
+
name: "wadi-documents-storage",
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
);
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { supabase } from "../config/supabase";
|
|
3
|
+
import { fetchWithRetry } from "../utils/api";
|
|
4
|
+
|
|
5
|
+
interface Project {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
description?: string;
|
|
9
|
+
created_at: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ProjectsState {
|
|
13
|
+
projects: Project[];
|
|
14
|
+
loading: boolean;
|
|
15
|
+
fetchProjects: () => Promise<void>;
|
|
16
|
+
createProject: (name: string, description: string) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const rawUrl = import.meta.env.VITE_API_URL || "https://wadi-wxg7.onrender.com";
|
|
20
|
+
const API_URL = rawUrl.replace(/\/api\/?$/, "").replace(/\/$/, "");
|
|
21
|
+
|
|
22
|
+
export const useProjectsStore = create<ProjectsState>((set) => ({
|
|
23
|
+
projects: [],
|
|
24
|
+
loading: false,
|
|
25
|
+
|
|
26
|
+
fetchProjects: async () => {
|
|
27
|
+
set({ loading: true });
|
|
28
|
+
try {
|
|
29
|
+
const {
|
|
30
|
+
data: { session },
|
|
31
|
+
} = await supabase.auth.getSession();
|
|
32
|
+
const token = session?.access_token;
|
|
33
|
+
if (!token) throw new Error("No authenticated session (Please login)");
|
|
34
|
+
|
|
35
|
+
const res = await fetchWithRetry(`${API_URL}/api/projects`, {
|
|
36
|
+
headers: {
|
|
37
|
+
Authorization: `Bearer ${token}`,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
let msg = `Error: ${res.status}`;
|
|
43
|
+
try {
|
|
44
|
+
const err = await res.json();
|
|
45
|
+
msg = err.error?.message || err.message || msg;
|
|
46
|
+
} catch {
|
|
47
|
+
/* ignore */
|
|
48
|
+
}
|
|
49
|
+
throw new Error(msg);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const contentType = res.headers.get("content-type");
|
|
53
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
54
|
+
throw new Error("Respuesta inválida del servidor (no es JSON)");
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const data = await res.json();
|
|
58
|
+
// Handle unified response shape if GET returns wrapped data?
|
|
59
|
+
// My backend routes.js returns `res.json(data)` (array), NOT `{ ok: true, data: [] }`.
|
|
60
|
+
// Only errors are wrapped. So straight array for data.
|
|
61
|
+
set({ projects: data, loading: false });
|
|
62
|
+
} catch (e) {
|
|
63
|
+
console.error("Failed to fetch projects", e);
|
|
64
|
+
set({ loading: false });
|
|
65
|
+
// Might want to expose error in store? But interface doesn't have it.
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
createProject: async (name, description) => {
|
|
70
|
+
try {
|
|
71
|
+
const {
|
|
72
|
+
data: { session },
|
|
73
|
+
} = await supabase.auth.getSession();
|
|
74
|
+
const token = session?.access_token;
|
|
75
|
+
|
|
76
|
+
const res = await fetchWithRetry(`${API_URL}/api/projects`, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: {
|
|
79
|
+
"Content-Type": "application/json",
|
|
80
|
+
Authorization: `Bearer ${token}`,
|
|
81
|
+
},
|
|
82
|
+
body: JSON.stringify({
|
|
83
|
+
name,
|
|
84
|
+
description,
|
|
85
|
+
}),
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
if (!res.ok) {
|
|
89
|
+
let msg = `Error: ${res.status}`;
|
|
90
|
+
try {
|
|
91
|
+
const err = await res.json();
|
|
92
|
+
msg = err.error?.message || err.message || msg;
|
|
93
|
+
} catch {
|
|
94
|
+
/* ignore */
|
|
95
|
+
}
|
|
96
|
+
throw new Error(msg);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const contentType = res.headers.get("content-type");
|
|
100
|
+
if (!contentType || !contentType.includes("application/json")) {
|
|
101
|
+
throw new Error("El servidor devolvió un error inesperado (HTML).");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const data = await res.json();
|
|
105
|
+
set((state) => ({ projects: [data, ...state.projects] }));
|
|
106
|
+
} catch (e) {
|
|
107
|
+
console.error("Failed to create project", e);
|
|
108
|
+
throw e;
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
}));
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { create } from "zustand";
|
|
2
|
+
import { supabase } from "../config/supabase";
|
|
3
|
+
import { fetchWithRetry } from "../utils/api";
|
|
4
|
+
|
|
5
|
+
interface Run {
|
|
6
|
+
id: string;
|
|
7
|
+
input: string;
|
|
8
|
+
output: string;
|
|
9
|
+
created_at: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface RunsState {
|
|
13
|
+
runs: Run[];
|
|
14
|
+
loading: boolean;
|
|
15
|
+
fetchRuns: (projectId: string) => Promise<void>;
|
|
16
|
+
createRun: (projectId: string, input: string) => Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const rawUrl = import.meta.env.VITE_API_URL || "https://wadi-wxg7.onrender.com";
|
|
20
|
+
const API_URL = rawUrl.replace(/\/api\/?$/, "").replace(/\/$/, "");
|
|
21
|
+
|
|
22
|
+
export const useRunsStore = create<RunsState>((set) => ({
|
|
23
|
+
runs: [],
|
|
24
|
+
loading: false,
|
|
25
|
+
|
|
26
|
+
fetchRuns: async (projectId) => {
|
|
27
|
+
set({ loading: true });
|
|
28
|
+
|
|
29
|
+
try {
|
|
30
|
+
const {
|
|
31
|
+
data: { session },
|
|
32
|
+
} = await supabase.auth.getSession();
|
|
33
|
+
const token = session?.access_token;
|
|
34
|
+
|
|
35
|
+
const res = await fetchWithRetry(
|
|
36
|
+
`${API_URL}/api/projects/${projectId}/runs`,
|
|
37
|
+
{
|
|
38
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
39
|
+
}
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
if (!res.ok) {
|
|
43
|
+
let msg = `Error: ${res.status}`;
|
|
44
|
+
try {
|
|
45
|
+
const err = await res.json();
|
|
46
|
+
msg = err.error?.message || err.message || msg;
|
|
47
|
+
} catch {
|
|
48
|
+
/* ignore */
|
|
49
|
+
}
|
|
50
|
+
throw new Error(msg);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const data = await res.json();
|
|
54
|
+
set({ runs: data, loading: false });
|
|
55
|
+
} catch (e) {
|
|
56
|
+
console.error("Failed to fetch runs", e);
|
|
57
|
+
set({ loading: false });
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
|
|
61
|
+
createRun: async (projectId, input) => {
|
|
62
|
+
try {
|
|
63
|
+
const {
|
|
64
|
+
data: { session },
|
|
65
|
+
} = await supabase.auth.getSession();
|
|
66
|
+
const token = session?.access_token;
|
|
67
|
+
|
|
68
|
+
const res = await fetchWithRetry(
|
|
69
|
+
`${API_URL}/api/projects/${projectId}/runs`,
|
|
70
|
+
{
|
|
71
|
+
method: "POST",
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Authorization: token ? `Bearer ${token}` : "",
|
|
75
|
+
},
|
|
76
|
+
body: JSON.stringify({ input }),
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
if (!res.ok) {
|
|
81
|
+
let msg = `Error: ${res.status}`;
|
|
82
|
+
try {
|
|
83
|
+
const err = await res.json();
|
|
84
|
+
msg = err.error?.message || err.message || msg;
|
|
85
|
+
} catch {
|
|
86
|
+
/* ignore */
|
|
87
|
+
}
|
|
88
|
+
throw new Error(msg);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const data = await res.json();
|
|
92
|
+
set((state) => ({ runs: [data, ...state.runs] }));
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error("Failed to create run", e);
|
|
95
|
+
throw e;
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
}));
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export const fetchWithRetry = async (
|
|
2
|
+
url: string,
|
|
3
|
+
options: RequestInit = {},
|
|
4
|
+
retries = 3,
|
|
5
|
+
backoff = 300
|
|
6
|
+
): Promise<Response> => {
|
|
7
|
+
try {
|
|
8
|
+
const res = await fetch(url, options);
|
|
9
|
+
|
|
10
|
+
// Check for success
|
|
11
|
+
if (res.ok) return res;
|
|
12
|
+
|
|
13
|
+
// Retry on Rate Limit (429) or Server Error (5xx)
|
|
14
|
+
if (retries > 0 && (res.status === 429 || res.status >= 500)) {
|
|
15
|
+
console.warn(
|
|
16
|
+
`Retrying ${url} (${res.status})... Attempts left: ${retries}`
|
|
17
|
+
);
|
|
18
|
+
await new Promise((r) => setTimeout(r, backoff));
|
|
19
|
+
return fetchWithRetry(url, options, retries - 1, backoff * 2);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return res;
|
|
23
|
+
} catch (error) {
|
|
24
|
+
// Network errors (fetch throws)
|
|
25
|
+
if (retries > 0) {
|
|
26
|
+
console.warn(
|
|
27
|
+
`Network error for ${url}. Retrying... Attempts left: ${retries}`
|
|
28
|
+
);
|
|
29
|
+
await new Promise((r) => setTimeout(r, backoff));
|
|
30
|
+
return fetchWithRetry(url, options, retries - 1, backoff * 2);
|
|
31
|
+
}
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
content: ["./src/**/*.{js,ts,jsx,tsx}"],
|
|
3
|
+
darkMode: "class",
|
|
4
|
+
theme: {
|
|
5
|
+
extend: {
|
|
6
|
+
colors: {
|
|
7
|
+
wadi: {
|
|
8
|
+
bg: "#f3f3f0",
|
|
9
|
+
surface: "#e5e5e0",
|
|
10
|
+
text: "#1a1a1a",
|
|
11
|
+
subtle: "#666666",
|
|
12
|
+
accent: "#00a7a7", // Teal
|
|
13
|
+
danger: "#e11d48", // Stronger red for light mode
|
|
14
|
+
border: "#d4d4cc",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
borderRadius: {
|
|
18
|
+
wadi: "1rem",
|
|
19
|
+
},
|
|
20
|
+
boxShadow: {
|
|
21
|
+
wadi: "0 2px 10px rgba(145, 246, 215, 0.1)",
|
|
22
|
+
},
|
|
23
|
+
fontFamily: {
|
|
24
|
+
sans: ["Inter", "ui-sans-serif", "system-ui"],
|
|
25
|
+
},
|
|
26
|
+
spacing: {
|
|
27
|
+
input: "3rem",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
plugins: [],
|
|
32
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "ES2022",
|
|
5
|
+
"useDefineForClassFields": true,
|
|
6
|
+
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
7
|
+
"module": "ESNext",
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"erasableSyntaxOnly": true,
|
|
23
|
+
"noFallthroughCasesInSwitch": true,
|
|
24
|
+
"noUncheckedSideEffectImports": true
|
|
25
|
+
},
|
|
26
|
+
"include": ["src"]
|
|
27
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
|
|
4
|
+
"target": "ES2023",
|
|
5
|
+
"lib": ["ES2023"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"types": ["node"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"erasableSyntaxOnly": true,
|
|
22
|
+
"noFallthroughCasesInSwitch": true,
|
|
23
|
+
"noUncheckedSideEffectImports": true
|
|
24
|
+
},
|
|
25
|
+
"include": ["vite.config.ts"]
|
|
26
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { defineConfig, loadEnv } from "vite";
|
|
2
|
+
import react from "@vitejs/plugin-react";
|
|
3
|
+
|
|
4
|
+
// https://vite.dev/config/
|
|
5
|
+
export default defineConfig(({ mode }) => {
|
|
6
|
+
const env = loadEnv(mode, process.cwd(), "");
|
|
7
|
+
|
|
8
|
+
return {
|
|
9
|
+
base: "/",
|
|
10
|
+
plugins: [react()],
|
|
11
|
+
define: {
|
|
12
|
+
"import.meta.env.VITE_SUPABASE_URL": JSON.stringify(
|
|
13
|
+
env.VITE_SUPABASE_URL || env.SUPABASE_URL
|
|
14
|
+
),
|
|
15
|
+
"import.meta.env.VITE_SUPABASE_KEY": JSON.stringify(
|
|
16
|
+
env.VITE_SUPABASE_KEY || env.SUPABASE_KEY
|
|
17
|
+
),
|
|
18
|
+
},
|
|
19
|
+
build: {
|
|
20
|
+
outDir: "dist",
|
|
21
|
+
assetsDir: "assets",
|
|
22
|
+
emptyOutDir: true,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
sw.js,1764938915730,8b1b9783edfa8d544da892ba7544d2d78073be8ef7dac3d51ec62c44ef962536
|
|
2
|
+
style.css,1764891366974,952ffa696c0b0e6f72c188be6b9c21f342e36f603fe389bfc2188d60140321f4
|
|
3
|
+
manifest.json,1764937803384,d2b71286ca452740ddecf13ae161031bcb54720c31606d06d925de1eb2608bde
|
|
4
|
+
index.html,1764937785775,4e6fc4c044330416955a189280e7c077815a5cd156fa5c5c3e4bbabab6ec3dca
|
|
5
|
+
firebase-config.js,1764864376063,62203773faa6509c0daa8ca08e3b440f74bd5c3d3f5b7d34903bb7757d0f6852
|
|
6
|
+
favicon.ico,1764857804978,9faedf10d0055e9b08d21824a66062cb7a9322ba431e74eae95b471d1aea68c7
|
|
7
|
+
assets/pop.mp3,1764857838135,46b50c321b39e89a491b6727a01628c34245605a30beb3e7414c5e01cff90e6e
|
|
8
|
+
assets/kivo-icon.png,1764857804978,9faedf10d0055e9b08d21824a66062cb7a9322ba431e74eae95b471d1aea68c7
|
|
9
|
+
assets/icon-512.png,1764891440378,3a58649a6c58e753c38dca0e1b8804533201e664aef78be400d72b1ba6a9a9bc
|
|
10
|
+
assets/icon-192.png,1764891426322,0470c1ebc96e639f4849ed49c2f028ef98286ec4db041fe7d2706afe13271d47
|
|
11
|
+
script.js,1764939149374,a1447b17184f8caebf45753759b9b94c97d34bdc85b0b517151954bc78ec48f5
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# Kivo Branding Guide
|
|
2
|
+
|
|
3
|
+
## 1. Misión
|
|
4
|
+
|
|
5
|
+
**"Del caos al orden."**
|
|
6
|
+
Kivo es un compañero emocional inteligente diseñado para ayudar a los usuarios a procesar sus pensamientos y emociones en un entorno seguro, minimalista y libre de juicios.
|
|
7
|
+
|
|
8
|
+
## 2. Paleta de Colores
|
|
9
|
+
|
|
10
|
+
### Principales
|
|
11
|
+
|
|
12
|
+
- **Fondo Principal**: `#F7F6F2` (Off-white cálido, papel)
|
|
13
|
+
- **Texto Primario**: `#1F2937` (Gris oscuro cálido)
|
|
14
|
+
- **Texto Secundario**: `#6B7280` (Gris medio)
|
|
15
|
+
|
|
16
|
+
### Acentos
|
|
17
|
+
|
|
18
|
+
- **Primario (Acción/Usuario)**: `#3B82F6` (Azul vibrante pero suave)
|
|
19
|
+
- **Complementario**: `#22D3EE` (Cyan suave)
|
|
20
|
+
- **Emocional**: `#A78BFA` (Violeta suave)
|
|
21
|
+
|
|
22
|
+
### UI Elements
|
|
23
|
+
|
|
24
|
+
- **Glass Panel**: `rgba(255, 255, 255, 0.6)`
|
|
25
|
+
- **Glass Border**: `rgba(255, 255, 255, 0.4)`
|
|
26
|
+
- **Sombra Suave**: `0 4px 20px rgba(0, 0, 0, 0.05)`
|
|
27
|
+
|
|
28
|
+
## 3. Tipografía
|
|
29
|
+
|
|
30
|
+
- **Familia**: Inter, SF Pro Display, o system-ui.
|
|
31
|
+
- **Estilo**: Limpio, moderno, sans-serif.
|
|
32
|
+
- **Pesos**:
|
|
33
|
+
- Títulos: SemiBold (600) o Bold (700)
|
|
34
|
+
- Cuerpo: Regular (400)
|
|
35
|
+
- Botones: SemiBold (600)
|
|
36
|
+
|
|
37
|
+
## 4. Logo
|
|
38
|
+
|
|
39
|
+
- **Estilo**: Tipográfico puro. Sin isotipos complejos.
|
|
40
|
+
- **Color**: `#1F2937` sobre fondo claro.
|
|
41
|
+
- **Uso**: Centrado en splash screens y headers.
|
|
42
|
+
|
|
43
|
+
## 5. Componentes UI
|
|
44
|
+
|
|
45
|
+
### Burbujas de Chat
|
|
46
|
+
|
|
47
|
+
- **Usuario (Derecha)**:
|
|
48
|
+
- Fondo: `#3B82F6`
|
|
49
|
+
- Texto: Blanco
|
|
50
|
+
- Radio: 20px (redondo)
|
|
51
|
+
- **Kivo (Izquierda)**:
|
|
52
|
+
- Fondo: Glass / Blanco translúcido
|
|
53
|
+
- Texto: `#1F2937`
|
|
54
|
+
- Borde: Sutil (`rgba(255,255,255,0.5)`)
|
|
55
|
+
|
|
56
|
+
### Botones
|
|
57
|
+
|
|
58
|
+
- **Primario**: Pill shape (bordes redondeados completos), color acento, sombra suave.
|
|
59
|
+
- **Secundario**: Borde fino, fondo transparente.
|
|
60
|
+
|
|
61
|
+
## 6. Tono de Voz
|
|
62
|
+
|
|
63
|
+
- **Empático**: Escucha activa, validación.
|
|
64
|
+
- **Directo**: Sin rodeos innecesarios.
|
|
65
|
+
- **Adaptable**: Cambia según el modo (Barrio, Técnico, Reflexivo).
|
|
66
|
+
|
|
67
|
+
## 7. Prohibiciones (Don'ts)
|
|
68
|
+
|
|
69
|
+
- ✖ No usar sombras duras o negras puras (`#000000`).
|
|
70
|
+
- ✖ No usar gradientes agresivos.
|
|
71
|
+
- ✖ No saturar la interfaz con elementos decorativos innecesarios.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Kivo Deployment Readiness Report
|
|
2
|
+
|
|
3
|
+
## Build Status
|
|
4
|
+
|
|
5
|
+
- **Date**: 2025-12-04
|
|
6
|
+
- **Status**: Ready for Distribution
|
|
7
|
+
- **Version**: 1.0.0 (1)
|
|
8
|
+
|
|
9
|
+
## Artifacts Location
|
|
10
|
+
|
|
11
|
+
The following build artifacts have been generated in `apps/kivo/android/app/build/outputs/`:
|
|
12
|
+
|
|
13
|
+
### APK (Direct Install)
|
|
14
|
+
|
|
15
|
+
- **Debug APK**: `apk/debug/app-debug.apk` (For testing)
|
|
16
|
+
- **Release APK**: `apk/release/app-release-unsigned.apk` (Requires signing)
|
|
17
|
+
|
|
18
|
+
### AAB (Google Play Store)
|
|
19
|
+
|
|
20
|
+
- **Release Bundle**: `bundle/release/app-release.aab` (Required for Play Console)
|
|
21
|
+
|
|
22
|
+
## Deployment Instructions
|
|
23
|
+
|
|
24
|
+
### 1. Google Play Store (AAB)
|
|
25
|
+
|
|
26
|
+
1. Go to **Google Play Console**.
|
|
27
|
+
2. Create a new release in **Production** or **Testing**.
|
|
28
|
+
3. Upload the `app-release.aab` file.
|
|
29
|
+
4. Google Play will handle the signing (if Play App Signing is enabled).
|
|
30
|
+
|
|
31
|
+
### 2. Manual Distribution (APK)
|
|
32
|
+
|
|
33
|
+
To share the APK manually (e.g., via WhatsApp or website):
|
|
34
|
+
|
|
35
|
+
1. Use the `app-debug.apk` for quick testing.
|
|
36
|
+
2. For production, you must sign the `app-release-unsigned.apk`:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
apksigner sign --ks my-release-key.jks --out app-release-signed.apk app-release-unsigned.apk
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Environment
|
|
43
|
+
|
|
44
|
+
- **SDK**: Android API 34
|
|
45
|
+
- **Java**: JDK 17
|
|
46
|
+
- **Build System**: Gradle 8.x
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Kivo Deployment URLs
|
|
2
|
+
|
|
3
|
+
Kivo is now live on Firebase Hosting!
|
|
4
|
+
|
|
5
|
+
- **Primary URL**: https://kivo-8c62e.web.app
|
|
6
|
+
- **Alternate URL**: https://kivo-8c62e.firebaseapp.com
|
|
7
|
+
|
|
8
|
+
## Status
|
|
9
|
+
|
|
10
|
+
- **Deployed**: Yes
|
|
11
|
+
- **Date**: 2025-12-04
|
|
12
|
+
- **Environment**: Production (Firebase Hosting)
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Kivo Mobile 2.0 Implementation Report
|
|
2
|
+
|
|
3
|
+
## 1. Mobile UI Responsiveness
|
|
4
|
+
|
|
5
|
+
- **CSS Updates**:
|
|
6
|
+
- Implemented `100dvh` for full viewport height on mobile.
|
|
7
|
+
- Added `safe-area-inset` support for notches and home bars.
|
|
8
|
+
- Fixed input bar at the bottom with proper padding.
|
|
9
|
+
- Increased touch targets for buttons and inputs.
|
|
10
|
+
- Improved message bubble styling and animations.
|
|
11
|
+
- **HTML Updates**:
|
|
12
|
+
- Replaced "Enviar" text button with an SVG icon for better space usage.
|
|
13
|
+
|
|
14
|
+
## 2. PWA Upgrade
|
|
15
|
+
|
|
16
|
+
- **Manifest**:
|
|
17
|
+
- Updated `manifest.json` with `standalone` display, orientation, categories, and maskable icons.
|
|
18
|
+
- **Service Worker**:
|
|
19
|
+
- Updated `sw.js` to version 3.
|
|
20
|
+
- Added `manifest.json` to the cache list.
|
|
21
|
+
- Ensured offline capability for core assets.
|
|
22
|
+
|
|
23
|
+
## 3. Android Configuration (Capacitor)
|
|
24
|
+
|
|
25
|
+
- **Config**:
|
|
26
|
+
- Updated `capacitor.config.json` with `androidScheme: 'https'` and splash screen settings.
|
|
27
|
+
- **Sync**:
|
|
28
|
+
- Ran `npx cap sync` to update the Android project with the latest web assets.
|
|
29
|
+
- **Assets**:
|
|
30
|
+
- Generated native icons and splash screens using `@capacitor/assets`.
|
|
31
|
+
|
|
32
|
+
## Next Steps
|
|
33
|
+
|
|
34
|
+
- **Test PWA**: Open `http://localhost:3000` on a mobile device (via network) and try "Add to Home Screen".
|
|
35
|
+
- **Build Android**: Open `android` folder in Android Studio and run the app on a device/emulator.
|