@agentprojectcontext/apx 1.80.2 → 1.89.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/package.json +9 -8
- package/skills/apc-context/SKILL.md +14 -7
- package/skills/apx/SKILL.md +62 -2
- package/skills/apx-mcp/SKILL.md +42 -15
- package/src/core/agent/a2a/peers.js +161 -0
- package/src/core/agent/a2a/reply.js +379 -27
- package/src/core/agent/abort.js +25 -0
- package/src/core/agent/agent-model.js +58 -0
- package/src/core/agent/agent-tools.js +101 -0
- package/src/core/agent/author-line.js +110 -0
- package/src/core/agent/build-agent-system.js +52 -18
- package/src/core/agent/channels/voice-context.js +17 -2
- package/src/core/agent/closing-floor.js +117 -0
- package/src/core/agent/constants.js +119 -11
- package/src/core/agent/engine-call.js +56 -0
- package/src/core/agent/group/run-group-turn.js +218 -0
- package/src/core/agent/group/turn-resolver.js +165 -0
- package/src/core/agent/judge.js +138 -11
- package/src/core/agent/loop/side-effects.js +106 -3
- package/src/core/agent/memory.js +31 -18
- package/src/core/agent/model-capabilities.js +47 -0
- package/src/core/agent/model-router.js +11 -40
- package/src/core/agent/prompt-builder.js +47 -0
- package/src/core/agent/prompts/channels/a2a.md +12 -0
- package/src/core/agent/prompts/channels/code.md +3 -1
- package/src/core/agent/prompts/channels/telegram.md +2 -0
- package/src/core/agent/prompts/channels/web_code.md +1 -1
- package/src/core/agent/prompts/channels/whatsapp.md +37 -0
- package/src/core/agent/prompts/core/agent-base.md +2 -0
- package/src/core/agent/prompts/discipline/action.md +1 -0
- package/src/core/agent/prompts/discipline/two-segment.md +2 -1
- package/src/core/agent/prompts/modes/mobility.md +36 -0
- package/src/core/agent/retry.js +42 -0
- package/src/core/agent/run-agent.js +322 -25
- package/src/core/agent/run-turn.js +253 -0
- package/src/core/agent/self-memory.js +18 -52
- package/src/core/agent/skills/agent-skills.js +118 -0
- package/src/core/agent/skills/catalog.js +1 -1
- package/src/core/agent/skills/declared.js +13 -0
- package/src/core/agent/skills/index-store.js +8 -1
- package/src/core/agent/skills/inspector.js +20 -3
- package/src/core/agent/skills/loader.js +18 -3
- package/src/core/agent/skills/media.js +121 -0
- package/src/core/agent/skills/origin.js +61 -0
- package/src/core/agent/skills/sections.js +136 -0
- package/src/core/agent/super-agent.js +54 -14
- package/src/core/agent/tools/handlers/_calendar.js +50 -0
- package/src/core/agent/tools/handlers/add-mcp.js +103 -0
- package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
- package/src/core/agent/tools/handlers/attach-media.js +56 -0
- package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
- package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
- package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
- package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
- package/src/core/agent/tools/handlers/call-agent.js +14 -6
- package/src/core/agent/tools/handlers/call-runtime.js +27 -49
- package/src/core/agent/tools/handlers/comment-task.js +78 -0
- package/src/core/agent/tools/handlers/complete-task.js +60 -0
- package/src/core/agent/tools/handlers/configure-agent.js +70 -0
- package/src/core/agent/tools/handlers/create-agent.js +68 -0
- package/src/core/agent/tools/handlers/create-task.js +41 -3
- package/src/core/agent/tools/handlers/import-agent.js +5 -5
- package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
- package/src/core/agent/tools/handlers/list-routines.js +46 -0
- package/src/core/agent/tools/handlers/list-tasks.js +8 -1
- package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
- package/src/core/agent/tools/handlers/read-skill.js +64 -0
- package/src/core/agent/tools/handlers/remember-routine.js +2 -8
- package/src/core/agent/tools/handlers/remember.js +82 -6
- package/src/core/agent/tools/handlers/remove-agent.js +42 -0
- package/src/core/agent/tools/handlers/run-routine.js +94 -0
- package/src/core/agent/tools/handlers/run-shell.js +44 -2
- package/src/core/agent/tools/handlers/send-telegram.js +41 -19
- package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
- package/src/core/agent/tools/handlers/view-media.js +69 -0
- package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
- package/src/core/agent/tools/helpers.js +36 -4
- package/src/core/agent/tools/names.js +64 -0
- package/src/core/agent/tools/registry-bridge.js +24 -1
- package/src/core/agent/tools/registry.js +79 -0
- package/src/core/agent/tools/tool-call-parser.js +136 -13
- package/src/core/agent/vision-bridge.js +69 -0
- package/src/core/apc/agent-identity.js +74 -0
- package/src/core/apc/agent-rename-refs.js +187 -0
- package/src/core/apc/agent-write.js +312 -0
- package/src/core/apc/agents-vault.js +1 -1
- package/src/core/apc/blob-keys.js +42 -0
- package/src/core/apc/frontmatter.js +166 -10
- package/src/core/apc/parser.js +33 -83
- package/src/core/apc/paths.js +4 -6
- package/src/core/apc/project-memory.js +44 -0
- package/src/core/apc/projects-helpers.js +33 -0
- package/src/core/apc/scaffold.js +36 -16
- package/src/core/channels/telegram/ask-callbacks.js +103 -0
- package/src/core/channels/telegram/dispatch.js +154 -30
- package/src/core/channels/telegram/helpers.js +59 -7
- package/src/core/channels/telegram/inbound/audio.js +26 -30
- package/src/core/channels/telegram/inbound/file.js +22 -32
- package/src/core/channels/telegram/inbound/photo.js +24 -28
- package/src/core/channels/telegram/progress-gate.js +76 -0
- package/src/core/channels/telegram/reply.js +151 -43
- package/src/core/channels/telegram/voice-note.js +150 -0
- package/src/core/config/index.js +53 -54
- package/src/core/config/paths.js +117 -31
- package/src/core/config/redact.js +89 -4
- package/src/core/config/secret-values.js +2 -4
- package/src/core/constants/actors.js +5 -0
- package/src/core/constants/channels.js +3 -1
- package/src/core/constants/task-categories.js +73 -0
- package/src/core/constants/task-fields.js +28 -0
- package/src/core/engines/_globs.js +33 -0
- package/src/core/engines/anthropic.js +19 -1
- package/src/core/engines/catalog.js +20 -0
- package/src/core/engines/gemini.js +84 -16
- package/src/core/engines/index.js +19 -3
- package/src/core/engines/mock.js +145 -1
- package/src/core/engines/openai-compatible.js +150 -15
- package/src/core/engines/presets.js +36 -9
- package/src/core/engines/zen.js +131 -0
- package/src/core/events/bus.js +140 -0
- package/src/core/events/mascot-notify.js +156 -0
- package/src/core/http-tools/browser.js +366 -36
- package/src/core/http-tools/catalog.js +206 -22
- package/src/core/http-tools/grep.js +62 -7
- package/src/core/http-tools/registry.js +3 -1
- package/src/core/i18n/en.js +34 -3
- package/src/core/i18n/es.js +36 -4
- package/src/core/i18n/index.js +5 -5
- package/src/core/i18n/pt.js +32 -3
- package/src/core/identity/self.js +14 -1
- package/src/core/images/engines/a1111.js +219 -0
- package/src/core/images/engines/index.js +187 -0
- package/src/core/images/engines/mock.js +74 -0
- package/src/core/images/engines/openai.js +130 -0
- package/src/core/images/engines/sdcpp.js +204 -0
- package/src/core/images/engines/shared.js +218 -0
- package/src/core/images/generate.js +260 -0
- package/src/core/integrations/catalog.js +8 -3
- package/src/core/integrations/plugins/_google-oauth.js +179 -0
- package/src/core/integrations/plugins/asana.js +7 -3
- package/src/core/integrations/plugins/calendar.js +404 -0
- package/src/core/integrations/store.js +2 -0
- package/src/core/memory/broker.js +16 -1
- package/src/core/memory/compactor.js +19 -3
- package/src/core/memory/consolidate.js +2 -2
- package/src/core/memory/dated-log.js +66 -0
- package/src/core/memory/embed-engines/custom.js +59 -0
- package/src/core/memory/embed-engines/gemini.js +9 -3
- package/src/core/memory/embed-engines/index.js +87 -15
- package/src/core/memory/embeddings.js +52 -24
- package/src/core/memory/index.js +13 -3
- package/src/core/memory/indexer.js +83 -27
- package/src/core/memory/prune.js +182 -0
- package/src/core/memory/store.js +22 -0
- package/src/core/memory/summarizer.js +72 -8
- package/src/core/mobility/answer.js +80 -0
- package/src/core/mobility/geofence.js +667 -0
- package/src/core/mobility/osm-route.js +282 -0
- package/src/core/mobility/preferences.js +91 -0
- package/src/core/mobility/state.js +245 -0
- package/src/core/mobility/trip-event.js +384 -0
- package/src/core/net/tailscale.js +168 -0
- package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
- package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
- package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
- package/src/core/profiles/bundled/secretary/profile.json +3 -1
- package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
- package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
- package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
- package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
- package/src/core/profiles/lifecycle.js +243 -19
- package/src/core/profiles/paths.js +12 -0
- package/src/core/profiles/store.js +47 -0
- package/src/core/routines/active-runs.js +213 -0
- package/src/core/routines/delivery.js +612 -0
- package/src/core/routines/header.js +88 -0
- package/src/core/routines/index.js +26 -0
- package/src/core/routines/run-log.js +78 -0
- package/src/core/routines/runner.js +629 -66
- package/src/core/routines/signals.js +75 -0
- package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
- package/src/core/runtime-skills/apx/SKILL.md +93 -1
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
- package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
- package/src/core/runtime-skills/apx-commitment/SKILL.md +134 -0
- package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
- package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
- package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
- package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
- package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
- package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
- package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
- package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
- package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
- package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
- package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
- package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
- package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
- package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
- package/src/core/runtimes/_spawn.js +9 -1
- package/src/core/runtimes/claude-code.js +11 -2
- package/src/core/runtimes/codex.js +44 -10
- package/src/core/runtimes/index.js +17 -2
- package/src/core/runtimes/opencode.js +88 -9
- package/src/core/runtimes/outcome.js +119 -0
- package/src/core/sessions/index.js +193 -1
- package/src/core/stores/agent-inbox.js +109 -23
- package/src/core/stores/code-sessions.js +21 -0
- package/src/core/stores/commitments.js +27 -3
- package/src/core/stores/conversations.js +220 -20
- package/src/core/stores/deliveries.js +177 -0
- package/src/core/stores/media-archive.js +228 -0
- package/src/core/stores/messages.js +1096 -112
- package/src/core/stores/organization.js +34 -0
- package/src/core/stores/project-memory.js +71 -0
- package/src/core/stores/routine-memory.js +16 -8
- package/src/core/stores/routines.js +27 -49
- package/src/core/stores/sessions.js +4 -8
- package/src/core/stores/tasks.js +212 -18
- package/src/core/stores/turn-record.js +209 -0
- package/src/core/tasks/columns.js +136 -0
- package/src/core/tasks/comment-turn.js +258 -0
- package/src/core/util/time.js +13 -0
- package/src/core/voice/engines/index.js +54 -1
- package/src/core/voice/engines/openai.js +50 -4
- package/src/core/voice/opus.js +67 -0
- package/src/core/voice/pronounceable.js +43 -0
- package/src/core/voice/transcription.js +4 -0
- package/src/core/voice/tts.js +114 -24
- package/src/host/daemon/active-turns.js +188 -0
- package/src/host/daemon/api/admin-config.js +9 -0
- package/src/host/daemon/api/agents.js +99 -90
- package/src/host/daemon/api/artifact-preview.js +7 -6
- package/src/host/daemon/api/artifacts.js +3 -2
- package/src/host/daemon/api/code.js +55 -9
- package/src/host/daemon/api/commitments.js +11 -0
- package/src/host/daemon/api/confirm.js +3 -2
- package/src/host/daemon/api/conversations.js +543 -35
- package/src/host/daemon/api/deck.js +9 -8
- package/src/host/daemon/api/deliveries.js +33 -0
- package/src/host/daemon/api/desktop.js +5 -4
- package/src/host/daemon/api/embeddings.js +15 -6
- package/src/host/daemon/api/engines.js +59 -8
- package/src/host/daemon/api/exec.js +437 -121
- package/src/host/daemon/api/groups.js +215 -0
- package/src/host/daemon/api/images.js +107 -0
- package/src/host/daemon/api/inbox.js +123 -2
- package/src/host/daemon/api/integrations.js +64 -2
- package/src/host/daemon/api/mcps.js +7 -6
- package/src/host/daemon/api/media.js +283 -0
- package/src/host/daemon/api/mobility.js +177 -0
- package/src/host/daemon/api/net.js +182 -0
- package/src/host/daemon/api/pairing.js +38 -5
- package/src/host/daemon/api/profiles.js +30 -2
- package/src/host/daemon/api/routines.js +36 -4
- package/src/host/daemon/api/runtimes.js +74 -39
- package/src/host/daemon/api/sessions-search.js +7 -2
- package/src/host/daemon/api/sessions.js +44 -2
- package/src/host/daemon/api/shared.js +127 -20
- package/src/host/daemon/api/skills.js +11 -4
- package/src/host/daemon/api/super-agent.js +384 -53
- package/src/host/daemon/api/tasks.js +180 -10
- package/src/host/daemon/api/telegram.js +11 -10
- package/src/host/daemon/api/thread-faces.js +159 -0
- package/src/host/daemon/api/top-level.js +3 -3
- package/src/host/daemon/api/transcribe.js +11 -10
- package/src/host/daemon/api/tts.js +97 -4
- package/src/host/daemon/api/turn-abort.js +23 -0
- package/src/host/daemon/api/turns.js +49 -0
- package/src/host/daemon/api/voice.js +5 -4
- package/src/host/daemon/api/web.js +98 -0
- package/src/host/daemon/api.js +39 -0
- package/src/host/daemon/delivery-sweep.js +58 -0
- package/src/host/daemon/desktop-ws.js +5 -23
- package/src/host/daemon/events-ws.js +273 -0
- package/src/host/daemon/index.js +59 -15
- package/src/host/daemon/plugins/desktop/index.js +17 -4
- package/src/host/daemon/plugins/telegram/index.js +78 -40
- package/src/host/daemon/pty-bridge.py +99 -0
- package/src/host/daemon/routines-scheduler.js +1 -0
- package/src/host/daemon/smoke.js +1 -2
- package/src/host/daemon/terminal-ws.js +132 -0
- package/src/host/daemon/tts-keepwarm.js +87 -0
- package/src/host/daemon/wakeup.js +11 -6
- package/src/host/daemon/whisper-server.js +44 -0
- package/src/host/daemon/whisper-server.py +70 -13
- package/src/host/daemon/ws-auth.js +28 -0
- package/src/interfaces/android/app/build.gradle +42 -0
- package/src/interfaces/android/app/proguard-rules.pro +4 -0
- package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
- package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
- package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
- package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
- package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
- package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
- package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
- package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
- package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
- package/src/interfaces/android/build.gradle +3 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
- package/src/interfaces/android/gradle.properties +3 -0
- package/src/interfaces/android/gradlew +248 -0
- package/src/interfaces/android/gradlew.bat +82 -0
- package/src/interfaces/android/settings.gradle +18 -0
- package/src/interfaces/cli/commands/a2a.js +145 -4
- package/src/interfaces/cli/commands/agent.js +247 -22
- package/src/interfaces/cli/commands/code.js +1 -1
- package/src/interfaces/cli/commands/commitment.js +5 -0
- package/src/interfaces/cli/commands/config.js +85 -6
- package/src/interfaces/cli/commands/exec.js +90 -1
- package/src/interfaces/cli/commands/image.js +314 -0
- package/src/interfaces/cli/commands/mcp.js +87 -23
- package/src/interfaces/cli/commands/memory.js +35 -22
- package/src/interfaces/cli/commands/panel.js +94 -0
- package/src/interfaces/cli/commands/profile.js +14 -0
- package/src/interfaces/cli/commands/project.js +29 -0
- package/src/interfaces/cli/commands/routine.js +45 -10
- package/src/interfaces/cli/commands/runtime.js +30 -7
- package/src/interfaces/cli/commands/session.js +90 -38
- package/src/interfaces/cli/commands/sessions.js +35 -2
- package/src/interfaces/cli/commands/skills.js +15 -9
- package/src/interfaces/cli/commands/status.js +2 -3
- package/src/interfaces/cli/commands/task.js +54 -5
- package/src/interfaces/cli/commands/telegram.js +12 -4
- package/src/interfaces/cli/commands/transcribe.js +177 -0
- package/src/interfaces/cli/help/index.js +311 -72
- package/src/interfaces/cli/http.js +61 -13
- package/src/interfaces/cli/index.js +1 -1
- package/src/interfaces/cli/routes/agent.js +5 -4
- package/src/interfaces/cli/routes/commitment.js +3 -2
- package/src/interfaces/cli/routes/config.js +7 -2
- package/src/interfaces/cli/routes/image.js +11 -0
- package/src/interfaces/cli/routes/index.js +2 -0
- package/src/interfaces/cli/routes/log.js +1 -1
- package/src/interfaces/cli/routes/memory.js +3 -2
- package/src/interfaces/cli/routes/panel.js +15 -2
- package/src/interfaces/cli/routes/profile.js +3 -2
- package/src/interfaces/cli/routes/transcribe.js +10 -0
- package/src/interfaces/cli/stdin.js +29 -0
- package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
- package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
- package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
- package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
- package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
- package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
- package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
- package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
- package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
- package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
- package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
- package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
- package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
- package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
- package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
- package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
- package/src/interfaces/desktop/assets/notification.mp3 +0 -0
- package/src/interfaces/desktop/main.js +473 -29
- package/src/interfaces/desktop/mascot-blobs.js +41 -0
- package/src/interfaces/desktop/mascot-preload.js +32 -0
- package/src/interfaces/desktop/mascot.css +186 -0
- package/src/interfaces/desktop/mascot.html +40 -0
- package/src/interfaces/desktop/mascot.js +163 -0
- package/src/interfaces/desktop/preload.js +10 -0
- package/src/interfaces/desktop/renderer.js +308 -48
- package/src/interfaces/desktop/style.css +34 -0
- package/src/interfaces/mcp-server/index.js +87 -0
- package/src/interfaces/tui/_shims/util-locale.ts +0 -2
- package/src/interfaces/tui/app.tsx +0 -6
- package/src/interfaces/tui/attach.ts +0 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
- package/src/interfaces/tui/plugin/api.tsx +0 -3
- package/src/interfaces/tui/plugin/runtime.ts +0 -3
- package/src/interfaces/tui/thread.ts +0 -16
- package/src/interfaces/web/README.md +22 -14
- package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
- package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
- package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/dist/index.html +22 -6
- package/src/interfaces/web/dist/index.html.br +0 -0
- package/src/interfaces/web/dist/index.html.gz +0 -0
- package/src/interfaces/web/dist/manifest.webmanifest +25 -0
- package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/dist/sw.js +106 -0
- package/src/interfaces/web/dist/sw.js.br +0 -0
- package/src/interfaces/web/dist/sw.js.gz +0 -0
- package/src/interfaces/web/eslint.config.js +83 -0
- package/src/interfaces/web/index.html +20 -4
- package/src/interfaces/web/package-lock.json +1651 -1280
- package/src/interfaces/web/package.json +9 -10
- package/src/interfaces/web/pnpm-lock.yaml +867 -869
- package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/public/manifest.webmanifest +25 -0
- package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/public/sw.js +106 -0
- package/src/interfaces/web/src/App.tsx +106 -10
- package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
- package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
- package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
- package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
- package/src/interfaces/web/src/components/Combobox.tsx +201 -0
- package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
- package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
- package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
- package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
- package/src/interfaces/web/src/components/Roby.tsx +5 -3
- package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
- package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
- package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
- package/src/interfaces/web/src/components/Toast.tsx +50 -14
- package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
- package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
- package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
- package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
- package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
- package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
- package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
- package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
- package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
- package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
- package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
- package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
- package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
- package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
- package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
- package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
- package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
- package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
- package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
- package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
- package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
- package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
- package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
- package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
- package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
- package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
- package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
- package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
- package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
- package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
- package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
- package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
- package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
- package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
- package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
- package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
- package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
- package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
- package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
- package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
- package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
- package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
- package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
- package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
- package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
- package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
- package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
- package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
- package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
- package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
- package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
- package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
- package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
- package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
- package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
- package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
- package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
- package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
- package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
- package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
- package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
- package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
- package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
- package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
- package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
- package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
- package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
- package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
- package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
- package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
- package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
- package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
- package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
- package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
- package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
- package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
- package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
- package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
- package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
- package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
- package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
- package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
- package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
- package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
- package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
- package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
- package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
- package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
- package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
- package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
- package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
- package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
- package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
- package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
- package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
- package/src/interfaces/web/src/components/ui.tsx +62 -23
- package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
- package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
- package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
- package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
- package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
- package/src/interfaces/web/src/constants/index.ts +1 -0
- package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
- package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
- package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
- package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
- package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
- package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
- package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
- package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
- package/src/interfaces/web/src/i18n/en.ts +832 -175
- package/src/interfaces/web/src/i18n/es.ts +841 -188
- package/src/interfaces/web/src/lib/api/agents.ts +23 -4
- package/src/interfaces/web/src/lib/api/code.ts +17 -0
- package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
- package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
- package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
- package/src/interfaces/web/src/lib/api/engines.ts +14 -0
- package/src/interfaces/web/src/lib/api/groups.ts +93 -0
- package/src/interfaces/web/src/lib/api/images.ts +193 -0
- package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
- package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
- package/src/interfaces/web/src/lib/api/media.ts +126 -0
- package/src/interfaces/web/src/lib/api/net.ts +44 -0
- package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
- package/src/interfaces/web/src/lib/api/projects.ts +9 -1
- package/src/interfaces/web/src/lib/api/routines.ts +9 -1
- package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
- package/src/interfaces/web/src/lib/api/skills.ts +8 -0
- package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
- package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
- package/src/interfaces/web/src/lib/api/tools.ts +2 -0
- package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
- package/src/interfaces/web/src/lib/api/turns.ts +20 -0
- package/src/interfaces/web/src/lib/api/voice.ts +72 -2
- package/src/interfaces/web/src/lib/api.ts +3 -0
- package/src/interfaces/web/src/lib/channels.ts +214 -0
- package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
- package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
- package/src/interfaces/web/src/lib/code-context.ts +0 -2
- package/src/interfaces/web/src/lib/http.ts +51 -17
- package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
- package/src/interfaces/web/src/lib/live.ts +252 -0
- package/src/interfaces/web/src/lib/net.ts +211 -0
- package/src/interfaces/web/src/lib/notify.ts +331 -0
- package/src/interfaces/web/src/lib/projectNav.ts +40 -0
- package/src/interfaces/web/src/lib/pwa.ts +115 -0
- package/src/interfaces/web/src/lib/qvox.ts +24 -0
- package/src/interfaces/web/src/lib/slug.ts +3 -0
- package/src/interfaces/web/src/lib/tone.ts +150 -0
- package/src/interfaces/web/src/main.tsx +15 -4
- package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
- package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
- package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
- package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
- package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
- package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
- package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
- package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
- package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
- package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
- package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
- package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
- package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
- package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
- package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
- package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
- package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
- package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
- package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
- package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
- package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
- package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
- package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
- package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
- package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
- package/src/interfaces/web/src/styles.css +106 -31
- package/src/interfaces/web/src/types/daemon.ts +246 -2
- package/src/interfaces/web/src/vite-env.d.ts +20 -0
- package/src/interfaces/tui/plugin/command-shim.ts +0 -109
- package/src/interfaces/web/components.json +0 -25
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
- package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
- package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
- package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
- package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
- package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
- package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
- package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
- package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
- package/src/interfaces/web/src/components/ui/card.tsx +0 -103
- package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
- package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
- package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
- package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
- package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
- package/src/interfaces/web/src/components/ui/command.tsx +0 -196
- package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
- package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
- package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
- package/src/interfaces/web/src/components/ui/field.tsx +0 -236
- package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
- package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
- package/src/interfaces/web/src/components/ui/item.tsx +0 -201
- package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
- package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
- package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
- package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
- package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
- package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
- package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
- package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
- package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
- package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
- package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
- package/src/interfaces/web/src/components/ui/table.tsx +0 -116
- package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
- package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
- package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
|
@@ -161,10 +161,26 @@ export async function compactChannelIfNeeded(opts = {}) {
|
|
|
161
161
|
});
|
|
162
162
|
|
|
163
163
|
const models = resolveCompactModels(config);
|
|
164
|
-
const
|
|
164
|
+
const prevSummaryText = prevCompact ? String(prevCompact.body || "").trim() : "";
|
|
165
|
+
const summary = await summarizeStructured({
|
|
166
|
+
prompt,
|
|
167
|
+
models,
|
|
168
|
+
config,
|
|
169
|
+
// The new summary must subsume this one; if it comes back smaller than the
|
|
170
|
+
// state it replaces, it dropped things and is refused.
|
|
171
|
+
prevSummary: prevSummaryText,
|
|
172
|
+
onReject: ({ model, reason }) =>
|
|
173
|
+
log(`memory: compaction for ${channel}/${chat_id} refused ${model}'s summary — ${reason}`),
|
|
174
|
+
});
|
|
165
175
|
if (!summary) {
|
|
166
|
-
|
|
167
|
-
|
|
176
|
+
// Deliberately writing NOTHING. A compact record replaces the turns it
|
|
177
|
+
// covers, so a bad one is permanent amnesia while no record at all just
|
|
178
|
+
// means the raw history stays and the next turn tries again.
|
|
179
|
+
log(
|
|
180
|
+
`memory: compaction for ${channel}/${chat_id} skipped — no usable summary; ` +
|
|
181
|
+
`keeping ${compactedReal} raw turn(s)`
|
|
182
|
+
);
|
|
183
|
+
return { skipped: "no usable summary" };
|
|
168
184
|
}
|
|
169
185
|
|
|
170
186
|
const totalCovered = prevCount + compactedReal;
|
|
@@ -196,8 +196,8 @@ export function revertConsolidation(opts = {}) {
|
|
|
196
196
|
return { removed, path: SELF_MEMORY_PATH };
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
-
/** Drop day headings left with no bullets under them. */
|
|
200
|
-
function stripEmptyDays(lines) {
|
|
199
|
+
/** Drop day headings left with no bullets under them. Shared with prune.js. */
|
|
200
|
+
export function stripEmptyDays(lines) {
|
|
201
201
|
const out = [];
|
|
202
202
|
for (let i = 0; i < lines.length; i++) {
|
|
203
203
|
const isHeading = /^##\s+\d{4}-\d{2}-\d{2}/.test(lines[i].trim());
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// The shape every dated note file in APX shares: one `## YYYY-MM-DD` heading
|
|
2
|
+
// per day, one `- [HH:MM][channel] note` bullet per note, oldest day first.
|
|
3
|
+
//
|
|
4
|
+
// Three files are written this way — the super-agent's notebook
|
|
5
|
+
// (`~/.apx/memory.md`), a project's memory (`<repo>/.apc/memory.md`) and a
|
|
6
|
+
// routine's memory — and the fiddly part is the same in all three: a note
|
|
7
|
+
// written today belongs at the END of TODAY'S block, not at the end of the
|
|
8
|
+
// file. Get that wrong and the day splits into two headings the moment
|
|
9
|
+
// anything else is appended. It had been written correctly once and
|
|
10
|
+
// approximately twice more; this is the one copy.
|
|
11
|
+
//
|
|
12
|
+
// Pure — the caller owns the file I/O.
|
|
13
|
+
import { dayStamp, hourStamp } from "#core/util/time.js";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Append one note to a dated markdown log and return the new body.
|
|
17
|
+
*
|
|
18
|
+
* @param existing current file body ("" for a file that doesn't exist yet)
|
|
19
|
+
* @param note the note; newlines are flattened, one bullet per call
|
|
20
|
+
* @param opts.channel tags the bullet "[HH:MM][channel] …" so the broker and
|
|
21
|
+
* the RAG indexer can attribute it. Omitted → plain "- note".
|
|
22
|
+
* @param opts.time override the HH:MM tag (tests, backfills)
|
|
23
|
+
* @param opts.date override the day heading (tests, backfills)
|
|
24
|
+
* @param opts.header "# …" title used only when creating the file
|
|
25
|
+
*/
|
|
26
|
+
export function appendDatedBullet(existing, note, opts = {}) {
|
|
27
|
+
const text = String(note || "").trim();
|
|
28
|
+
if (!text) throw new Error("nothing to remember (empty note)");
|
|
29
|
+
|
|
30
|
+
const { channel = "", time = "", header = "" } = opts;
|
|
31
|
+
const date = opts.date || dayStamp();
|
|
32
|
+
const heading = `## ${date}`;
|
|
33
|
+
const oneLine = text.replace(/\n+/g, " ").trim();
|
|
34
|
+
const ch = String(channel || "").trim().toLowerCase();
|
|
35
|
+
const bullet = `- ${ch ? `[${time || hourStamp()}][${ch}] ` : ""}${oneLine}`;
|
|
36
|
+
|
|
37
|
+
const body = String(existing || "");
|
|
38
|
+
if (!body.trim()) {
|
|
39
|
+
return header ? `${header}\n\n${heading}\n${bullet}\n` : `${heading}\n${bullet}\n`;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const lines = body.split("\n");
|
|
43
|
+
// lastIndexOf, not includes(): a heading that merely *contains* today's date
|
|
44
|
+
// ("## 2026-01-01 — release") is not today's block, and treating it as one
|
|
45
|
+
// used to splice the bullet under whatever heading happened to come first.
|
|
46
|
+
const idx = lines.lastIndexOf(heading);
|
|
47
|
+
if (idx < 0) {
|
|
48
|
+
const sep = body.endsWith("\n") ? "" : "\n";
|
|
49
|
+
return `${body}${sep}\n${heading}\n${bullet}\n`;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// End of today's block: the next heading, or EOF. Trailing blank lines inside
|
|
53
|
+
// the block stay below the new bullet.
|
|
54
|
+
let insertAt = lines.length;
|
|
55
|
+
for (let i = idx + 1; i < lines.length; i++) {
|
|
56
|
+
if (lines[i].startsWith("## ")) {
|
|
57
|
+
insertAt = i;
|
|
58
|
+
break;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
while (insertAt > idx + 1 && lines[insertAt - 1].trim() === "") insertAt--;
|
|
62
|
+
|
|
63
|
+
lines.splice(insertAt, 0, bullet);
|
|
64
|
+
const next = lines.join("\n");
|
|
65
|
+
return next.endsWith("\n") ? next : `${next}\n`;
|
|
66
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Custom OpenAI-compatible embeddings adapter. Backs every user-added provider
|
|
2
|
+
// (config.memory.embeddings.custom.<slug>, surfaced as id "custom:<slug>") — a
|
|
3
|
+
// local or self-hosted /embeddings endpoint such as a Zen server, LiteLLM, or a
|
|
4
|
+
// llama.cpp server. Distinct from the built-in `openai` adapter in two ways:
|
|
5
|
+
// 1. the API key is OPTIONAL (local servers are often keyless), and it never
|
|
6
|
+
// borrows engines.openai.api_key — a custom endpoint gets only its own key;
|
|
7
|
+
// 2. every vector is tagged with the provider's OWN id (`custom:<slug>:model`)
|
|
8
|
+
// so two custom endpoints never collide in the index's cosine space.
|
|
9
|
+
|
|
10
|
+
import { l2normalize } from "../embeddings.js";
|
|
11
|
+
|
|
12
|
+
const DEFAULT_MODEL = "text-embedding-3-small";
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
id: "custom",
|
|
16
|
+
|
|
17
|
+
// Available once it has a base_url — the endpoint to POST to. A key is only
|
|
18
|
+
// required if the server itself demands one (checked at call time by the 401).
|
|
19
|
+
async isAvailable(config = {}) {
|
|
20
|
+
return Boolean(config.base_url);
|
|
21
|
+
},
|
|
22
|
+
|
|
23
|
+
async embed({ text, config = {}, timeoutMs = 8000, signal }) {
|
|
24
|
+
const base = String(config.base_url || "").replace(/\/$/, "");
|
|
25
|
+
if (!base) throw new Error("custom embeddings: no base_url");
|
|
26
|
+
const key = config.api_key || "";
|
|
27
|
+
const model = config.model || DEFAULT_MODEL;
|
|
28
|
+
// The provider's own id, injected by the registry — the index-space tag.
|
|
29
|
+
const tag = config._embedder_id || "custom";
|
|
30
|
+
const ctrl = new AbortController();
|
|
31
|
+
const onParentAbort = () => ctrl.abort();
|
|
32
|
+
if (signal) signal.addEventListener("abort", onParentAbort, { once: true });
|
|
33
|
+
const timer = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
34
|
+
try {
|
|
35
|
+
const res = await fetch(`${base}/embeddings`, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: {
|
|
38
|
+
...(key ? { authorization: `Bearer ${key}` } : {}),
|
|
39
|
+
"content-type": "application/json",
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({ model, input: text }),
|
|
42
|
+
signal: ctrl.signal,
|
|
43
|
+
});
|
|
44
|
+
if (!res.ok) {
|
|
45
|
+
const err = await res.text().catch(() => "");
|
|
46
|
+
throw new Error(`custom embeddings ${res.status}: ${err.slice(0, 200)}`);
|
|
47
|
+
}
|
|
48
|
+
const json = await res.json();
|
|
49
|
+
const vector = json?.data?.[0]?.embedding;
|
|
50
|
+
if (!Array.isArray(vector) || vector.length === 0) {
|
|
51
|
+
throw new Error("custom embeddings: empty vector");
|
|
52
|
+
}
|
|
53
|
+
return { vector: l2normalize(vector), embedder: `${tag}:${model}`, dim: vector.length };
|
|
54
|
+
} finally {
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
if (signal) signal.removeEventListener("abort", onParentAbort);
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
};
|
|
@@ -1,9 +1,15 @@
|
|
|
1
|
-
// Google Gemini embeddings adapter
|
|
2
|
-
//
|
|
1
|
+
// Google Gemini embeddings adapter. Free tier available with a Gemini API key,
|
|
2
|
+
// and it reuses engines.gemini.api_key rather than asking for a second one.
|
|
3
|
+
//
|
|
4
|
+
// The default used to be `text-embedding-004`, which Google has since retired:
|
|
5
|
+
// the endpoint answers 404 "not found for API version v1beta", embedOne swallows
|
|
6
|
+
// it as a provider error, and every vector silently comes back from the offline
|
|
7
|
+
// `tf` fallback instead. Pin a model that is actually served, and override it
|
|
8
|
+
// with memory.embeddings.gemini.model when Google moves again.
|
|
3
9
|
|
|
4
10
|
import { l2normalize } from "../embeddings.js";
|
|
5
11
|
|
|
6
|
-
const DEFAULT_MODEL = "
|
|
12
|
+
const DEFAULT_MODEL = "gemini-embedding-001";
|
|
7
13
|
const BASE = "https://generativelanguage.googleapis.com/v1beta";
|
|
8
14
|
|
|
9
15
|
function getKey(config = {}, parentEnginesCfg) {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
import ollama from "./ollama.js";
|
|
23
23
|
import openai from "./openai.js";
|
|
24
24
|
import gemini from "./gemini.js";
|
|
25
|
+
import custom from "./custom.js";
|
|
25
26
|
import tf from "./tf.js";
|
|
26
27
|
|
|
27
28
|
const ADAPTERS = { ollama, openai, gemini, tf };
|
|
@@ -30,7 +31,29 @@ export const EMBED_ENGINE_IDS = Object.keys(ADAPTERS);
|
|
|
30
31
|
// Local-first, then free-with-key, then paid, then offline fallback.
|
|
31
32
|
export const AUTO_PREFERENCE = ["ollama", "gemini", "openai", "tf"];
|
|
32
33
|
|
|
34
|
+
// ── Custom providers ────────────────────────────────────────────────────────
|
|
35
|
+
// Users can add any number of OpenAI-compatible /embeddings endpoints (a local
|
|
36
|
+
// Zen / LiteLLM / llama.cpp server). They live under memory.embeddings.custom
|
|
37
|
+
// .<slug> and surface with id "custom:<slug>", all backed by the custom adapter.
|
|
38
|
+
// Mirrors the TTS engine registry (src/core/voice/engines/index.js).
|
|
39
|
+
export const CUSTOM_PREFIX = "custom:";
|
|
40
|
+
|
|
41
|
+
export function isCustomId(id) {
|
|
42
|
+
return typeof id === "string" && id.startsWith(CUSTOM_PREFIX);
|
|
43
|
+
}
|
|
44
|
+
function slugOf(id) {
|
|
45
|
+
return isCustomId(id) ? id.slice(CUSTOM_PREFIX.length) : id;
|
|
46
|
+
}
|
|
47
|
+
function customEngineIds(embedCfg) {
|
|
48
|
+
return Object.keys(embedCfg?.custom || {}).map((slug) => CUSTOM_PREFIX + slug);
|
|
49
|
+
}
|
|
50
|
+
function knownIds(embedCfg) {
|
|
51
|
+
return [...EMBED_ENGINE_IDS, ...customEngineIds(embedCfg)];
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
export function getEmbedAdapter(provider) {
|
|
55
|
+
// Every custom provider is OpenAI-compatible → the custom adapter.
|
|
56
|
+
if (isCustomId(provider)) return custom;
|
|
34
57
|
const a = ADAPTERS[provider];
|
|
35
58
|
if (!a) {
|
|
36
59
|
throw new Error(
|
|
@@ -42,8 +65,8 @@ export function getEmbedAdapter(provider) {
|
|
|
42
65
|
|
|
43
66
|
export function embeddingsConfig(globalConfig) {
|
|
44
67
|
const mem = globalConfig?.memory || {};
|
|
45
|
-
//
|
|
46
|
-
//
|
|
68
|
+
// memory.embed_* are the flat defaults every config ships with. With no
|
|
69
|
+
// explicit `embeddings.ollama` block, fold them into a synthetic one.
|
|
47
70
|
const section = mem.embeddings || {};
|
|
48
71
|
if (!section.ollama && (mem.embed_model || mem.embed_base_url || mem.embed_timeout_ms)) {
|
|
49
72
|
return {
|
|
@@ -62,10 +85,17 @@ export function embeddingsConfig(globalConfig) {
|
|
|
62
85
|
}
|
|
63
86
|
|
|
64
87
|
function providerConfig(globalConfig, provider) {
|
|
65
|
-
|
|
88
|
+
const emb = embeddingsConfig(globalConfig);
|
|
89
|
+
// A custom provider's config lives under .custom.<slug>; inject its own id so
|
|
90
|
+
// the adapter tags vectors with `custom:<slug>:model` (a distinct cosine space).
|
|
91
|
+
if (isCustomId(provider)) {
|
|
92
|
+
return { ...(emb?.custom?.[slugOf(provider)] || {}), _embedder_id: provider };
|
|
93
|
+
}
|
|
94
|
+
return emb?.[provider] || {};
|
|
66
95
|
}
|
|
67
96
|
|
|
68
97
|
function isEnabled(embedCfg, id) {
|
|
98
|
+
if (isCustomId(id)) return embedCfg?.custom?.[slugOf(id)]?.enabled !== false;
|
|
69
99
|
return embedCfg?.[id]?.enabled !== false;
|
|
70
100
|
}
|
|
71
101
|
|
|
@@ -76,15 +106,17 @@ export function resolveMode(embedCfg) {
|
|
|
76
106
|
return p && p !== "auto" ? "single" : "chain";
|
|
77
107
|
}
|
|
78
108
|
|
|
79
|
-
/** Full chain order: user's
|
|
109
|
+
/** Full chain order: user's saved order (known ids only) then the rest, with tf
|
|
110
|
+
* ALWAYS last (the guaranteed offline floor). "Known" now includes every
|
|
111
|
+
* custom:<slug> so added providers can be reordered. */
|
|
80
112
|
export function resolveChainOrder(embedCfg) {
|
|
81
|
-
const
|
|
82
|
-
|
|
113
|
+
const known = knownIds(embedCfg);
|
|
114
|
+
const ordered = Array.isArray(embedCfg?.order)
|
|
115
|
+
? embedCfg.order.filter((id) => known.includes(id) && id !== "tf")
|
|
83
116
|
: [];
|
|
84
|
-
const rest = AUTO_PREFERENCE.filter((id) =>
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
return full;
|
|
117
|
+
const rest = [...AUTO_PREFERENCE.filter((id) => id !== "tf"), ...customEngineIds(embedCfg)]
|
|
118
|
+
.filter((id) => !ordered.includes(id));
|
|
119
|
+
return [...ordered, ...rest, "tf"];
|
|
88
120
|
}
|
|
89
121
|
|
|
90
122
|
/**
|
|
@@ -115,7 +147,7 @@ export async function selectEmbedEngine({ globalConfig, provider }) {
|
|
|
115
147
|
// 3. Chain mode: probe the (enabled) order, first available wins.
|
|
116
148
|
for (const id of resolveChainOrder(embedCfg)) {
|
|
117
149
|
if (id !== "tf" && !isEnabled(embedCfg, id)) continue;
|
|
118
|
-
const adapter =
|
|
150
|
+
const adapter = getEmbedAdapter(id);
|
|
119
151
|
const cfg = providerConfig(globalConfig, id);
|
|
120
152
|
try {
|
|
121
153
|
if (await adapter.isAvailable(cfg, globalConfig?.engines)) {
|
|
@@ -126,12 +158,50 @@ export async function selectEmbedEngine({ globalConfig, provider }) {
|
|
|
126
158
|
return { provider: "tf", adapter: tf, engineConfig: providerConfig(globalConfig, "tf") };
|
|
127
159
|
}
|
|
128
160
|
|
|
129
|
-
/**
|
|
161
|
+
/**
|
|
162
|
+
* The ORDERED list of engines embedOne should try this call, first to last,
|
|
163
|
+
* before the guaranteed tf floor. Unlike selectEmbedEngine (which picks ONE by
|
|
164
|
+
* isAvailable), this returns every enabled+available engine in chain order so
|
|
165
|
+
* embedOne can fall through to the next one when a call FAILS at runtime — a
|
|
166
|
+
* rate-limited (429) or down provider, not just a keyless one. tf is omitted
|
|
167
|
+
* here; embedOne appends it as the final fallback.
|
|
168
|
+
* Returns [{ provider, adapter, engineConfig }].
|
|
169
|
+
*/
|
|
170
|
+
export async function selectEmbedChain({ globalConfig }) {
|
|
171
|
+
const embedCfg = embeddingsConfig(globalConfig);
|
|
172
|
+
|
|
173
|
+
// Single mode: exactly the configured engine, no fallback (matches the mode's
|
|
174
|
+
// contract; embedOne still drops to tf if that one engine errors).
|
|
175
|
+
if (resolveMode(embedCfg) === "single") {
|
|
176
|
+
const id = embedCfg?.provider;
|
|
177
|
+
if (id && id !== "auto" && (ADAPTERS[id] || isCustomId(id))) {
|
|
178
|
+
return [{ provider: id, adapter: getEmbedAdapter(id), engineConfig: providerConfig(globalConfig, id) }];
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const out = [];
|
|
183
|
+
for (const id of resolveChainOrder(embedCfg)) {
|
|
184
|
+
if (id === "tf") continue;
|
|
185
|
+
if (!isEnabled(embedCfg, id)) continue;
|
|
186
|
+
let adapter;
|
|
187
|
+
try { adapter = getEmbedAdapter(id); } catch { continue; }
|
|
188
|
+
const cfg = providerConfig(globalConfig, id);
|
|
189
|
+
try {
|
|
190
|
+
if (await adapter.isAvailable(cfg, globalConfig?.engines)) {
|
|
191
|
+
out.push({ provider: id, adapter, engineConfig: cfg });
|
|
192
|
+
}
|
|
193
|
+
} catch { /* probe failures skip the engine */ }
|
|
194
|
+
}
|
|
195
|
+
return out;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/** Discover which engines are configured/available right now — built-ins plus
|
|
199
|
+
* every user-added custom:<slug> provider. */
|
|
130
200
|
export async function listAvailableEmbedEngines(globalConfig) {
|
|
131
201
|
const embedCfg = embeddingsConfig(globalConfig);
|
|
132
202
|
const out = [];
|
|
133
|
-
for (const id of
|
|
134
|
-
const adapter =
|
|
203
|
+
for (const id of knownIds(embedCfg)) {
|
|
204
|
+
const adapter = getEmbedAdapter(id);
|
|
135
205
|
const cfg = providerConfig(globalConfig, id);
|
|
136
206
|
let available = false;
|
|
137
207
|
try {
|
|
@@ -140,8 +210,10 @@ export async function listAvailableEmbedEngines(globalConfig) {
|
|
|
140
210
|
out.push({
|
|
141
211
|
id,
|
|
142
212
|
available,
|
|
143
|
-
|
|
213
|
+
// `_embedder_id` is injected for custom blocks, not user-set config.
|
|
214
|
+
configured: Object.keys(cfg).filter((k) => k !== "enabled" && k !== "_embedder_id").length > 0,
|
|
144
215
|
enabled: isEnabled(embedCfg, id),
|
|
216
|
+
...(isCustomId(id) ? { custom: true, label: cfg.label || slugOf(id) } : {}),
|
|
145
217
|
});
|
|
146
218
|
}
|
|
147
219
|
return out;
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
// NOTE: this module is the leaf the engine adapters import (l2normalize /
|
|
20
20
|
// tfEmbed). It also imports the registry — ESM live bindings make this safe
|
|
21
21
|
// because selectEmbedEngine is only referenced at call time, never at init.
|
|
22
|
-
import { selectEmbedEngine } from "./embed-engines/index.js";
|
|
22
|
+
import { selectEmbedEngine, selectEmbedChain } from "./embed-engines/index.js";
|
|
23
23
|
|
|
24
24
|
const TF_DIM = 256;
|
|
25
25
|
|
|
@@ -85,35 +85,57 @@ function tfResult(text) {
|
|
|
85
85
|
return { vector: v, embedder: "tf", dim: v.length };
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// The provider id inside an embedder tag ("ollama:nomic-embed-text" → "ollama",
|
|
89
|
+
// "tf" → "tf"). Used to pin a batch to whatever actually answered.
|
|
90
|
+
export function embedderProvider(embedder) {
|
|
91
|
+
return String(embedder || "tf").split(":")[0];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function tryEmbed({ adapter, engineConfig }, clean, opts) {
|
|
95
|
+
const timeoutMs = opts.timeoutMs || engineConfig?.timeout_ms || 4000;
|
|
96
|
+
const out = await adapter.embed({
|
|
97
|
+
text: clean,
|
|
98
|
+
config: engineConfig || {},
|
|
99
|
+
parentEnginesCfg: opts.globalConfig?.engines,
|
|
100
|
+
timeoutMs,
|
|
101
|
+
signal: opts.signal,
|
|
102
|
+
});
|
|
103
|
+
if (!out || !Array.isArray(out.vector) || out.vector.length === 0) {
|
|
104
|
+
throw new Error("empty vector");
|
|
105
|
+
}
|
|
106
|
+
return out;
|
|
107
|
+
}
|
|
108
|
+
|
|
88
109
|
export async function embedOne(text, opts = {}) {
|
|
89
110
|
const clean = String(text || "").slice(0, 8000);
|
|
90
111
|
if (!clean.trim()) return tfResult("");
|
|
91
112
|
if (opts.forceTf) return tfResult(clean);
|
|
92
113
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
114
|
+
// Explicit provider (test UI, batch fast-path): exactly that engine, no chain
|
|
115
|
+
// fallback — tf only if it errors. This keeps the tester honest about one
|
|
116
|
+
// provider and lets a batch pin to the engine that already won.
|
|
117
|
+
if (opts.provider && opts.provider !== "auto") {
|
|
118
|
+
try {
|
|
119
|
+
const picked = await selectEmbedEngine({ globalConfig: opts.globalConfig, provider: opts.provider });
|
|
120
|
+
return await tryEmbed(picked, clean, opts);
|
|
121
|
+
} catch {
|
|
122
|
+
return tfResult(clean);
|
|
123
|
+
}
|
|
101
124
|
}
|
|
102
125
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
} catch {
|
|
115
|
-
return tfResult(clean);
|
|
126
|
+
// Chain: walk every enabled+available engine in order and fall through to the
|
|
127
|
+
// NEXT one whenever a call fails at runtime — a rate-limited (429) or down
|
|
128
|
+
// provider, not just a keyless one. This is the "falls back to the next if one
|
|
129
|
+
// fails" the UI promises; before, a 429 on the first engine dropped straight
|
|
130
|
+
// to the offline tf floor and skipped a working local Ollama behind it.
|
|
131
|
+
let chain = [];
|
|
132
|
+
try { chain = await selectEmbedChain({ globalConfig: opts.globalConfig }); } catch { /* → tf */ }
|
|
133
|
+
for (const engine of chain) {
|
|
134
|
+
try {
|
|
135
|
+
return await tryEmbed(engine, clean, opts);
|
|
136
|
+
} catch { /* try the next engine in the chain */ }
|
|
116
137
|
}
|
|
138
|
+
return tfResult(clean);
|
|
117
139
|
}
|
|
118
140
|
|
|
119
141
|
// Embed many strings. Probes the provider once with the first item; if that
|
|
@@ -124,9 +146,15 @@ export async function embedBatch(texts, opts = {}) {
|
|
|
124
146
|
if (list.length === 0) return [];
|
|
125
147
|
const first = await embedOne(list[0], opts);
|
|
126
148
|
const out = [first];
|
|
127
|
-
|
|
149
|
+
// Pin the rest to whatever actually answered. Without this, a chain that fell
|
|
150
|
+
// past a rate-limited gemini to ollama would re-probe (and re-429) gemini for
|
|
151
|
+
// every remaining item — slow and quota-burning. tf → forceTf; a real engine →
|
|
152
|
+
// call it directly (no chain re-walk).
|
|
153
|
+
const restOpts = first.embedder === "tf"
|
|
154
|
+
? { ...opts, forceTf: true }
|
|
155
|
+
: { ...opts, provider: embedderProvider(first.embedder) };
|
|
128
156
|
for (let i = 1; i < list.length; i++) {
|
|
129
|
-
out.push(await embedOne(list[i],
|
|
157
|
+
out.push(await embedOne(list[i], restOpts));
|
|
130
158
|
}
|
|
131
159
|
return out;
|
|
132
160
|
}
|
package/src/core/memory/index.js
CHANGED
|
@@ -41,7 +41,17 @@ let _indexing = false;
|
|
|
41
41
|
function indexOnce(note) {
|
|
42
42
|
if (_indexing || !_store) return Promise.resolve();
|
|
43
43
|
_indexing = true;
|
|
44
|
-
return indexNewMessages(_store, {
|
|
44
|
+
return indexNewMessages(_store, {
|
|
45
|
+
embed: embedOptsFromConfig(_cfg),
|
|
46
|
+
projects: _projects,
|
|
47
|
+
log: note,
|
|
48
|
+
// How many chunks one pass may embed. A local embedder happily takes the
|
|
49
|
+
// default; a hosted one on a free tier does not — 1000 embed calls a minute
|
|
50
|
+
// is a 429, and a rate-limited provider degrades to `tf`, which the
|
|
51
|
+
// consistency guard then (correctly) refuses to write. Smaller passes, more
|
|
52
|
+
// of them: `memory.index_batch`.
|
|
53
|
+
...(Number(_cfg?.memory?.index_batch) > 0 ? { limit: Number(_cfg.memory.index_batch) } : {}),
|
|
54
|
+
})
|
|
45
55
|
.catch(() => {})
|
|
46
56
|
.finally(() => {
|
|
47
57
|
_indexing = false;
|
|
@@ -54,8 +64,8 @@ export function memoryEnabled(config) {
|
|
|
54
64
|
|
|
55
65
|
// The embeddings provider is resolved from config.memory.embeddings inside
|
|
56
66
|
// embedOne/embedBatch via the engine registry — so all we forward here is the
|
|
57
|
-
// live config. (
|
|
58
|
-
//
|
|
67
|
+
// live config. (The flat memory.embed_* defaults are folded into a synthetic
|
|
68
|
+
// ollama block by embed-engines/index.js.)
|
|
59
69
|
function embedOptsFromConfig(config) {
|
|
60
70
|
return { globalConfig: config };
|
|
61
71
|
}
|
|
@@ -238,24 +238,66 @@ function collectAgentMemoryChunks(store, apxHome) {
|
|
|
238
238
|
|
|
239
239
|
// Project memory (.apc/memory.md) for every registered project. Needs the
|
|
240
240
|
// registry to map id → repo path. Scoped by channel "project:<id>".
|
|
241
|
+
//
|
|
242
|
+
// BOTH halves are indexed under the same scope: the curated `.apc/memory.md` and
|
|
243
|
+
// the local `~/.apx/projects/<id>/memory.md` the agent writes. They differ in who
|
|
244
|
+
// may write them and whether git carries them — not in whether they are true, and
|
|
245
|
+
// retrieval that saw only the committed half would miss everything the agent has
|
|
246
|
+
// learned since the owner last curated.
|
|
241
247
|
function collectProjectMemoryChunks(store, projects) {
|
|
242
248
|
const fresh = [];
|
|
243
249
|
const list = typeof projects?.list === "function" ? projects.list() : Array.isArray(projects) ? projects : [];
|
|
244
250
|
for (const entry of list) {
|
|
245
251
|
const root = entry?.path;
|
|
246
252
|
if (!root) continue; // the default project (id 0) has no repo root
|
|
247
|
-
const
|
|
248
|
-
|
|
253
|
+
const files = [
|
|
254
|
+
["projmem", readIfExists(apcMemoryFile(root))],
|
|
255
|
+
["projlocalmem", entry?.storage_path || entry?.storagePath
|
|
256
|
+
? readIfExists(path.join(entry.storage_path || entry.storagePath, "memory.md"))
|
|
257
|
+
: null],
|
|
258
|
+
];
|
|
249
259
|
const channel = `project:${entry.id}`;
|
|
250
|
-
for (const
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
260
|
+
for (const [prefix, body] of files) {
|
|
261
|
+
if (body == null) continue;
|
|
262
|
+
for (const block of chunkFreeMarkdown(body)) {
|
|
263
|
+
const id = `${prefix}:${entry.id}:${fnv1aHex(block)}`;
|
|
264
|
+
if (store.hasId(id)) continue;
|
|
265
|
+
fresh.push({ id, source: "project-memory", channel, ts: "", tag: "project-memory", text: block });
|
|
266
|
+
}
|
|
254
267
|
}
|
|
255
268
|
}
|
|
256
269
|
return fresh;
|
|
257
270
|
}
|
|
258
271
|
|
|
272
|
+
// The offline fallback embedder. Everything else is a real provider space.
|
|
273
|
+
const TF_FAMILY = "tf";
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Provider family of an embedder id ("ollama:nomic-embed-text" → "ollama").
|
|
277
|
+
* Vectors are only comparable within one family.
|
|
278
|
+
*/
|
|
279
|
+
export function embedderFamily(embedder) {
|
|
280
|
+
const id = String(embedder || TF_FAMILY);
|
|
281
|
+
const cut = id.indexOf(":");
|
|
282
|
+
return cut === -1 ? id : id.slice(0, cut);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* What to do when the live embedder does not match the one the store was built
|
|
287
|
+
* with. Pure, so the policy is testable without a reachable provider.
|
|
288
|
+
*
|
|
289
|
+
* "ok" — same space (or an empty store); index normally.
|
|
290
|
+
* "reindex" — moving into a real provider space; wipe and re-embed history.
|
|
291
|
+
* "skip" — the provider is down and we would fall back to `tf`; leave the
|
|
292
|
+
* good store alone rather than mix spaces.
|
|
293
|
+
*
|
|
294
|
+
* @returns {"ok"|"reindex"|"skip"}
|
|
295
|
+
*/
|
|
296
|
+
export function reconcileEmbedder(stored, family, hasRows) {
|
|
297
|
+
if (!stored || stored === family || !hasRows) return "ok";
|
|
298
|
+
return family === TF_FAMILY ? "skip" : "reindex";
|
|
299
|
+
}
|
|
300
|
+
|
|
259
301
|
// Run one incremental indexing pass. Returns { indexed, backend }.
|
|
260
302
|
// `opts.embed` overrides embedding options (baseUrl/model/timeoutMs) for tests.
|
|
261
303
|
export async function indexNewMessages(store, opts = {}) {
|
|
@@ -270,32 +312,46 @@ export async function indexNewMessages(store, opts = {}) {
|
|
|
270
312
|
cursor.channels = cursor.channels || {};
|
|
271
313
|
|
|
272
314
|
// Embedder-consistency guard. Cosine only works within one embedder space, so
|
|
273
|
-
// the whole store must share an embedder family
|
|
274
|
-
//
|
|
275
|
-
// -
|
|
276
|
-
//
|
|
277
|
-
// -
|
|
278
|
-
//
|
|
315
|
+
// the whole store must share an embedder family. Probe the currently-active
|
|
316
|
+
// embedder and reconcile:
|
|
317
|
+
// - moving into a REAL provider space (from tf, or from another provider):
|
|
318
|
+
// wipe + full re-index so the history lives in one comparable space.
|
|
319
|
+
// - falling back to `tf` (the offline embedder — the provider is down):
|
|
320
|
+
// skip this pass entirely rather than pollute a good store with tf rows.
|
|
321
|
+
//
|
|
322
|
+
// The family used to be a boolean, "ollama" vs everything-else-is-tf. That
|
|
323
|
+
// made Gemini and OpenAI indistinguishable from the degraded fallback, so
|
|
324
|
+
// putting Gemini first while Ollama was down read as a downgrade and indexing
|
|
325
|
+
// stopped forever instead of re-indexing into the Gemini space.
|
|
279
326
|
const probe = await embedOne("apx memory embedder probe", embedOpts);
|
|
280
|
-
const family = probe.embedder
|
|
327
|
+
const family = embedderFamily(probe.embedder);
|
|
281
328
|
const stored = cursor.embedder || null;
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
cursor.channels = {};
|
|
290
|
-
log(`memory: embedder ${stored}→ollama — full re-index`);
|
|
291
|
-
} else {
|
|
292
|
-
log("memory: Ollama unavailable — skipping index to keep embedder consistent");
|
|
293
|
-
cursor.embedder = stored; // keep the good signature
|
|
294
|
-
writeCursor(cursorPath, cursor);
|
|
295
|
-
return { indexed: 0, backend: store.backend, skipped: "embedder-downgrade" };
|
|
329
|
+
const verdict = reconcileEmbedder(stored, family, store.count() > 0);
|
|
330
|
+
if (verdict === "reindex") {
|
|
331
|
+
try {
|
|
332
|
+
store.clear?.();
|
|
333
|
+
} catch {
|
|
334
|
+
/* ignore */
|
|
296
335
|
}
|
|
336
|
+
cursor.channels = {};
|
|
337
|
+
log(`memory: embedder ${stored}→${family} — full re-index`);
|
|
338
|
+
} else if (verdict === "skip") {
|
|
339
|
+
log(
|
|
340
|
+
`memory: embedding provider unavailable (would fall back to ${TF_FAMILY}) — ` +
|
|
341
|
+
`skipping index to keep the ${stored} store consistent`
|
|
342
|
+
);
|
|
343
|
+
cursor.embedder = stored; // keep the good signature
|
|
344
|
+
writeCursor(cursorPath, cursor);
|
|
345
|
+
return { indexed: 0, backend: store.backend, skipped: "embedder-downgrade" };
|
|
297
346
|
}
|
|
347
|
+
// Persist the embedder signature NOW, before doing any work. It is separate
|
|
348
|
+
// state from the per-channel cursors: those may only advance on a complete
|
|
349
|
+
// pass, but the signature describes the store as it already is. Writing it at
|
|
350
|
+
// the end meant a CAPPED pass never recorded it — so the next pass still read
|
|
351
|
+
// the old family, wiped the store, re-embedded the same first `limit` chunks,
|
|
352
|
+
// capped again, and looped forever without the index ever growing.
|
|
298
353
|
cursor.embedder = family;
|
|
354
|
+
writeCursor(cursorPath, cursor);
|
|
299
355
|
|
|
300
356
|
const { fresh: msgChunks, maxTsByChannel } = collectMessageChunks(store, cursor, messagesDir);
|
|
301
357
|
const memChunks = collectMemoryChunks(store, memoryPath);
|