@agentprojectcontext/apx 1.81.0 → 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 +21 -11
- 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
|
@@ -13,6 +13,12 @@ import { getRecentTelegramTurnsFromFs, appendGlobalMessage } from "#core/stores/
|
|
|
13
13
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
14
14
|
import { SUPERAGENT_ACTOR_ID } from "#core/identity/index.js";
|
|
15
15
|
import { applyNudgeCallback } from "#core/nudge/index.js";
|
|
16
|
+
import { recordDelivery } from "#core/stores/deliveries.js";
|
|
17
|
+
import { silenceMobilityToday } from "#core/mobility/preferences.js";
|
|
18
|
+
import { getMobilityAlert, recordMobilityResponse } from "#core/mobility/state.js";
|
|
19
|
+
import { answerMobilityAlert } from "#core/mobility/answer.js";
|
|
20
|
+
import { doneTask } from "#core/stores/tasks.js";
|
|
21
|
+
import { resolveLang } from "#core/i18n/index.js";
|
|
16
22
|
|
|
17
23
|
/**
|
|
18
24
|
* The label the user actually tapped, recovered from the keyboard attached to
|
|
@@ -52,6 +58,10 @@ export async function handleCallbackQuery(self, callbackQuery) {
|
|
|
52
58
|
await handleNudgeCallback(self, callbackQuery);
|
|
53
59
|
return;
|
|
54
60
|
}
|
|
61
|
+
if (data.startsWith("apx:mobility:")) {
|
|
62
|
+
await handleMobilityCallback(self, callbackQuery);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
55
65
|
const adapter = createTelegramConfirmAdapter({
|
|
56
66
|
token: resolveBotToken(self.channel),
|
|
57
67
|
chatId: callbackQuery.message?.chat?.id,
|
|
@@ -94,6 +104,98 @@ export async function handleCallbackQuery(self, callbackQuery) {
|
|
|
94
104
|
});
|
|
95
105
|
}
|
|
96
106
|
|
|
107
|
+
/**
|
|
108
|
+
* A proximity chip: "voy" / "hoy no" while driving, "hecho" / "todavía no"
|
|
109
|
+
* when the follow-up comes back after the trip. Each one carries the alert id
|
|
110
|
+
* (apx:mobility:<action>:<id>) because the answer has to land on the ONE place
|
|
111
|
+
* it was asked about — the owner can have two of these open at once, and a
|
|
112
|
+
* bare "yes" would close whichever came last.
|
|
113
|
+
*/
|
|
114
|
+
export async function handleMobilityAlertCallback(self, callbackQuery, action, alertId) {
|
|
115
|
+
const lang = resolveLang(self.globalConfig);
|
|
116
|
+
const alert = getMobilityAlert(alertId);
|
|
117
|
+
if (!alert) {
|
|
118
|
+
await self._answerCallback({ callback_query_id: callbackQuery.id });
|
|
119
|
+
await clearKeyboard(self, callbackQuery);
|
|
120
|
+
self.log(`telegram[${self.channel.name}] mobility alert ${alertId} is gone`);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// The answer itself lives in core (core/mobility/answer.js) so a tap here
|
|
125
|
+
// and a tap on the car card mean the same thing. This adapter supplies the
|
|
126
|
+
// one piece core cannot have: resolving the project a task lives in.
|
|
127
|
+
const { ack } = answerMobilityAlert(alertId, action, {
|
|
128
|
+
lang,
|
|
129
|
+
closeTask: (target) => {
|
|
130
|
+
const closed = closeAlertTask(self, target);
|
|
131
|
+
if (!closed) self.log(`telegram[${self.channel.name}] mobility task ${target.task_id} not found — nothing closed`);
|
|
132
|
+
return closed;
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
await self._answerCallback({ callback_query_id: callbackQuery.id, text: ack });
|
|
136
|
+
await clearKeyboard(self, callbackQuery);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Close the task the alert was about. The alert stores the project the task
|
|
141
|
+
* came from, so this resolves that project rather than searching every one —
|
|
142
|
+
* two projects can hold tasks with the same short id prefix.
|
|
143
|
+
*/
|
|
144
|
+
function closeAlertTask(self, alert) {
|
|
145
|
+
if (!alert.task_id) return false;
|
|
146
|
+
let storagePath = null;
|
|
147
|
+
try {
|
|
148
|
+
storagePath = self.projects.get(alert.project_id)?.storagePath || null;
|
|
149
|
+
} catch {
|
|
150
|
+
storagePath = null;
|
|
151
|
+
}
|
|
152
|
+
if (!storagePath) return false;
|
|
153
|
+
try {
|
|
154
|
+
return Boolean(doneTask(storagePath, alert.task_id, "mobility"));
|
|
155
|
+
} catch (error) {
|
|
156
|
+
self.log(`telegram[${self.channel.name}] could not close task: ${error.message}`);
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
export async function handleMobilityCallback(self, callbackQuery) {
|
|
162
|
+
const parts = String(callbackQuery.data || "").split(":");
|
|
163
|
+
const action = parts[2] || "";
|
|
164
|
+
const alertId = parts[3] || "";
|
|
165
|
+
if (alertId) return handleMobilityAlertCallback(self, callbackQuery, action, alertId);
|
|
166
|
+
recordMobilityResponse(action);
|
|
167
|
+
const chatId = callbackQuery.message?.chat?.id;
|
|
168
|
+
let ack = "Listo.";
|
|
169
|
+
let response = "";
|
|
170
|
+
if (action === "later") {
|
|
171
|
+
const project = self.resolveProject();
|
|
172
|
+
const original = String(callbackQuery.message?.text || "recordatorio de viaje").slice(0, 500);
|
|
173
|
+
const id = project?.storagePath ? recordDelivery(project.storagePath, {
|
|
174
|
+
agent: "super_agent",
|
|
175
|
+
agentName: "Roby",
|
|
176
|
+
routine: "mobility-reminder",
|
|
177
|
+
notify: `Recordatorio pospuesto por usuario: ${original}`,
|
|
178
|
+
priority: false,
|
|
179
|
+
project_id: project.id,
|
|
180
|
+
}) : null;
|
|
181
|
+
ack = id ? "Lo guardé para próxima ronda." : "No pude guardar el recordatorio.";
|
|
182
|
+
response = ack;
|
|
183
|
+
} else if (action === "silence") {
|
|
184
|
+
silenceMobilityToday();
|
|
185
|
+
ack = "Sin avisos de viaje por hoy.";
|
|
186
|
+
response = ack;
|
|
187
|
+
} else if (action === "yes" || action === "no") {
|
|
188
|
+
// Retired from the trip card — they asked "¿vas ahora?" and did nothing
|
|
189
|
+
// with the answer. Still handled because cards carrying them are sitting
|
|
190
|
+
// in the chat history on a phone, and a button that answers nothing is
|
|
191
|
+
// worse than an outdated one.
|
|
192
|
+
ack = action === "yes" ? "Marcado: vas ahora." : "Entendido: no vas ahora.";
|
|
193
|
+
}
|
|
194
|
+
await self._answerCallback({ callback_query_id: callbackQuery.id, text: ack });
|
|
195
|
+
await clearKeyboard(self, callbackQuery);
|
|
196
|
+
if (response && chatId) await self._send({ chat_id: chatId, text: response });
|
|
197
|
+
}
|
|
198
|
+
|
|
97
199
|
/** Best-effort: take the keyboard off a message whose buttons are now dead. */
|
|
98
200
|
async function clearKeyboard(self, callbackQuery) {
|
|
99
201
|
const chatId = callbackQuery.message?.chat?.id;
|
|
@@ -352,6 +454,7 @@ export async function runResumedTurn(self, ctx) {
|
|
|
352
454
|
saTrace,
|
|
353
455
|
streamedCount: state.streamedCount,
|
|
354
456
|
lastStreamedText: state.lastStreamedText,
|
|
457
|
+
heldCount: state.heldCount,
|
|
355
458
|
agentDisplay,
|
|
356
459
|
extraMeta: { ask_resume: true },
|
|
357
460
|
});
|
|
@@ -17,21 +17,39 @@ import { getRecentTelegramTurnsFromFs, appendGlobalMessage } from "#core/stores/
|
|
|
17
17
|
import { compactChannelIfNeeded, agentScopedMemoryBlock } from "#core/memory/index.js";
|
|
18
18
|
import { readAgents } from "#core/apc/parser.js";
|
|
19
19
|
import { buildAgentSystem } from "#core/agent/build-agent-system.js";
|
|
20
|
+
import { resolveAgentModel } from "#core/agent/agent-model.js";
|
|
20
21
|
import { resolveAgentName, SUPERAGENT_ACTOR_ID } from "#core/identity/index.js";
|
|
21
22
|
import { registerSender, resolveAllowedTools } from "#core/identity/telegram.js";
|
|
22
23
|
import { buildRelationshipBlock } from "#core/agent/index.js";
|
|
24
|
+
import { authorLine } from "#core/agent/author-line.js";
|
|
23
25
|
import { CHANNELS } from "#core/constants/channels.js";
|
|
24
26
|
import { tryResolveSkillCommand } from "#core/agent/skills/trigger.js";
|
|
25
27
|
import * as askFlow from "./ask.js";
|
|
26
|
-
import { telegramAuthorLabel } from "./helpers.js";
|
|
28
|
+
import { telegramAuthorLabel, releaseActiveRequest, isImpatientResend } from "./helpers.js";
|
|
27
29
|
import { handleIncomingPhoto } from "./inbound/photo.js";
|
|
28
30
|
import { handleIncomingAudio } from "./inbound/audio.js";
|
|
29
31
|
import { handleIncomingFile, detectIncomingFile } from "./inbound/file.js";
|
|
30
32
|
import { buildStreamHandler, runTelegramSuperAgent, telegramErrorText, sendFinalReply, runFollowupTurn } from "./reply.js";
|
|
31
33
|
import { t, resolveLang } from "#core/i18n/index.js";
|
|
34
|
+
import { isMobilitySilenceCommand, silenceMobilityToday } from "#core/mobility/preferences.js";
|
|
32
35
|
|
|
33
36
|
const nowIso = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
34
37
|
|
|
38
|
+
// One Telegram message = ONE stored record. The media handlers used to append
|
|
39
|
+
// their own row AND rewrite `text`, so dispatch's inbound log stored the same
|
|
40
|
+
// turn a second time: the viewer showed it twice, the current transcript landed
|
|
41
|
+
// in its own history (the media row was already on disk by the time we read it
|
|
42
|
+
// back), and the next turn replayed it twice more. They now return what they
|
|
43
|
+
// archived and this folds it into the single inbound record, so the file
|
|
44
|
+
// metadata (local_path, file_id, …) is not lost with the duplicate.
|
|
45
|
+
function mediaMeta(media) {
|
|
46
|
+
if (!media.length) return {};
|
|
47
|
+
return {
|
|
48
|
+
...Object.assign({}, ...media.map((m) => m.meta)),
|
|
49
|
+
media_kind: media.length === 1 ? media[0].kind : media.map((m) => m.kind),
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
35
53
|
export async function handleUpdate(self, u) {
|
|
36
54
|
self.lastUpdateAt = nowIso();
|
|
37
55
|
|
|
@@ -72,43 +90,103 @@ export async function handleUpdate(self, u) {
|
|
|
72
90
|
// Role-based tool gating for the super-agent path (guests → no tools).
|
|
73
91
|
const allowedTools = resolveAllowedTools(self.globalConfig, sender);
|
|
74
92
|
|
|
75
|
-
//
|
|
93
|
+
// What the user actually typed, needed before the interrupt decision below.
|
|
94
|
+
// Media handlers rewrite it further down; a resend is plain text, so the raw
|
|
95
|
+
// field is enough here.
|
|
96
|
+
let text = msg.text || msg.caption || "";
|
|
97
|
+
if (isMobilitySilenceCommand(text)) silenceMobilityToday();
|
|
98
|
+
|
|
99
|
+
// Default Interrupt: a new message aborts the running turn for this chat —
|
|
100
|
+
// "no, stop, do this instead". Except when the "new" message is the SAME
|
|
101
|
+
// one the turn is already working on: that is the user checking whether a
|
|
102
|
+
// quiet turn is still alive, and aborting it restarts the work from zero
|
|
103
|
+
// (see isImpatientResend). Then we let the running turn finish and say so.
|
|
76
104
|
if (chat_id) {
|
|
77
105
|
const prev = self.activeRequests.get(chat_id);
|
|
106
|
+
if (prev && isImpatientResend(prev, text)) {
|
|
107
|
+
const secs = Math.round((Date.now() - prev.startedAt) / 1000);
|
|
108
|
+
self.log(
|
|
109
|
+
`telegram[${self.channel.name}] resend of the in-flight message for chat ${chat_id} ` +
|
|
110
|
+
`(${secs}s in) — keeping the running turn`
|
|
111
|
+
);
|
|
112
|
+
// Logged so the history is honest about what was sent, flagged so the
|
|
113
|
+
// turn that eventually answers knows it was asked twice.
|
|
114
|
+
appendGlobalMessage({
|
|
115
|
+
channel: CHANNELS.TELEGRAM,
|
|
116
|
+
direction: "in",
|
|
117
|
+
type: "user",
|
|
118
|
+
actor_id: msg.from?.id ? String(msg.from.id) : author,
|
|
119
|
+
external_id: String(u.update_id),
|
|
120
|
+
author,
|
|
121
|
+
body: text,
|
|
122
|
+
meta: {
|
|
123
|
+
chat_id,
|
|
124
|
+
user_id: msg.from?.id || null,
|
|
125
|
+
message_id: msg.message_id,
|
|
126
|
+
tg_channel: self.channel.name,
|
|
127
|
+
resend_of_in_flight: true,
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
try {
|
|
131
|
+
// Its own words, from the situation — not a canned "please wait".
|
|
132
|
+
const line = await authorLine({
|
|
133
|
+
globalConfig: self.globalConfig,
|
|
134
|
+
instruction:
|
|
135
|
+
`You are ${Math.round(secs / 60) || 1} minute(s) into working on exactly this request ` +
|
|
136
|
+
`and the user just sent it again, which means the quiet made them think you stopped. ` +
|
|
137
|
+
`In ONE short line: you are still on it, and say what you are doing right now. ` +
|
|
138
|
+
`Do not restart, do not apologise at length, do not promise a time.`,
|
|
139
|
+
});
|
|
140
|
+
if (line) await self._send({ chat_id, text: line });
|
|
141
|
+
} catch (e) {
|
|
142
|
+
self.log(`telegram[${self.channel.name}] resend ack failed: ${e.message}`);
|
|
143
|
+
}
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
78
146
|
if (prev) {
|
|
79
147
|
self.log(`telegram[${self.channel.name}] interrupting previous request for chat ${chat_id}`);
|
|
80
148
|
prev.abort();
|
|
81
149
|
}
|
|
82
150
|
}
|
|
83
151
|
const abortCtrl = new AbortController();
|
|
152
|
+
// The turn's own text and start time ride on the controller so the next
|
|
153
|
+
// inbound can tell "do something else" from "are you still there".
|
|
154
|
+
abortCtrl.text = text;
|
|
155
|
+
abortCtrl.startedAt = Date.now();
|
|
84
156
|
if (chat_id) self.activeRequests.set(chat_id, abortCtrl);
|
|
85
157
|
|
|
86
|
-
let text = msg.text || msg.caption || "";
|
|
87
|
-
|
|
88
158
|
// ── Incoming media ────────────────────────────────────────────────────
|
|
89
|
-
// Photo
|
|
90
|
-
// so the rest of the pipeline treats them like a typed message
|
|
91
|
-
//
|
|
159
|
+
// Photo, voice/audio and files each download the attachment and rewrite
|
|
160
|
+
// `text` so the rest of the pipeline treats them like a typed message; the
|
|
161
|
+
// file metadata comes back in `media` and is stored on the single inbound
|
|
162
|
+
// record below. The handlers live in ./inbound/ to keep this dispatcher
|
|
163
|
+
// focused on routing. Each one
|
|
92
164
|
// injects a marker so a caption-less attachment is never an empty turn:
|
|
93
165
|
// photos an `[image]` marker (plus the pixels, as an attachment, for a
|
|
94
166
|
// multimodal engine), audio its `[audio]` transcript, files a description
|
|
95
167
|
// with the local path.
|
|
96
168
|
const attachments = [];
|
|
169
|
+
const media = []; // what the handlers downloaded, folded into the inbound record below
|
|
97
170
|
if (msg.photo && msg.photo.length > 0) {
|
|
98
|
-
let attachment;
|
|
99
|
-
({ text, attachment } = await handleIncomingPhoto(self, { msg,
|
|
171
|
+
let attachment, archived;
|
|
172
|
+
({ text, attachment, media: archived } = await handleIncomingPhoto(self, { msg, text }));
|
|
100
173
|
if (attachment) attachments.push(attachment);
|
|
174
|
+
if (archived) media.push(archived);
|
|
101
175
|
}
|
|
102
176
|
const incomingAudio = msg.voice || msg.audio;
|
|
103
177
|
if (incomingAudio && incomingAudio.file_id) {
|
|
104
|
-
|
|
178
|
+
let archived;
|
|
179
|
+
({ text, media: archived } = await handleIncomingAudio(self, { chat_id, text, incomingAudio }));
|
|
180
|
+
if (archived) media.push(archived);
|
|
105
181
|
}
|
|
106
182
|
// Documents, video, video notes and GIFs. Without this a file sent with no
|
|
107
183
|
// caption left `text` empty, the turn was dropped, and the bot answered
|
|
108
184
|
// nothing at all.
|
|
109
185
|
const incomingFile = detectIncomingFile(msg);
|
|
110
186
|
if (incomingFile) {
|
|
111
|
-
|
|
187
|
+
let archived;
|
|
188
|
+
({ text, media: archived } = await handleIncomingFile(self, { text, incoming: incomingFile }));
|
|
189
|
+
if (archived) media.push(archived);
|
|
112
190
|
}
|
|
113
191
|
|
|
114
192
|
// If there's a pending ask_questions flow for this chat AND the current
|
|
@@ -125,6 +203,7 @@ export async function handleUpdate(self, u) {
|
|
|
125
203
|
author,
|
|
126
204
|
body: text,
|
|
127
205
|
meta: {
|
|
206
|
+
...mediaMeta(media),
|
|
128
207
|
chat_id,
|
|
129
208
|
user_id: msg.from?.id || null,
|
|
130
209
|
message_id: msg.message_id,
|
|
@@ -188,6 +267,7 @@ export async function handleUpdate(self, u) {
|
|
|
188
267
|
author,
|
|
189
268
|
body: text,
|
|
190
269
|
meta: {
|
|
270
|
+
...mediaMeta(media),
|
|
191
271
|
chat_id,
|
|
192
272
|
user_id: msg.from?.id || null,
|
|
193
273
|
message_id: msg.message_id,
|
|
@@ -197,20 +277,37 @@ export async function handleUpdate(self, u) {
|
|
|
197
277
|
|
|
198
278
|
// Super-agent is ALWAYS active on Telegram: respond_with_engine === false
|
|
199
279
|
// used to silently drop user messages, which looked to the user like the
|
|
200
|
-
// bot ignored them. Honour the
|
|
280
|
+
// bot ignored them. Honour the flag only as a soft hint (skip the
|
|
201
281
|
// routed-agent shortcut so we fall straight to super-agent) but never let
|
|
202
282
|
// it short-circuit the whole reply. To genuinely silence the bot, disable
|
|
203
283
|
// the channel entirely (telegram.enabled = false in config).
|
|
204
284
|
const skipRoutedAgent = self.channel.respond_with_engine === false;
|
|
205
285
|
if (!text) return;
|
|
206
286
|
|
|
207
|
-
// Short-circuit /reset / /new:
|
|
208
|
-
//
|
|
209
|
-
//
|
|
287
|
+
// Short-circuit /reset / /new: confirm and stop. No turn runs — the one
|
|
288
|
+
// model call below writes the confirmation itself, it does not answer the
|
|
289
|
+
// command. The marker we just logged is enough — getRecentTelegramTurns
|
|
290
|
+
// will honor it for future messages.
|
|
210
291
|
if (isReset) {
|
|
211
292
|
try {
|
|
212
|
-
|
|
293
|
+
// The ack is ours to trigger, not to word: the model writes it, and the
|
|
294
|
+
// canned line is only what goes out if it can't (engine down, no model
|
|
295
|
+
// configured). See core/agent/author-line.js.
|
|
296
|
+
const lang = resolveLang(self.globalConfig);
|
|
297
|
+
// Writing it takes a second or two, which on a chat reads as nothing
|
|
298
|
+
// happening — the same indicator a normal turn puts up covers it.
|
|
299
|
+
const stopAckTyping = self._startTyping(chat_id);
|
|
300
|
+
let ack;
|
|
301
|
+
try {
|
|
302
|
+
ack = (await authorLine({
|
|
303
|
+
globalConfig: self.globalConfig,
|
|
304
|
+
instruction: "The user just cleared this conversation — from here you remember none of it and the thread starts fresh. Confirm that in one line and invite what comes next.",
|
|
305
|
+
})) || t("telegram.reset_ack", { lang });
|
|
306
|
+
} finally {
|
|
307
|
+
stopAckTyping();
|
|
308
|
+
}
|
|
213
309
|
await self._send({ chat_id, text: ack });
|
|
310
|
+
// attribution-exempt: /reset ack — a short model-authored line whose attribution the ack path does not surface.
|
|
214
311
|
appendGlobalMessage({
|
|
215
312
|
channel: CHANNELS.TELEGRAM,
|
|
216
313
|
direction: "out",
|
|
@@ -231,6 +328,11 @@ export async function handleUpdate(self, u) {
|
|
|
231
328
|
// Start "typing..." indicator. Stops when we send the reply (or fail).
|
|
232
329
|
const stopTyping = self._startTyping(chat_id);
|
|
233
330
|
|
|
331
|
+
// Detach the model turn from the poll loop. Awaiting it here used to freeze
|
|
332
|
+
// getUpdates for the whole run, so a newer Telegram message could never
|
|
333
|
+
// abort this one — Default Interrupt existed, but never fired.
|
|
334
|
+
const replyTurn = (async () => {
|
|
335
|
+
|
|
234
336
|
// Preset to the super-agent defaults so every exit path (including one where
|
|
235
337
|
// neither the routed-agent nor the super-agent branch runs) has a valid
|
|
236
338
|
// actor — the routed-agent / super-agent branches override these on success,
|
|
@@ -242,16 +344,20 @@ export async function handleUpdate(self, u) {
|
|
|
242
344
|
let replyModel = null; // model that actually produced the reply
|
|
243
345
|
let replyUsage = null; // token accounting for this turn
|
|
244
346
|
let replyTrace = null; // what the turn actually did (summarised on the message)
|
|
347
|
+
let replyJudge = null; // verdict trail, when the turn was continued past a stop
|
|
245
348
|
const projectCfg = target.config || self.globalConfig;
|
|
246
349
|
// Display name for the super-agent persona on this channel (from identity.json).
|
|
247
350
|
const agentDisplay = resolveAgentName(self.globalConfig);
|
|
248
351
|
|
|
249
|
-
// Try the project's chosen agent first (skipped
|
|
352
|
+
// Try the project's chosen agent first (skipped when the
|
|
250
353
|
// respond_with_engine === false hint asked to bypass routed agents).
|
|
251
354
|
const routeSlug = skipRoutedAgent ? null : self.channel.route_to_agent;
|
|
252
355
|
if (routeSlug) {
|
|
253
356
|
const agent = readAgents(target.path).find((a) => a.slug === routeSlug);
|
|
254
|
-
|
|
357
|
+
// An agent that inherits its model is still usable: the router resolves
|
|
358
|
+
// one for it, same as a direct chat.
|
|
359
|
+
const agentModel = agent ? await resolveAgentModel({ agent, config: projectCfg }) : null;
|
|
360
|
+
if (agent && agentModel) {
|
|
255
361
|
try {
|
|
256
362
|
const scopedMemory = await agentScopedMemoryBlock(text, { project: target, agent, config: projectCfg });
|
|
257
363
|
const system = buildAgentSystem(target, agent, {
|
|
@@ -261,18 +367,19 @@ export async function handleUpdate(self, u) {
|
|
|
261
367
|
extraParts: [relationshipBlock, scopedMemory].filter(Boolean),
|
|
262
368
|
});
|
|
263
369
|
const result = await callEngine({
|
|
264
|
-
modelId:
|
|
370
|
+
modelId: agentModel,
|
|
265
371
|
system,
|
|
266
372
|
messages: [{ role: "user", content: text }],
|
|
267
373
|
config: projectCfg,
|
|
374
|
+
signal: abortCtrl.signal,
|
|
268
375
|
});
|
|
269
376
|
replyText = result.text;
|
|
270
377
|
replyAuthor = agent.slug;
|
|
271
378
|
replyActorId = agent.slug;
|
|
272
379
|
replyKind = "agent";
|
|
273
|
-
// Fully-qualified id
|
|
274
|
-
//
|
|
275
|
-
replyModel =
|
|
380
|
+
// Fully-qualified id (provider:model) — callEngine resolves it
|
|
381
|
+
// internally and doesn't hand it back.
|
|
382
|
+
replyModel = agentModel;
|
|
276
383
|
replyUsage = result.usage || null;
|
|
277
384
|
} catch (e) {
|
|
278
385
|
self.log(`telegram[${self.channel.name}] agent reply failed: ${e.message}`);
|
|
@@ -293,13 +400,15 @@ export async function handleUpdate(self, u) {
|
|
|
293
400
|
}
|
|
294
401
|
}
|
|
295
402
|
|
|
296
|
-
// Fallback: super-agent — STREAMED
|
|
297
|
-
//
|
|
298
|
-
//
|
|
299
|
-
//
|
|
403
|
+
// Fallback: super-agent — STREAMED, but not narrated step by step. One
|
|
404
|
+
// notice goes out when work starts, the notes before every later step are
|
|
405
|
+
// held (./progress-gate.js), and the closing message carries the result;
|
|
406
|
+
// tool calls are logged but never sent (internal). The streamed turn + its
|
|
407
|
+
// final send live in ./reply.js so this dispatcher and the ask-flow resume
|
|
300
408
|
// (_runResumedTurn in the host poller) share ONE reply path — no drift.
|
|
301
409
|
let streamedCount = 0;
|
|
302
410
|
let lastStreamedText = "";
|
|
411
|
+
let heldCount = 0;
|
|
303
412
|
if (!replyText && isSuperAgentEnabled(self.globalConfig)) {
|
|
304
413
|
const { onEvent, state } = buildStreamHandler(self, { chat_id, update_id: u.update_id, agentDisplay });
|
|
305
414
|
|
|
@@ -351,6 +460,7 @@ export async function handleUpdate(self, u) {
|
|
|
351
460
|
replyKind = "superagent";
|
|
352
461
|
replyUsage = sa.usage;
|
|
353
462
|
replyTrace = sa.trace || null;
|
|
463
|
+
replyJudge = sa.judge || null;
|
|
354
464
|
replyModel = sa.model || state.model || null;
|
|
355
465
|
|
|
356
466
|
// ── ask_questions integration ────────────────────────────────────
|
|
@@ -360,7 +470,7 @@ export async function handleUpdate(self, u) {
|
|
|
360
470
|
// (via _runResumedTurn) once every answer is collected.
|
|
361
471
|
const askQuestions = askFlow.extractAskQuestionsFromTrace(sa.trace);
|
|
362
472
|
if (askQuestions && chat_id) {
|
|
363
|
-
self.activeRequests
|
|
473
|
+
releaseActiveRequest(self.activeRequests, chat_id, abortCtrl);
|
|
364
474
|
stopTyping();
|
|
365
475
|
try {
|
|
366
476
|
await self._startAskFlow({
|
|
@@ -383,12 +493,13 @@ export async function handleUpdate(self, u) {
|
|
|
383
493
|
}
|
|
384
494
|
streamedCount = state.streamedCount;
|
|
385
495
|
lastStreamedText = state.lastStreamedText;
|
|
496
|
+
heldCount = state.heldCount;
|
|
386
497
|
} catch (e) {
|
|
387
498
|
if (abortCtrl.signal.aborted) {
|
|
388
499
|
// A newer message superseded this one. Whatever streamed so far is
|
|
389
500
|
// already sent + logged; the newer message's run continues the thread.
|
|
390
501
|
self.log(`telegram[${self.channel.name}] request aborted for chat ${chat_id}`);
|
|
391
|
-
|
|
502
|
+
releaseActiveRequest(self.activeRequests, chat_id, abortCtrl);
|
|
392
503
|
stopTyping();
|
|
393
504
|
return;
|
|
394
505
|
}
|
|
@@ -402,7 +513,13 @@ export async function handleUpdate(self, u) {
|
|
|
402
513
|
}
|
|
403
514
|
}
|
|
404
515
|
|
|
405
|
-
if (
|
|
516
|
+
if (abortCtrl.signal.aborted) {
|
|
517
|
+
self.log(`telegram[${self.channel.name}] request aborted for chat ${chat_id}`);
|
|
518
|
+
releaseActiveRequest(self.activeRequests, chat_id, abortCtrl);
|
|
519
|
+
stopTyping();
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
releaseActiveRequest(self.activeRequests, chat_id, abortCtrl);
|
|
406
523
|
stopTyping();
|
|
407
524
|
await sendFinalReply(self, {
|
|
408
525
|
chat_id,
|
|
@@ -416,7 +533,14 @@ export async function handleUpdate(self, u) {
|
|
|
416
533
|
saTrace: replyTrace,
|
|
417
534
|
streamedCount,
|
|
418
535
|
lastStreamedText,
|
|
536
|
+
heldCount,
|
|
419
537
|
agentDisplay,
|
|
538
|
+
// Recoverable after the fact: this turn ran longer because a verdict said
|
|
539
|
+
// it wasn't finished, not because the model rambled.
|
|
540
|
+
extraMeta: replyJudge ? { judge: replyJudge } : {},
|
|
541
|
+
});
|
|
542
|
+
})();
|
|
543
|
+
replyTurn.catch((e) => {
|
|
544
|
+
self.log(`telegram[${self.channel.name}] reply turn crashed: ${e.message}`);
|
|
420
545
|
});
|
|
421
546
|
}
|
|
422
|
-
|
|
@@ -76,7 +76,7 @@ export function loadState() {
|
|
|
76
76
|
if (!fs.existsSync(TELEGRAM_STATE_PATH)) return { channels: {} };
|
|
77
77
|
try {
|
|
78
78
|
const raw = JSON.parse(fs.readFileSync(TELEGRAM_STATE_PATH, "utf8"));
|
|
79
|
-
return { channels: raw.channels || {}
|
|
79
|
+
return { channels: raw.channels || {} };
|
|
80
80
|
} catch {
|
|
81
81
|
return { channels: {} };
|
|
82
82
|
}
|
|
@@ -116,8 +116,9 @@ export function tokenSource(channel) {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Resolve the list of telegram channels to poll
|
|
120
|
-
*
|
|
119
|
+
* Resolve the list of telegram channels to poll. Credentials live in
|
|
120
|
+
* telegram.channels[]; with none configured we fall back to a single implicit
|
|
121
|
+
* "default" channel whose token/chat id come from the environment.
|
|
121
122
|
*/
|
|
122
123
|
export function resolveChannels(globalConfig) {
|
|
123
124
|
const tg = globalConfig.telegram || {};
|
|
@@ -135,15 +136,17 @@ export function resolveChannels(globalConfig) {
|
|
|
135
136
|
poll_interval_ms: c.poll_interval_ms || tg.poll_interval_ms || 1500,
|
|
136
137
|
}));
|
|
137
138
|
}
|
|
138
|
-
//
|
|
139
|
-
|
|
139
|
+
// Env-only mode: no channels configured, but a token is in the environment.
|
|
140
|
+
// resolveBotToken()/resolveChatId() fill the blanks from BOT_TELEGRAM_TOKEN
|
|
141
|
+
// / TELEGRAM_CHAT_ID at call time.
|
|
142
|
+
if (!process.env.BOT_TELEGRAM_TOKEN && !process.env.TELEGRAM_BOT_TOKEN) {
|
|
140
143
|
return [];
|
|
141
144
|
}
|
|
142
145
|
return [
|
|
143
146
|
{
|
|
144
147
|
name: "default",
|
|
145
|
-
bot_token:
|
|
146
|
-
chat_id:
|
|
148
|
+
bot_token: "",
|
|
149
|
+
chat_id: "",
|
|
147
150
|
route_to_agent: tg.route_to_agent || "",
|
|
148
151
|
project: null,
|
|
149
152
|
respond_with_engine: tg.respond_with_engine !== false,
|
|
@@ -155,3 +158,52 @@ export function resolveChannels(globalConfig) {
|
|
|
155
158
|
export function sleep(ms) {
|
|
156
159
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
157
160
|
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Drop this chat's AbortController only if it is still the one we own.
|
|
164
|
+
* An aborted turn used to `activeRequests.delete(chat_id)` unconditionally,
|
|
165
|
+
* which wiped the NEWER turn's controller and made the next interrupt a no-op.
|
|
166
|
+
*/
|
|
167
|
+
export function releaseActiveRequest(activeRequests, chat_id, abortCtrl) {
|
|
168
|
+
if (chat_id && activeRequests.get(chat_id) === abortCtrl) {
|
|
169
|
+
activeRequests.delete(chat_id);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Below this, a resend of the same text is impatience, not a new instruction.
|
|
174
|
+
// Past it, the run has been going long enough that "again" plausibly means
|
|
175
|
+
// "that is stuck, start over" — so the interrupt goes through as usual.
|
|
176
|
+
const RESEND_WINDOW_MS = 10 * 60_000;
|
|
177
|
+
|
|
178
|
+
/** Comparable form of a chat message: case, accents and punctuation dropped. */
|
|
179
|
+
function normalizeForResend(text) {
|
|
180
|
+
return String(text || "")
|
|
181
|
+
.toLowerCase()
|
|
182
|
+
.normalize("NFD")
|
|
183
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
184
|
+
.replace(/[^\p{L}\p{N}]+/gu, " ")
|
|
185
|
+
.trim();
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Is this inbound the SAME message the chat is already working on?
|
|
190
|
+
*
|
|
191
|
+
* Default Interrupt aborts the running turn on every new message, which is
|
|
192
|
+
* right for "no, stop, do this instead" and exactly wrong for the case that
|
|
193
|
+
* actually happens: a long turn goes quiet (one progress note per 90s), the
|
|
194
|
+
* user assumes it died and sends the same request again. The resend killed the
|
|
195
|
+
* work in flight and restarted it from zero — so the next one looked stuck too.
|
|
196
|
+
* Six resends of one message in 35 minutes, and nothing ever finished.
|
|
197
|
+
*
|
|
198
|
+
* A verbatim repeat inside the window is treated as "still here?", not as a new
|
|
199
|
+
* turn: the running work keeps its abort controller and finishes.
|
|
200
|
+
*
|
|
201
|
+
* @returns {boolean} true when the caller should let the running turn continue.
|
|
202
|
+
*/
|
|
203
|
+
export function isImpatientResend(prev, text, { now = Date.now } = {}) {
|
|
204
|
+
if (!prev?.text) return false;
|
|
205
|
+
const incoming = normalizeForResend(text);
|
|
206
|
+
if (!incoming) return false;
|
|
207
|
+
if (incoming !== normalizeForResend(prev.text)) return false;
|
|
208
|
+
return now() - (prev.startedAt || 0) < RESEND_WINDOW_MS;
|
|
209
|
+
}
|
|
@@ -6,19 +6,22 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Takes the poller instance (`self`, for logging, channel + the typing
|
|
8
8
|
// indicator) plus the parsed update context, and returns the `text` the rest of
|
|
9
|
-
// the pipeline should run — the transcript merged into any existing caption
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
// the pipeline should run — the transcript merged into any existing caption —
|
|
10
|
+
// plus the `media` metadata dispatch folds into the ONE record it writes for
|
|
11
|
+
// this update. This handler deliberately writes nothing itself: it used to
|
|
12
|
+
// append its own row while also rewriting `text`, so the same turn was stored
|
|
13
|
+
// twice (see dispatch.js).
|
|
12
14
|
import { transcribe as transcribeAudioFile } from "#core/voice/transcription.js";
|
|
13
15
|
import { resolveBotToken, telegramMediaDir } from "../helpers.js";
|
|
14
16
|
import { downloadTelegramFile } from "../media.js";
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* @param {object} self poller instance (uses self.log, self.channel, self._startTyping)
|
|
18
|
-
* @param {object} ctx {
|
|
19
|
-
* @returns {Promise<{ text: string }>} text to continue the
|
|
20
|
+
* @param {object} ctx { chat_id, text, incomingAudio }
|
|
21
|
+
* @returns {Promise<{ text: string, media: object }>} text to continue the
|
|
22
|
+
* pipeline with, and what was archived for the inbound record
|
|
20
23
|
*/
|
|
21
|
-
export async function handleIncomingAudio(self, {
|
|
24
|
+
export async function handleIncomingAudio(self, { chat_id, text, incomingAudio }) {
|
|
22
25
|
const token = resolveBotToken(self.channel);
|
|
23
26
|
const mediaDir = telegramMediaDir();
|
|
24
27
|
|
|
@@ -53,30 +56,23 @@ export async function handleIncomingAudio(self, { msg, u, author, chat_id, text,
|
|
|
53
56
|
? `[audio] ${transcript}`
|
|
54
57
|
: `[audio] (transcription unavailable${transcribeError ? ": " + transcribeError : ""})`;
|
|
55
58
|
|
|
56
|
-
appendGlobalMessage({
|
|
57
|
-
channel: CHANNELS.TELEGRAM,
|
|
58
|
-
direction: "in",
|
|
59
|
-
type: "audio",
|
|
60
|
-
actor_id: msg.from?.id ? String(msg.from.id) : author,
|
|
61
|
-
external_id: String(u.update_id),
|
|
62
|
-
author,
|
|
63
|
-
body: audioBody,
|
|
64
|
-
meta: {
|
|
65
|
-
chat_id,
|
|
66
|
-
user_id: msg.from?.id || null,
|
|
67
|
-
message_id: msg.message_id,
|
|
68
|
-
tg_channel: self.channel.name,
|
|
69
|
-
local_path: localPath,
|
|
70
|
-
file_id: incomingAudio.file_id,
|
|
71
|
-
duration: incomingAudio.duration,
|
|
72
|
-
mime_type: incomingAudio.mime_type,
|
|
73
|
-
transcription_backend: transcribeBackend,
|
|
74
|
-
transcription_error: transcribeError,
|
|
75
|
-
},
|
|
76
|
-
});
|
|
77
|
-
|
|
78
59
|
// Inject the transcribed text into `text` so the rest of the agent pipeline
|
|
79
60
|
// treats it identically to a typed message. If there was a caption alongside
|
|
80
|
-
// the audio, prepend the audio marker to it.
|
|
81
|
-
|
|
61
|
+
// the audio, prepend the audio marker to it. The file metadata rides back
|
|
62
|
+
// with it so the stored turn keeps it, download or transcription failures
|
|
63
|
+
// included.
|
|
64
|
+
return {
|
|
65
|
+
text: text ? `${audioBody}\n${text}` : audioBody,
|
|
66
|
+
media: {
|
|
67
|
+
kind: "audio",
|
|
68
|
+
meta: {
|
|
69
|
+
local_path: localPath,
|
|
70
|
+
file_id: incomingAudio.file_id,
|
|
71
|
+
duration: incomingAudio.duration,
|
|
72
|
+
mime_type: incomingAudio.mime_type,
|
|
73
|
+
transcription_backend: transcribeBackend,
|
|
74
|
+
transcription_error: transcribeError,
|
|
75
|
+
},
|
|
76
|
+
},
|
|
77
|
+
};
|
|
82
78
|
}
|