@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
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<resources>
|
|
3
|
+
<style name="AppTheme" parent="android:style/Theme.Material.NoActionBar">
|
|
4
|
+
<item name="android:fontFamily">sans</item>
|
|
5
|
+
<item name="android:colorAccent">@color/apx_green</item>
|
|
6
|
+
<item name="android:navigationBarColor">@color/apx_dark</item>
|
|
7
|
+
<item name="android:statusBarColor">@color/apx_dark</item>
|
|
8
|
+
<item name="android:windowLightStatusBar">false</item>
|
|
9
|
+
<item name="android:windowBackground">@drawable/app_background</item>
|
|
10
|
+
<item name="android:windowSplashScreenBackground">@color/apx_dark</item>
|
|
11
|
+
<item name="android:windowSplashScreenAnimatedIcon">@mipmap/ic_launcher</item>
|
|
12
|
+
<item name="android:windowSplashScreenIconBackgroundColor">@color/apx_dark</item>
|
|
13
|
+
</style>
|
|
14
|
+
</resources>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<automotiveApp>
|
|
3
|
+
<!-- The card APX already posted for chat messages. -->
|
|
4
|
+
<uses name="notification" />
|
|
5
|
+
<!-- The chip: a real screen on the head unit, drawn by ApxCarAppService.
|
|
6
|
+
It is what lets a proximity alert show four answers, which a
|
|
7
|
+
notification on this surface never can. -->
|
|
8
|
+
<uses name="template" />
|
|
9
|
+
</automotiveApp>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<network-security-config>
|
|
3
|
+
<!-- APX daemons commonly run over a trusted private LAN using HTTP. -->
|
|
4
|
+
<base-config cleartextTrafficPermitted="true">
|
|
5
|
+
<trust-anchors>
|
|
6
|
+
<certificates src="system" />
|
|
7
|
+
<certificates src="user" />
|
|
8
|
+
</trust-anchors>
|
|
9
|
+
</base-config>
|
|
10
|
+
</network-security-config>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertFalse;
|
|
4
|
+
import static org.junit.Assert.assertTrue;
|
|
5
|
+
|
|
6
|
+
import org.junit.Test;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The line this detector has to hold: Android Auto talks to the phone both
|
|
10
|
+
* when it is running and when it wants to be. Only the first is a trip.
|
|
11
|
+
*/
|
|
12
|
+
public final class AndroidAutoDetectorTest {
|
|
13
|
+
@Test
|
|
14
|
+
public void recognisesARunningProjectionSession() {
|
|
15
|
+
assertTrue(AndroidAutoDetector.isProjectionActive(
|
|
16
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "Android Auto está en ejecución"
|
|
17
|
+
));
|
|
18
|
+
assertTrue(AndroidAutoDetector.isProjectionActive(
|
|
19
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "Android Auto is running"
|
|
20
|
+
));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Test
|
|
24
|
+
public void ignoresAnInvitationToSetAndroidAutoUp() {
|
|
25
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
26
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "Tocá para configurar Android Auto"
|
|
27
|
+
));
|
|
28
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
29
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "Tap to set up Android Auto"
|
|
30
|
+
));
|
|
31
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
32
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto disponible", "Conectá tu teléfono al auto"
|
|
33
|
+
));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@Test
|
|
37
|
+
public void aDismissibleNotificationIsNeverASession() {
|
|
38
|
+
// A live projection posts a foreground-service notification, which the
|
|
39
|
+
// user cannot swipe away. Anything dismissible is an announcement.
|
|
40
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
41
|
+
AndroidAutoDetector.AUTO_PACKAGE, false, "Android Auto", "Android Auto está en ejecución"
|
|
42
|
+
));
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@Test
|
|
46
|
+
public void recognisesWhatARealHeadUnitSessionActuallyPosts() {
|
|
47
|
+
// Verbatim from a Galaxy A55 projecting to a head unit. It arrives with
|
|
48
|
+
// FLAG_NO_CLEAR | FLAG_FOREGROUND_SERVICE and NO FLAG_ONGOING_EVENT,
|
|
49
|
+
// which is why the caller must fold both flags into `persistent`.
|
|
50
|
+
assertTrue(AndroidAutoDetector.isProjectionActive(
|
|
51
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "Conectado al vehículo"
|
|
52
|
+
));
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@Test
|
|
56
|
+
public void theDeveloperHeadUnitServerIsNotACar() {
|
|
57
|
+
// Developer mode posts this while the DHU port is open. A server
|
|
58
|
+
// waiting for a head unit would otherwise pin the phone in a trip for
|
|
59
|
+
// as long as developer mode stays on.
|
|
60
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
61
|
+
AndroidAutoDetector.AUTO_PACKAGE,
|
|
62
|
+
true,
|
|
63
|
+
"Programador de Android Auto",
|
|
64
|
+
"Servidor de unidad principal en ejecución"
|
|
65
|
+
));
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@Test
|
|
69
|
+
public void otherAppsAreNeverAndroidAuto() {
|
|
70
|
+
assertFalse(AndroidAutoDetector.isAutoPackage(MapsNavigationDetector.MAPS_PACKAGE));
|
|
71
|
+
assertFalse(AndroidAutoDetector.isProjectionActive(
|
|
72
|
+
MapsNavigationDetector.MAPS_PACKAGE, true, "Navegando", "Android Auto está en ejecución"
|
|
73
|
+
));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@Test
|
|
77
|
+
public void anOngoingSessionInAnUntranslatedLocaleStillCounts() {
|
|
78
|
+
// The running-terms list cannot cover every language Android Auto
|
|
79
|
+
// ships in; an ongoing notification from the projection app that is
|
|
80
|
+
// not an offer is a session in all of them.
|
|
81
|
+
assertTrue(AndroidAutoDetector.isProjectionActive(
|
|
82
|
+
AndroidAutoDetector.AUTO_PACKAGE, true, "Android Auto", "自動車モードで実行中"
|
|
83
|
+
));
|
|
84
|
+
}
|
|
85
|
+
}
|
package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertNull;
|
|
5
|
+
import static org.junit.Assert.assertTrue;
|
|
6
|
+
|
|
7
|
+
import org.junit.Before;
|
|
8
|
+
import org.junit.Test;
|
|
9
|
+
|
|
10
|
+
import java.util.List;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* What the head unit is showing, and what it must stop showing.
|
|
14
|
+
*
|
|
15
|
+
* The screens themselves need the template host to draw, so this covers the
|
|
16
|
+
* half that does not: which alerts are live, in what order, and that answering
|
|
17
|
+
* one anywhere takes it off the car.
|
|
18
|
+
*/
|
|
19
|
+
public final class CarAlertStoreTest {
|
|
20
|
+
|
|
21
|
+
private static MessageFrameParser.MobilityAlert alert(String id, String title) {
|
|
22
|
+
return new MessageFrameParser.MobilityAlert(
|
|
23
|
+
id, title, "Farmacia", "Av. San Martin 1234", title + " cerca", "1.4 km", "Comprar algo",
|
|
24
|
+
-41.13, -71.31, "https://maps/nav", "https://maps/stop",
|
|
25
|
+
List.of(new MessageFrameParser.Action("navigate", "Navegar ahora"))
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@Before
|
|
30
|
+
public void reset() {
|
|
31
|
+
CarAlertStore.clear();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@Test
|
|
35
|
+
public void keepsAlertsNewestLast() {
|
|
36
|
+
CarAlertStore.put(alert("a", "Farmacia"));
|
|
37
|
+
CarAlertStore.put(alert("b", "Ferretería"));
|
|
38
|
+
assertEquals(List.of("a", "b"), CarAlertStore.all().stream()
|
|
39
|
+
.map(MessageFrameParser.MobilityAlert::id).toList());
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@Test
|
|
43
|
+
public void reSendingAnAlertReplacesItInsteadOfDuplicatingIt() {
|
|
44
|
+
// The daemon can re-push a card — a phone that reconnects mid-drive
|
|
45
|
+
// gets the live set again. Two rows for one place would read as two
|
|
46
|
+
// errands at the same shop.
|
|
47
|
+
CarAlertStore.put(alert("a", "Farmacia"));
|
|
48
|
+
CarAlertStore.put(alert("a", "Farmacia del Puente"));
|
|
49
|
+
assertEquals(1, CarAlertStore.all().size());
|
|
50
|
+
assertEquals("Farmacia del Puente", CarAlertStore.all().get(0).title());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
public void dropsTheOldestPastTheCap() {
|
|
55
|
+
// A car screen is read at speed. Past a handful nobody is choosing, and
|
|
56
|
+
// nothing here would ever forget on its own during a long drive.
|
|
57
|
+
for (int i = 0; i < 8; i++) CarAlertStore.put(alert("a" + i, "Lugar " + i));
|
|
58
|
+
List<String> ids = CarAlertStore.all().stream()
|
|
59
|
+
.map(MessageFrameParser.MobilityAlert::id).toList();
|
|
60
|
+
assertEquals(5, ids.size());
|
|
61
|
+
assertEquals(List.of("a3", "a4", "a5", "a6", "a7"), ids);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
@Test
|
|
65
|
+
public void answeringAnywhereTakesItOffTheCar() {
|
|
66
|
+
CarAlertStore.put(alert("a", "Farmacia"));
|
|
67
|
+
CarAlertStore.remove("a");
|
|
68
|
+
assertTrue(CarAlertStore.all().isEmpty());
|
|
69
|
+
assertNull(CarAlertStore.get("a"));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@Test
|
|
73
|
+
public void theTripEndingClearsEverything() {
|
|
74
|
+
CarAlertStore.put(alert("a", "Farmacia"));
|
|
75
|
+
CarAlertStore.put(alert("b", "Ferretería"));
|
|
76
|
+
CarAlertStore.clear();
|
|
77
|
+
assertTrue(CarAlertStore.all().isEmpty());
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Test
|
|
81
|
+
public void aScreenIsToldWhenTheSetMoves() {
|
|
82
|
+
int[] calls = {0};
|
|
83
|
+
Runnable listener = () -> calls[0]++;
|
|
84
|
+
CarAlertStore.addListener(listener);
|
|
85
|
+
CarAlertStore.put(alert("a", "Farmacia"));
|
|
86
|
+
CarAlertStore.remove("a");
|
|
87
|
+
assertEquals(2, calls[0]);
|
|
88
|
+
|
|
89
|
+
// A screen that has gone away must stop being called, or the store
|
|
90
|
+
// holds a dead Screen for the rest of the drive.
|
|
91
|
+
CarAlertStore.removeListener(listener);
|
|
92
|
+
CarAlertStore.put(alert("b", "Ferretería"));
|
|
93
|
+
assertEquals(2, calls[0]);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
@Test
|
|
97
|
+
public void removingSomethingThatIsNotThereTellsNobody() {
|
|
98
|
+
int[] calls = {0};
|
|
99
|
+
CarAlertStore.addListener(() -> calls[0]++);
|
|
100
|
+
CarAlertStore.remove("never-existed");
|
|
101
|
+
CarAlertStore.clear(); // already empty
|
|
102
|
+
assertEquals(0, calls[0]);
|
|
103
|
+
}
|
|
104
|
+
}
|
package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertThrows;
|
|
5
|
+
|
|
6
|
+
import org.junit.Test;
|
|
7
|
+
|
|
8
|
+
public final class DaemonAddressTest {
|
|
9
|
+
@Test
|
|
10
|
+
public void normalizesLanAddress() {
|
|
11
|
+
assertEquals("http://192.0.2.20:7430", DaemonAddress.normalize("192.0.2.20:7430/mobile"));
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
@Test
|
|
15
|
+
public void keepsHttpsAddress() {
|
|
16
|
+
assertEquals("https://apx.example.com", DaemonAddress.normalize("https://apx.example.com/mobile"));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
@Test
|
|
20
|
+
public void rejectsUnsupportedScheme() {
|
|
21
|
+
assertThrows(IllegalArgumentException.class, () -> DaemonAddress.normalize("ftp://example.com"));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertFalse;
|
|
4
|
+
import static org.junit.Assert.assertTrue;
|
|
5
|
+
|
|
6
|
+
import org.junit.Test;
|
|
7
|
+
|
|
8
|
+
public final class MapsNavigationDetectorTest {
|
|
9
|
+
@Test
|
|
10
|
+
public void acceptsMapsNavigationCategory() {
|
|
11
|
+
assertTrue(MapsNavigationDetector.isLikelyNavigation(
|
|
12
|
+
MapsNavigationDetector.MAPS_PACKAGE,
|
|
13
|
+
"navigation",
|
|
14
|
+
true,
|
|
15
|
+
"Google Maps",
|
|
16
|
+
"Ruta activa"
|
|
17
|
+
));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@Test
|
|
21
|
+
public void acceptsSpanishTurnGuidanceWithoutCategory() {
|
|
22
|
+
assertTrue(MapsNavigationDetector.isLikelyNavigation(
|
|
23
|
+
MapsNavigationDetector.MAPS_PACKAGE,
|
|
24
|
+
null,
|
|
25
|
+
true,
|
|
26
|
+
"Continúa por Avenida Belgrano",
|
|
27
|
+
"Gira a la derecha en 500 m"
|
|
28
|
+
));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@Test
|
|
32
|
+
public void rejectsOtherAppsAndNonOngoingMapsNotices() {
|
|
33
|
+
assertFalse(MapsNavigationDetector.isLikelyNavigation(
|
|
34
|
+
"org.example.maps",
|
|
35
|
+
"navigation",
|
|
36
|
+
true,
|
|
37
|
+
"Navegando",
|
|
38
|
+
"5 min"
|
|
39
|
+
));
|
|
40
|
+
assertFalse(MapsNavigationDetector.isLikelyNavigation(
|
|
41
|
+
MapsNavigationDetector.MAPS_PACKAGE,
|
|
42
|
+
null,
|
|
43
|
+
false,
|
|
44
|
+
"Nuevo lugar recomendado",
|
|
45
|
+
"Cerca tuyo"
|
|
46
|
+
));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@Test
|
|
50
|
+
public void extractsSamsungNavigationDestination() {
|
|
51
|
+
assertTrue(MapsNavigationDetector.destinationFrom(
|
|
52
|
+
"en dirección a Parque Nacional Laguna Blanca"
|
|
53
|
+
).equals("Parque Nacional Laguna Blanca"));
|
|
54
|
+
assertTrue(MapsNavigationDetector.destinationFrom(
|
|
55
|
+
"heading to Central Station"
|
|
56
|
+
).equals("Central Station"));
|
|
57
|
+
assertTrue(MapsNavigationDetector.destinationFrom(
|
|
58
|
+
"Estoy yendo a La Anónima km 4"
|
|
59
|
+
).equals("La Anónima km 4"));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Test
|
|
63
|
+
public void rejectsHonorTurnInstructionAsDestination() {
|
|
64
|
+
assertTrue(MapsNavigationDetector.destinationFrom(
|
|
65
|
+
"Dirígete hacia Parque Nacional Laguna Blanca",
|
|
66
|
+
"Llegada: 5:55 p. m."
|
|
67
|
+
).isBlank());
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertFalse;
|
|
5
|
+
import static org.junit.Assert.assertTrue;
|
|
6
|
+
|
|
7
|
+
import org.junit.Test;
|
|
8
|
+
|
|
9
|
+
public final class MapsShareIntentParserTest {
|
|
10
|
+
@Test
|
|
11
|
+
public void extractsDestinationFromMapsDirectionsUrl() {
|
|
12
|
+
String shared = "Mirá mi viaje https://www.google.com/maps/dir/?api=1&destination=La+Anonima+Km+4&travelmode=driving";
|
|
13
|
+
|
|
14
|
+
assertTrue(MapsShareIntentParser.isGoogleMapsShare(shared));
|
|
15
|
+
assertEquals("La Anonima Km 4", MapsShareIntentParser.destinationFrom(shared));
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Test
|
|
19
|
+
public void keepsLiveMapsShortLinkWhenDestinationIsOpaque() {
|
|
20
|
+
String shared = "Estoy en camino. Consulta el progreso de mi viaje y la hora de llegada en Maps: https://maps.app.goo.gl/AbCdEf123";
|
|
21
|
+
|
|
22
|
+
assertTrue(MapsShareIntentParser.isGoogleMapsShare(shared));
|
|
23
|
+
assertEquals("https://maps.app.goo.gl/AbCdEf123", MapsShareIntentParser.destinationFrom(shared));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Test
|
|
27
|
+
public void rejectsGenericTextShares() {
|
|
28
|
+
assertFalse(MapsShareIntentParser.isGoogleMapsShare("comprar cartulina"));
|
|
29
|
+
assertEquals("", MapsShareIntentParser.destinationFrom("comprar cartulina"));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertFalse;
|
|
5
|
+
import static org.junit.Assert.assertNull;
|
|
6
|
+
import static org.junit.Assert.assertTrue;
|
|
7
|
+
|
|
8
|
+
import org.junit.Test;
|
|
9
|
+
|
|
10
|
+
import java.util.List;
|
|
11
|
+
|
|
12
|
+
public final class MessageFrameParserTest {
|
|
13
|
+
/** The lines alone, for the assertions that are about wording. */
|
|
14
|
+
private static List<String> lines(String frame) {
|
|
15
|
+
return MessageFrameParser.notices(frame).stream().map(MessageFrameParser.Notice::text).toList();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Test
|
|
19
|
+
public void prefersDaemonNotificationsAndTreatsEmptyAsNoNews() {
|
|
20
|
+
String ready = """
|
|
21
|
+
{"type":"messages","notifications":["sofia respondió en Telegram"],"events":[
|
|
22
|
+
{"direction":"in","channel":"telegram"}
|
|
23
|
+
]}
|
|
24
|
+
""";
|
|
25
|
+
assertEquals(List.of("sofia respondió en Telegram"), lines(ready));
|
|
26
|
+
|
|
27
|
+
String ownerSend = """
|
|
28
|
+
{"type":"messages","notifications":[],"events":[
|
|
29
|
+
{"direction":"in","channel":"telegram","type":"user"}
|
|
30
|
+
]}
|
|
31
|
+
""";
|
|
32
|
+
assertTrue(MessageFrameParser.notices(ownerSend).isEmpty());
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@Test
|
|
36
|
+
public void readsTheChannelEachNoticeIsAboutWhenTheDaemonTagsThem() {
|
|
37
|
+
String frame = """
|
|
38
|
+
{"type":"messages","notices":[
|
|
39
|
+
{"text":"Roby respondió en Telegram","channel":"telegram"},
|
|
40
|
+
{"text":"Pasá por La Anónima","channel":"mobility"}
|
|
41
|
+
],"notifications":["Roby respondió en Telegram","Pasá por La Anónima"],"events":[]}
|
|
42
|
+
""";
|
|
43
|
+
|
|
44
|
+
assertEquals(
|
|
45
|
+
List.of(
|
|
46
|
+
new MessageFrameParser.Notice("Roby respondió en Telegram", "telegram"),
|
|
47
|
+
new MessageFrameParser.Notice("Pasá por La Anónima", "mobility")
|
|
48
|
+
),
|
|
49
|
+
MessageFrameParser.notices(frame)
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@Test
|
|
54
|
+
public void anUntaggedLineFromAnOlderDaemonHasNoChannelAndSoAlwaysRings() {
|
|
55
|
+
String frame = """
|
|
56
|
+
{"type":"messages","notifications":["sofia respondió en Telegram"],"events":[]}
|
|
57
|
+
""";
|
|
58
|
+
|
|
59
|
+
List<MessageFrameParser.Notice> notices = MessageFrameParser.notices(frame);
|
|
60
|
+
assertEquals(1, notices.size());
|
|
61
|
+
assertEquals(null, notices.get(0).channel());
|
|
62
|
+
assertFalse(NotifyChannels.known(notices.get(0).channel()));
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@Test
|
|
66
|
+
public void ignoresOwnerSendAndBubblesAgentFinalsWhenDaemonOmitsTheField() {
|
|
67
|
+
String frame = """
|
|
68
|
+
{"type":"messages","events":[
|
|
69
|
+
{"direction":"in","channel":"telegram","type":"user"},
|
|
70
|
+
{"direction":"in","channel":"group","type":"user"},
|
|
71
|
+
{"direction":"out","channel":"telegram","type":"agent","streamed":true,"author":"Roby"},
|
|
72
|
+
{"direction":"out","channel":"telegram","type":"agent","author":"Roby","agent_slug":"super_agent"},
|
|
73
|
+
{"direction":"out","channel":"group","type":"agent","author":"sofia","agent_slug":"sofia"},
|
|
74
|
+
{"direction":"out","channel":"a2a","type":"agent","author":"martin","agent_slug":"martin"},
|
|
75
|
+
{"direction":"in","channel":"a2a","type":"agent","author":"martin"}
|
|
76
|
+
]}
|
|
77
|
+
""";
|
|
78
|
+
|
|
79
|
+
assertEquals(
|
|
80
|
+
List.of(
|
|
81
|
+
new MessageFrameParser.Notice("Roby respondió en Telegram", "telegram"),
|
|
82
|
+
new MessageFrameParser.Notice("sofia respondió en Grupo", "group"),
|
|
83
|
+
new MessageFrameParser.Notice("martin respondió en A2A", "a2a")
|
|
84
|
+
),
|
|
85
|
+
MessageFrameParser.notices(frame)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
@Test
|
|
90
|
+
public void rejectsMalformedFrames() {
|
|
91
|
+
assertTrue(MessageFrameParser.notices("not json").isEmpty());
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Test
|
|
95
|
+
public void readsAvatarFromHelloAndSettingsFrames() {
|
|
96
|
+
assertEquals("coral", MessageFrameParser.avatar("{\"type\":\"hello\",\"settings\":{\"super_agent\":{\"icon\":\"coral\"}}}"));
|
|
97
|
+
assertEquals("zafiro", MessageFrameParser.avatar("{\"type\":\"settings\",\"settings\":{\"super_agent\":{\"icon\":\"zafiro\"}}}"));
|
|
98
|
+
assertEquals(null, MessageFrameParser.avatar("{\"type\":\"messages\",\"events\":[]}"));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
@Test
|
|
102
|
+
public void surfacesMobilityDeliveryFromRobyAsApxNotification() {
|
|
103
|
+
String frame = """
|
|
104
|
+
{"type":"messages","events":[
|
|
105
|
+
{"direction":"out","channel":"telegram","via":"mobility_delivery","notify":"Pasá por La Anónima"}
|
|
106
|
+
]}
|
|
107
|
+
""";
|
|
108
|
+
|
|
109
|
+
// Filed on Telegram, tagged mobility: muting Telegram must not silence
|
|
110
|
+
// the car.
|
|
111
|
+
assertEquals(
|
|
112
|
+
List.of(new MessageFrameParser.Notice("Pasá por La Anónima", "mobility")),
|
|
113
|
+
MessageFrameParser.notices(frame)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// ── the proximity card ──────────────────────────────────────────────────
|
|
118
|
+
// The frame the head unit and the phone both draw. It carries its whole
|
|
119
|
+
// payload, unlike the "go re-fetch" notices above: a phone in a tunnel
|
|
120
|
+
// cannot ask, and the card has to become four buttons within a second.
|
|
121
|
+
|
|
122
|
+
private static final String ALERT_FRAME = """
|
|
123
|
+
{"type":"mobility_alert","alert":{
|
|
124
|
+
"id":"mb1234","title":"Farmacia del Puente",
|
|
125
|
+
"address":"Av. San Martin 1234, Bariloche",
|
|
126
|
+
"body":"Estas cerca de Farmacia del Puente (1.4 km). Direccion: Av. San Martin 1234, Bariloche. Tarea: Comprar ibuprofeno",
|
|
127
|
+
"distance_label":"1.4 km","task":"Comprar ibuprofeno",
|
|
128
|
+
"latitude":-41.13,"longitude":-71.31,
|
|
129
|
+
"navigate_url":"https://maps.example/nav","add_stop_url":"https://maps.example/stop",
|
|
130
|
+
"actions":[{"id":"navigate","label":"Navegar ahora"},{"id":"add_stop","label":"Sumar a la ruta"},
|
|
131
|
+
{"id":"next","label":"Para despues"},{"id":"skip","label":"No ahora"}]}}
|
|
132
|
+
""";
|
|
133
|
+
|
|
134
|
+
@Test
|
|
135
|
+
public void readsTheWholeCardIncludingTheAddress() {
|
|
136
|
+
MessageFrameParser.MobilityAlert alert = MessageFrameParser.mobilityAlert(ALERT_FRAME);
|
|
137
|
+
assertEquals("mb1234", alert.id());
|
|
138
|
+
assertEquals("Farmacia del Puente", alert.title());
|
|
139
|
+
assertEquals("Av. San Martin 1234, Bariloche", alert.address());
|
|
140
|
+
assertEquals("1.4 km", alert.distanceLabel());
|
|
141
|
+
assertEquals("Comprar ibuprofeno", alert.task());
|
|
142
|
+
assertEquals("https://maps.example/nav", alert.navigateUrl());
|
|
143
|
+
assertEquals("https://maps.example/stop", alert.addStopUrl());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
@Test
|
|
147
|
+
public void keepsTheFourAnswersInTheOrderTheDaemonSentThem() {
|
|
148
|
+
// Android renders what it is given rather than holding its own copy of
|
|
149
|
+
// the list — a fifth answer must never need a new APK.
|
|
150
|
+
MessageFrameParser.MobilityAlert alert = MessageFrameParser.mobilityAlert(ALERT_FRAME);
|
|
151
|
+
assertEquals(
|
|
152
|
+
List.of("navigate", "add_stop", "next", "skip"),
|
|
153
|
+
alert.actions().stream().map(MessageFrameParser.Action::id).toList()
|
|
154
|
+
);
|
|
155
|
+
assertEquals("Navegar ahora", alert.actions().get(0).label());
|
|
156
|
+
assertEquals("No ahora", alert.actions().get(3).label());
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@Test
|
|
160
|
+
public void missingOptionalFieldsAreNullRatherThanEmptyStrings() {
|
|
161
|
+
// The daemon omits what it does not know. A blank address rendered as
|
|
162
|
+
// "" would draw an empty line on the head unit under every place.
|
|
163
|
+
String frame = "{\"type\":\"mobility_alert\",\"alert\":{\"id\":\"mb2\",\"title\":\"Kiosco\",\"body\":\"Kiosco\"}}";
|
|
164
|
+
MessageFrameParser.MobilityAlert alert = MessageFrameParser.mobilityAlert(frame);
|
|
165
|
+
assertNull(alert.address());
|
|
166
|
+
assertNull(alert.task());
|
|
167
|
+
assertNull(alert.navigateUrl());
|
|
168
|
+
assertTrue(alert.actions().isEmpty());
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
@Test
|
|
172
|
+
public void anythingThatIsNotAnAlertFrameIsNull() {
|
|
173
|
+
assertNull(MessageFrameParser.mobilityAlert("{\"type\":\"messages\",\"notices\":[]}"));
|
|
174
|
+
assertNull(MessageFrameParser.mobilityAlert("{\"type\":\"mobility_alert\"}"));
|
|
175
|
+
// An alert with no id could never be answered — refuse it rather than
|
|
176
|
+
// drawing four buttons that go nowhere.
|
|
177
|
+
assertNull(MessageFrameParser.mobilityAlert("{\"type\":\"mobility_alert\",\"alert\":{\"title\":\"x\"}}"));
|
|
178
|
+
assertNull(MessageFrameParser.mobilityAlert("no json at all"));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertFalse;
|
|
5
|
+
import static org.junit.Assert.assertTrue;
|
|
6
|
+
|
|
7
|
+
import org.junit.Test;
|
|
8
|
+
|
|
9
|
+
public final class TravelEventGateTest {
|
|
10
|
+
@Test
|
|
11
|
+
public void waitsForKnownDestinationToRemainStable() {
|
|
12
|
+
assertEquals(
|
|
13
|
+
TravelEventGate.KNOWN_DESTINATION_SETTLE_MS,
|
|
14
|
+
TravelEventGate.delayMs(1_000L, "Onelli 444", 0L, "")
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
@Test
|
|
19
|
+
public void waitsTenMinutesBeforeUnknownTripPrompt() {
|
|
20
|
+
assertEquals(
|
|
21
|
+
TravelEventGate.UNKNOWN_DESTINATION_SETTLE_MS,
|
|
22
|
+
TravelEventGate.delayMs(1_000L, "", 0L, "")
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
@Test
|
|
27
|
+
public void suppressesRepeatedSameDestinationForThirtyMinutes() {
|
|
28
|
+
long sentAt = 10_000L;
|
|
29
|
+
assertTrue(TravelEventGate.coolingDown(sentAt + 60_000L, "Onelli 444", sentAt, "onelli 444"));
|
|
30
|
+
assertFalse(TravelEventGate.coolingDown(
|
|
31
|
+
sentAt + TravelEventGate.SAME_DESTINATION_COOLDOWN_MS,
|
|
32
|
+
"Onelli 444",
|
|
33
|
+
sentAt,
|
|
34
|
+
"Onelli 444"
|
|
35
|
+
));
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Test
|
|
39
|
+
public void appliesGlobalCooldownToDifferentDestination() {
|
|
40
|
+
long sentAt = 10_000L;
|
|
41
|
+
assertEquals(
|
|
42
|
+
TravelEventGate.DIFFERENT_DESTINATION_COOLDOWN_MS - 60_000L,
|
|
43
|
+
TravelEventGate.delayMs(sentAt + 60_000L, "Albarracín 601", sentAt, "Onelli 444")
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Test
|
|
48
|
+
public void theUnknownDestinationWaitIsShortEnoughToStillBeUseful() {
|
|
49
|
+
// Ten minutes put the trip-start message half way through a short
|
|
50
|
+
// drive. What the long wait was protecting — a destination arriving
|
|
51
|
+
// late — is handled by the listener rescheduling at 45 s when it
|
|
52
|
+
// resolves, so the settle never had to cover it.
|
|
53
|
+
assertEquals(3 * 60_000L, TravelEventGate.UNKNOWN_DESTINATION_SETTLE_MS);
|
|
54
|
+
assertTrue(
|
|
55
|
+
"an unknown destination still waits longer than a known one",
|
|
56
|
+
TravelEventGate.UNKNOWN_DESTINATION_SETTLE_MS > TravelEventGate.KNOWN_DESTINATION_SETTLE_MS
|
|
57
|
+
);
|
|
58
|
+
// And it stays under the cooldown that follows a send, so shortening it
|
|
59
|
+
// cannot turn into two cards for one drive.
|
|
60
|
+
assertTrue(
|
|
61
|
+
TravelEventGate.UNKNOWN_DESTINATION_SETTLE_MS < TravelEventGate.DIFFERENT_DESTINATION_COOLDOWN_MS
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package dev.agentprojectcontext.apx;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.assertEquals;
|
|
4
|
+
import static org.junit.Assert.assertTrue;
|
|
5
|
+
|
|
6
|
+
import org.junit.Test;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The words on the errand cards. Only the pure label logic is covered here —
|
|
10
|
+
* assembling the views needs a Context, which a plain JVM test does not have —
|
|
11
|
+
* but the labels are where the lying happens, so they are the part worth
|
|
12
|
+
* pinning down.
|
|
13
|
+
*/
|
|
14
|
+
public class TripPlacesSheetTest {
|
|
15
|
+
|
|
16
|
+
@Test
|
|
17
|
+
public void readsDistanceInTheUnitTheDriverThinksIn() {
|
|
18
|
+
assertEquals("820 m", TripPlacesSheet.distanceLabel(820));
|
|
19
|
+
assertEquals("1,2 km", TripPlacesSheet.distanceLabel(1_200).replace('.', ','));
|
|
20
|
+
// Unknown is blank, never "0 m": claiming the shop is underfoot is
|
|
21
|
+
// worse than saying nothing about how far it is.
|
|
22
|
+
assertEquals("", TripPlacesSheet.distanceLabel(-1));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
@Test
|
|
26
|
+
public void headlineIsThePlaceThenHowFar() {
|
|
27
|
+
assertEquals("La Anónima · 1.2 km".replace('.', ','),
|
|
28
|
+
TripPlacesSheet.headline("La Anónima", 1_200).replace('.', ','));
|
|
29
|
+
assertEquals("La Anónima", TripPlacesSheet.headline("La Anónima", -1));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@Test
|
|
33
|
+
public void anUnsettledErrandSaysItIsStillAChoice() {
|
|
34
|
+
// Bread can be bought at three supermarkets. Showing the nearest one
|
|
35
|
+
// without saying so would claim a decision APX has not made.
|
|
36
|
+
String line = TripPlacesSheet.stateLine("", false, 3);
|
|
37
|
+
assertTrue(line, line.startsWith("3 lugares posibles"));
|
|
38
|
+
// One candidate is the decision — nothing to disclose.
|
|
39
|
+
assertEquals("", TripPlacesSheet.stateLine("", false, 1));
|
|
40
|
+
assertEquals("Lugar elegido", TripPlacesSheet.stateLine("", true, 3));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@Test
|
|
44
|
+
public void anAnsweredErrandShowsTheAnswerAndNotTheOptions() {
|
|
45
|
+
assertEquals("Dijiste que vas", TripPlacesSheet.stateLine("go", true, 3));
|
|
46
|
+
assertEquals("Lo dejaste para otro día", TripPlacesSheet.stateLine("skip", false, 3));
|
|
47
|
+
// Declining a shop is not dropping the errand: the line has to say the
|
|
48
|
+
// difference, or the list reads as if the task were closed.
|
|
49
|
+
assertEquals("Te aviso en la siguiente", TripPlacesSheet.stateLine("next", false, 3));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@Test
|
|
53
|
+
public void theChipsCarryNoEmoji() throws Exception {
|
|
54
|
+
// The same labels reach a car head unit, where the Assistant reads them
|
|
55
|
+
// aloud — and a pin emoji comes out as its Unicode name mid-sentence.
|
|
56
|
+
String source = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(
|
|
57
|
+
"src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java")),
|
|
58
|
+
java.nio.charset.StandardCharsets.UTF_8);
|
|
59
|
+
for (String label : new String[] { "Navegar", "Sumar a la ruta", "Voy", "En la siguiente" }) {
|
|
60
|
+
int at = source.indexOf("\"" + label + "\"");
|
|
61
|
+
assertTrue("chip label missing: " + label, at > 0);
|
|
62
|
+
}
|
|
63
|
+
assertTrue("a chip label must not carry an emoji",
|
|
64
|
+
!source.contains("\"🧭") && !source.contains("\"✅") && !source.contains("\"❌") && !source.contains("\"➕"));
|
|
65
|
+
}
|
|
66
|
+
}
|