@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
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
// The one-line bubbles the desktop / Android pets show.
|
|
2
|
+
//
|
|
3
|
+
// WHY HERE, NOT IN EACH CLIENT. Desktop Electron and the Android overlay both
|
|
4
|
+
// subscribe to the same /api/events/ws feed. When each one invented its own
|
|
5
|
+
// filter they drifted: both treated the owner's own send (`direction: "in"`)
|
|
6
|
+
// as news, and skipped the thing the pet is for — an agent actually launching
|
|
7
|
+
// its closing message on Telegram, a group, or A2A. One function, attached to
|
|
8
|
+
// the frame as `notifications: string[]`, is what both surfaces render.
|
|
9
|
+
//
|
|
10
|
+
// SIGNAL, NOT DATA. A line names who spoke and where — on A2A, who spoke to
|
|
11
|
+
// whom. It never carries the body. Delivery rows may also bring a bounded
|
|
12
|
+
// `notify` headline the writer already chose (≤100 chars) — still a notice,
|
|
13
|
+
// not the message.
|
|
14
|
+
//
|
|
15
|
+
// EACH LINE CARRIES ITS CHANNEL. The text alone leaves a client with nothing to
|
|
16
|
+
// filter on: the phone has Telegram installed ON it, so an APX bubble about a
|
|
17
|
+
// Telegram reply is the same news twice, while the trip notice on the same
|
|
18
|
+
// phone is the only way that news arrives at all. So a notice is `{ text,
|
|
19
|
+
// channel }` and the surface decides which channels may ring it — the web has
|
|
20
|
+
// done that per device since lib/channels.ts; the APK could not, because what
|
|
21
|
+
// reached it was a bare string.
|
|
22
|
+
|
|
23
|
+
import { SUPERAGENT_ACTOR_ID } from "../constants/actors.js";
|
|
24
|
+
import { resolveAgentName } from "../identity/self.js";
|
|
25
|
+
|
|
26
|
+
const AGENT_FINAL_CHANNELS = new Set(["telegram", "group", "a2a"]);
|
|
27
|
+
const DELIVERY_VIA = new Set(["routine_delivery", "mobility_delivery"]);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The channels a BUBBLE can be about — not the channels APX speaks on.
|
|
31
|
+
*
|
|
32
|
+
* Five, and the list is closed by construction: three are agent finals
|
|
33
|
+
* (telegram / group / a2a) and two are deliveries that arrive with their own
|
|
34
|
+
* headline. A routine delivery is filed on `web` and a mobility one on
|
|
35
|
+
* telegram, but neither is news *about that channel* — "an errand on the way
|
|
36
|
+
* home" is not a Telegram message, and muting Telegram must not silence the
|
|
37
|
+
* car. So a delivery is tagged by what it IS, the same rule the `log` channel
|
|
38
|
+
* settled on core-side.
|
|
39
|
+
*
|
|
40
|
+
* A client shows this list as the choice; nothing else can ever ring.
|
|
41
|
+
*/
|
|
42
|
+
export const NOTICE_CHANNELS = ["telegram", "group", "a2a", "routine", "mobility"];
|
|
43
|
+
|
|
44
|
+
function channelLabel(channel) {
|
|
45
|
+
if (channel === "telegram") return "Telegram";
|
|
46
|
+
if (channel === "group") return "Grupo";
|
|
47
|
+
if (channel === "a2a") return "A2A";
|
|
48
|
+
if (!channel) return "un canal";
|
|
49
|
+
return channel.charAt(0).toUpperCase() + channel.slice(1);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function speakerName(event) {
|
|
53
|
+
const author = String(event?.author || "").trim();
|
|
54
|
+
if (author && author !== "user" && author !== "owner" && !author.startsWith("@")) return author;
|
|
55
|
+
return String(event?.agent_slug || "").trim() || "agente";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** A participant's name as a sentence should carry it.
|
|
59
|
+
*
|
|
60
|
+
* The super-agent is filed on the ledger under its ACTOR ID, so a bubble that
|
|
61
|
+
* printed the stored name said "a Super_agent" about the agent the owner calls
|
|
62
|
+
* Roby. An id is what the ledger needs to keep one thread per correspondent;
|
|
63
|
+
* it is not what a sentence about that correspondent says. Everyone else keeps
|
|
64
|
+
* the name they were addressed by — an a2a address is a slug written lowercase
|
|
65
|
+
* (`magui`), and "de magui a roby" reads as a log line rather than as news, so
|
|
66
|
+
* it gets a capital. A name that already carries its own casing (`Roby`,
|
|
67
|
+
* `iOS-bot`) is left exactly as its author wrote it. */
|
|
68
|
+
function peerLabel(name) {
|
|
69
|
+
const n = String(name || "").trim();
|
|
70
|
+
if (n === SUPERAGENT_ACTOR_ID) return resolveAgentName();
|
|
71
|
+
if (!n || n !== n.toLowerCase()) return n;
|
|
72
|
+
return n.charAt(0).toUpperCase() + n.slice(1);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** An agent's closing message on Telegram / group / A2A — not a stream chunk,
|
|
76
|
+
* not a tool row, not the owner's own send, not a delivery that already has
|
|
77
|
+
* its own headline. */
|
|
78
|
+
export function isAgentFinalEvent(event) {
|
|
79
|
+
if (!event || event.direction !== "out") return false;
|
|
80
|
+
if (event.type && event.type !== "agent") return false;
|
|
81
|
+
if (!AGENT_FINAL_CHANNELS.has(event.channel)) return false;
|
|
82
|
+
if (event.streamed === true) return false;
|
|
83
|
+
if (DELIVERY_VIA.has(event.via)) return false;
|
|
84
|
+
return true;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {object[]} events the public events already on a "messages" frame
|
|
89
|
+
* @returns {{text: string, channel: string}[]}
|
|
90
|
+
* one notice per distinct agent×channel (plus any delivery
|
|
91
|
+
* headlines), in a stable order, each tagged with the channel a
|
|
92
|
+
* client filters on. See NOTICE_CHANNELS.
|
|
93
|
+
*/
|
|
94
|
+
export function mascotNoticesFromEvents(events) {
|
|
95
|
+
const notices = [];
|
|
96
|
+
const list = Array.isArray(events) ? events : [];
|
|
97
|
+
|
|
98
|
+
for (const event of list) {
|
|
99
|
+
if (event?.via === "mobility_delivery") {
|
|
100
|
+
const notice = String(event.notify || "").trim();
|
|
101
|
+
if (notice) notices.push({ text: notice, channel: "mobility" });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
const routineByAgent = new Map();
|
|
106
|
+
for (const event of list) {
|
|
107
|
+
if (!event || event.via !== "routine_delivery" || event.channel !== "web") continue;
|
|
108
|
+
if (!event.agent_slug || event.agent_slug === "super_agent") continue;
|
|
109
|
+
routineByAgent.set(event.agent_slug, event.notify || routineByAgent.get(event.agent_slug) || "");
|
|
110
|
+
}
|
|
111
|
+
for (const [agent, notify] of routineByAgent) {
|
|
112
|
+
const notice = String(notify || "").trim();
|
|
113
|
+
notices.push({
|
|
114
|
+
text: notice ? `${agent}: ${notice}` : `${agent} te dejó un mensaje`,
|
|
115
|
+
channel: "routine",
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const finals = new Map();
|
|
120
|
+
for (const event of list) {
|
|
121
|
+
if (!isAgentFinalEvent(event)) continue;
|
|
122
|
+
const agent = speakerName(event);
|
|
123
|
+
// On A2A the pair IS the news. "martin respondió en A2A" names a channel the
|
|
124
|
+
// owner never opened and leaves out the only thing he wants to know — who
|
|
125
|
+
// reached who. The counterpart rides the event for exactly this line; when
|
|
126
|
+
// it is missing (an older row, a writer that set no `to`) the bubble falls
|
|
127
|
+
// back to naming the channel rather than inventing a recipient.
|
|
128
|
+
const to = event.channel === "a2a" ? String(event.to || "").trim() : "";
|
|
129
|
+
finals.set(`${event.channel}|${agent}|${to}`, { channel: event.channel, agent, to });
|
|
130
|
+
}
|
|
131
|
+
for (const { channel, agent, to } of finals.values()) {
|
|
132
|
+
notices.push({
|
|
133
|
+
text: to
|
|
134
|
+
? `Nuevo mensaje de ${peerLabel(agent)} a ${peerLabel(to)}`
|
|
135
|
+
: `${agent} respondió en ${channelLabel(channel)}`,
|
|
136
|
+
channel,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return notices;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The same notices as bare lines.
|
|
145
|
+
*
|
|
146
|
+
* Still the frame's `notifications`, because an APK is installed software that
|
|
147
|
+
* updates when its owner gets around to it: a phone carrying last month's build
|
|
148
|
+
* reads this field and must keep working. Desktop reads it too — the pet there
|
|
149
|
+
* has no per-channel question to answer, one screen showing everything is the
|
|
150
|
+
* whole point of it.
|
|
151
|
+
*
|
|
152
|
+
* @returns {string[]}
|
|
153
|
+
*/
|
|
154
|
+
export function mascotNotificationsFromEvents(events) {
|
|
155
|
+
return mascotNoticesFromEvents(events).map((notice) => notice.text);
|
|
156
|
+
}
|
|
@@ -10,12 +10,13 @@
|
|
|
10
10
|
// (no Chromium needed).
|
|
11
11
|
//
|
|
12
12
|
// Endpoints (mounted at /api/tools/browser by api.js):
|
|
13
|
-
// POST /navigate { url, launch_options?, allow_dangerous? }
|
|
14
|
-
// POST /
|
|
15
|
-
// POST /
|
|
16
|
-
// POST /
|
|
17
|
-
// POST /
|
|
18
|
-
// POST /
|
|
13
|
+
// POST /navigate { url, launch_options?, allow_dangerous?, snapshot? }
|
|
14
|
+
// POST /snapshot { selector?, interactive_only?, max_nodes? }
|
|
15
|
+
// POST /screenshot { selector?, ref?, full_page?, width?, height?, encoded? }
|
|
16
|
+
// POST /click { selector | ref, snapshot? }
|
|
17
|
+
// POST /type { selector | ref, text, clear?, snapshot? }
|
|
18
|
+
// POST /select { selector | ref, value, snapshot? }
|
|
19
|
+
// POST /hover { selector | ref }
|
|
19
20
|
// POST /evaluate { code }
|
|
20
21
|
// POST /get_text { selector? }
|
|
21
22
|
// POST /get_content { selector? } // raw innerHTML
|
|
@@ -35,6 +36,8 @@ const _consoleLogs = [];
|
|
|
35
36
|
|
|
36
37
|
const MAX_SCREENSHOT_BYTES = 2 * 1024 * 1024; // 2MB
|
|
37
38
|
const MAX_CONTENT_CHARS = 1 * 1024 * 1024; // 1MB
|
|
39
|
+
const MAX_SNAPSHOT_NODES = 400;
|
|
40
|
+
const MAX_SNAPSHOT_CHARS = 40 * 1024;
|
|
38
41
|
|
|
39
42
|
// Args we always pass for stability + reduced attack surface.
|
|
40
43
|
const SECURITY_ARGS = [
|
|
@@ -228,11 +231,328 @@ async function onPage(fn) {
|
|
|
228
231
|
return withContextRetry(() => fn(page));
|
|
229
232
|
}
|
|
230
233
|
|
|
234
|
+
// ---------------------------------------------------------------------------
|
|
235
|
+
// Accessibility snapshot + refs
|
|
236
|
+
// ---------------------------------------------------------------------------
|
|
237
|
+
//
|
|
238
|
+
// Why this exists. A model driving Puppeteer by CSS selector has to invent the
|
|
239
|
+
// selector out of browser_get_content's raw HTML — a megabyte of markup to find
|
|
240
|
+
// one button, and a wrong guess most of the time. Snapshot walks the RENDERED
|
|
241
|
+
// DOM instead and returns what a screen reader would announce: role, accessible
|
|
242
|
+
// name, state, one line per element, with every control stamped `ref_N`. The
|
|
243
|
+
// action tools take `{ ref }`, so the model clicks what it read rather than
|
|
244
|
+
// what it inferred.
|
|
245
|
+
//
|
|
246
|
+
// Refs live in the page as `data-apx-ref` attributes and die with it. A
|
|
247
|
+
// navigation or a re-render invalidates them; the action tools then say so by
|
|
248
|
+
// name instead of failing on a mystery selector.
|
|
249
|
+
|
|
250
|
+
// Runs INSIDE the page — must stay self-contained (page.evaluate stringifies
|
|
251
|
+
// it, so it can close over nothing from this module).
|
|
252
|
+
function collectA11yNodes({ rootSelector, interactiveOnly, maxNodes }) {
|
|
253
|
+
const SKIP_TAGS = new Set(["SCRIPT", "STYLE", "NOSCRIPT", "TEMPLATE", "HEAD", "SVG", "PATH", "IFRAME"]);
|
|
254
|
+
// Controls whose subtree the walk does not enter: their accessible name
|
|
255
|
+
// already carries the inner text, so descending only duplicates it.
|
|
256
|
+
const LEAF_TAGS = new Set(["A", "BUTTON", "INPUT", "SELECT", "TEXTAREA", "SUMMARY"]);
|
|
257
|
+
const INTERACTIVE_ROLES = new Set([
|
|
258
|
+
"button", "link", "checkbox", "radio", "tab", "menuitem", "menuitemcheckbox",
|
|
259
|
+
"menuitemradio", "option", "switch", "combobox", "textbox", "searchbox",
|
|
260
|
+
"slider", "spinbutton", "treeitem",
|
|
261
|
+
]);
|
|
262
|
+
const TAG_ROLES = {
|
|
263
|
+
A: "link", BUTTON: "button", SELECT: "combobox", TEXTAREA: "textbox",
|
|
264
|
+
SUMMARY: "button", LABEL: "label", IMG: "img", FORM: "form", NAV: "navigation",
|
|
265
|
+
MAIN: "main", HEADER: "banner", FOOTER: "contentinfo", ASIDE: "complementary",
|
|
266
|
+
DIALOG: "dialog", TABLE: "table", TR: "row", ARTICLE: "article",
|
|
267
|
+
H1: "heading", H2: "heading", H3: "heading", H4: "heading", H5: "heading", H6: "heading",
|
|
268
|
+
};
|
|
269
|
+
// Emitted without a ref: they carry no action, they carry the grouping that
|
|
270
|
+
// tells one "Delete" apart from the next.
|
|
271
|
+
const LANDMARK_ROLES = new Set([
|
|
272
|
+
"navigation", "main", "banner", "contentinfo", "complementary", "dialog",
|
|
273
|
+
"form", "search", "region", "article", "table", "row", "tablist",
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
const nodes = [];
|
|
277
|
+
let refSeq = 0;
|
|
278
|
+
let truncated = false;
|
|
279
|
+
|
|
280
|
+
// A fresh snapshot retires the previous generation of refs, so a stale ref
|
|
281
|
+
// can never silently resolve to a different element after a re-render.
|
|
282
|
+
for (const el of document.querySelectorAll("[data-apx-ref]")) el.removeAttribute("data-apx-ref");
|
|
283
|
+
|
|
284
|
+
const root = rootSelector ? document.querySelector(rootSelector) : document.body;
|
|
285
|
+
if (!root) return { error: `Element not found: ${rootSelector}` };
|
|
286
|
+
|
|
287
|
+
const squash = (t, cap) => {
|
|
288
|
+
const v = String(t || "").replace(/\s+/g, " ").trim();
|
|
289
|
+
return v.length > cap ? v.slice(0, cap) + "…" : v;
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
function roleOf(el) {
|
|
293
|
+
const explicit = (el.getAttribute("role") || "").trim().toLowerCase();
|
|
294
|
+
if (explicit) return explicit.split(/\s+/)[0];
|
|
295
|
+
const tag = el.tagName;
|
|
296
|
+
if (tag === "INPUT") {
|
|
297
|
+
const t = (el.getAttribute("type") || "text").toLowerCase();
|
|
298
|
+
if (t === "checkbox") return "checkbox";
|
|
299
|
+
if (t === "radio") return "radio";
|
|
300
|
+
if (t === "submit" || t === "button" || t === "reset" || t === "image") return "button";
|
|
301
|
+
if (t === "range") return "slider";
|
|
302
|
+
if (t === "number") return "spinbutton";
|
|
303
|
+
if (t === "search") return "searchbox";
|
|
304
|
+
return "textbox";
|
|
305
|
+
}
|
|
306
|
+
if (tag === "A") return el.hasAttribute("href") ? "link" : "";
|
|
307
|
+
return TAG_ROLES[tag] || "";
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function visible(el) {
|
|
311
|
+
if (el.hasAttribute("hidden")) return false;
|
|
312
|
+
if (el.getAttribute("aria-hidden") === "true") return false;
|
|
313
|
+
if (el.tagName === "INPUT" && (el.getAttribute("type") || "").toLowerCase() === "hidden") return false;
|
|
314
|
+
if (!el.getClientRects().length) return false;
|
|
315
|
+
const cs = getComputedStyle(el);
|
|
316
|
+
return !(cs.visibility === "hidden" || cs.display === "none" || cs.opacity === "0");
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function nameOf(el) {
|
|
320
|
+
const aria = el.getAttribute("aria-label");
|
|
321
|
+
if (aria && aria.trim()) return squash(aria, 120);
|
|
322
|
+
const by = el.getAttribute("aria-labelledby");
|
|
323
|
+
if (by) {
|
|
324
|
+
const joined = by.split(/\s+/)
|
|
325
|
+
.map((id) => document.getElementById(id))
|
|
326
|
+
.filter(Boolean)
|
|
327
|
+
.map((n) => squash(n.innerText || n.textContent, 80))
|
|
328
|
+
.join(" ");
|
|
329
|
+
if (joined.trim()) return squash(joined, 120);
|
|
330
|
+
}
|
|
331
|
+
if (el.tagName === "IMG") return squash(el.getAttribute("alt"), 120);
|
|
332
|
+
if (el.tagName === "INPUT" || el.tagName === "TEXTAREA" || el.tagName === "SELECT") {
|
|
333
|
+
if (el.labels && el.labels.length) {
|
|
334
|
+
const l = squash(el.labels[0].innerText || el.labels[0].textContent, 80);
|
|
335
|
+
if (l) return l;
|
|
336
|
+
}
|
|
337
|
+
return squash(
|
|
338
|
+
el.getAttribute("placeholder") || el.getAttribute("title") || el.getAttribute("name"),
|
|
339
|
+
120
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
|
+
return squash(el.innerText || el.textContent, 120) || squash(el.getAttribute("title"), 120);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
function isInteractive(el, role) {
|
|
346
|
+
const tag = el.tagName;
|
|
347
|
+
if (tag === "A") return el.hasAttribute("href");
|
|
348
|
+
if (LEAF_TAGS.has(tag)) return true;
|
|
349
|
+
if (el.isContentEditable) return true;
|
|
350
|
+
if (INTERACTIVE_ROLES.has(role)) return true;
|
|
351
|
+
const ti = el.getAttribute("tabindex");
|
|
352
|
+
if (ti !== null && ti !== "-1") return true;
|
|
353
|
+
return el.hasAttribute("onclick");
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// Text owned by THIS element (its direct text-node children), so each run of
|
|
357
|
+
// page copy is attributed to exactly one node and never repeated up the tree.
|
|
358
|
+
function directText(el) {
|
|
359
|
+
let out = "";
|
|
360
|
+
for (const n of el.childNodes) if (n.nodeType === 3) out += n.nodeValue;
|
|
361
|
+
return squash(out, 300);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function walk(el, depth, parentName) {
|
|
365
|
+
if (nodes.length >= maxNodes) { truncated = true; return; }
|
|
366
|
+
if (SKIP_TAGS.has(el.tagName)) return;
|
|
367
|
+
if (!visible(el)) return;
|
|
368
|
+
|
|
369
|
+
const role = roleOf(el);
|
|
370
|
+
const interactive = isInteractive(el, role);
|
|
371
|
+
let emitted = false;
|
|
372
|
+
let ownName = parentName;
|
|
373
|
+
|
|
374
|
+
if (interactive) {
|
|
375
|
+
const ref = `ref_${++refSeq}`;
|
|
376
|
+
el.setAttribute("data-apx-ref", ref);
|
|
377
|
+
const name = nameOf(el);
|
|
378
|
+
const node = { depth, ref, role: role || "generic", name };
|
|
379
|
+
const type = el.tagName === "INPUT" ? (el.getAttribute("type") || "text").toLowerCase() : null;
|
|
380
|
+
if (type && type !== "text") node.type = type;
|
|
381
|
+
if (el.tagName === "A") {
|
|
382
|
+
const href = el.getAttribute("href");
|
|
383
|
+
if (href) node.href = squash(href, 120);
|
|
384
|
+
}
|
|
385
|
+
// A password field's value is never worth echoing back into a transcript.
|
|
386
|
+
const stateOnly = type === "checkbox" || type === "radio";
|
|
387
|
+
if (!stateOnly && type !== "password" && (el.tagName === "INPUT" || el.tagName === "TEXTAREA") && el.value) {
|
|
388
|
+
node.value = squash(el.value, 60);
|
|
389
|
+
}
|
|
390
|
+
if (el.tagName === "SELECT" && el.value) node.value = squash(el.value, 60);
|
|
391
|
+
if (el.checked) node.checked = true;
|
|
392
|
+
if (el.disabled || el.getAttribute("aria-disabled") === "true") node.disabled = true;
|
|
393
|
+
if (el.required) node.required = true;
|
|
394
|
+
const expanded = el.getAttribute("aria-expanded");
|
|
395
|
+
if (expanded !== null) node.expanded = expanded === "true";
|
|
396
|
+
if (el.getAttribute("aria-selected") === "true") node.selected = true;
|
|
397
|
+
nodes.push(node);
|
|
398
|
+
emitted = true;
|
|
399
|
+
ownName = name;
|
|
400
|
+
} else if (!interactiveOnly && LANDMARK_ROLES.has(role)) {
|
|
401
|
+
const label = squash(el.getAttribute("aria-label"), 80);
|
|
402
|
+
nodes.push(label ? { depth, role, name: label } : { depth, role });
|
|
403
|
+
emitted = true;
|
|
404
|
+
} else if (!interactiveOnly && role === "heading") {
|
|
405
|
+
const level = /^H[1-6]$/.test(el.tagName)
|
|
406
|
+
? Number(el.tagName[1])
|
|
407
|
+
: Number(el.getAttribute("aria-level")) || null;
|
|
408
|
+
const name = squash(el.innerText || el.textContent, 160);
|
|
409
|
+
const node = { depth, role: "heading", name };
|
|
410
|
+
if (level) node.level = level;
|
|
411
|
+
nodes.push(node);
|
|
412
|
+
emitted = true;
|
|
413
|
+
ownName = name;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
if (!interactiveOnly && !(el.tagName === "LABEL" && el.control)) {
|
|
417
|
+
const own = directText(el);
|
|
418
|
+
// Skip copy already spoken by the control that encloses it.
|
|
419
|
+
if (own && own.length > 1 && own !== ownName && own !== parentName) {
|
|
420
|
+
if (nodes.length >= maxNodes) truncated = true;
|
|
421
|
+
else nodes.push({ depth: emitted ? depth + 1 : depth, role: "text", name: own });
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (LEAF_TAGS.has(el.tagName)) return;
|
|
426
|
+
const childDepth = emitted ? depth + 1 : depth;
|
|
427
|
+
for (const child of el.children) walk(child, childDepth, ownName);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
walk(root, 0, "");
|
|
431
|
+
return { url: location.href, title: document.title, nodes, truncated };
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* A structural node with no name and no children says nothing — layout tables
|
|
436
|
+
* alone can emit dozens of them. Drop it: a node is empty when the next node is
|
|
437
|
+
* not deeper than it is.
|
|
438
|
+
*/
|
|
439
|
+
export function pruneEmptyContainers(nodes) {
|
|
440
|
+
const list = nodes || [];
|
|
441
|
+
return list.filter((n, i) => {
|
|
442
|
+
if (n.ref || n.name) return true;
|
|
443
|
+
const next = list[i + 1];
|
|
444
|
+
return !!next && (Number(next.depth) || 0) > (Number(n.depth) || 0);
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** Render collected nodes as the indented, screen-reader-shaped text the model reads. */
|
|
449
|
+
export function renderSnapshot(nodes, { maxChars = MAX_SNAPSHOT_CHARS } = {}) {
|
|
450
|
+
const lines = [];
|
|
451
|
+
let chars = 0;
|
|
452
|
+
let clipped = 0;
|
|
453
|
+
for (const n of pruneEmptyContainers(nodes)) {
|
|
454
|
+
const pad = " ".repeat(Math.max(0, Math.min(Number(n.depth) || 0, 12)));
|
|
455
|
+
let line = `${pad}- ${n.role || "generic"}`;
|
|
456
|
+
if (n.name) line += ` ${JSON.stringify(n.name)}`;
|
|
457
|
+
if (n.ref) line += ` [${n.ref}]`;
|
|
458
|
+
const meta = [];
|
|
459
|
+
if (n.level) meta.push(`level=${n.level}`);
|
|
460
|
+
if (n.type) meta.push(`type=${n.type}`);
|
|
461
|
+
if (n.href) meta.push(`href=${n.href}`);
|
|
462
|
+
if (n.value) meta.push(`value=${JSON.stringify(n.value)}`);
|
|
463
|
+
if (n.checked) meta.push("checked");
|
|
464
|
+
if (n.selected) meta.push("selected");
|
|
465
|
+
if (n.expanded !== undefined) meta.push(`expanded=${n.expanded}`);
|
|
466
|
+
if (n.disabled) meta.push("disabled");
|
|
467
|
+
if (n.required) meta.push("required");
|
|
468
|
+
if (meta.length) line += ` {${meta.join(" ")}}`;
|
|
469
|
+
if (chars + line.length + 1 > maxChars) { clipped++; continue; }
|
|
470
|
+
chars += line.length + 1;
|
|
471
|
+
lines.push(line);
|
|
472
|
+
}
|
|
473
|
+
if (clipped) lines.push(`…(${clipped} more nodes omitted — narrow with selector or interactive_only)`);
|
|
474
|
+
return lines.join("\n");
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* The CSS selector an action tool should act on, from either addressing mode.
|
|
479
|
+
* `ref` wins when both are given; neither is an error the model can fix.
|
|
480
|
+
*/
|
|
481
|
+
export function resolveTarget({ ref, selector } = {}) {
|
|
482
|
+
if (ref !== undefined && ref !== null && String(ref).trim() !== "") {
|
|
483
|
+
const id = String(ref).trim();
|
|
484
|
+
if (!/^ref_\d+$/.test(id)) {
|
|
485
|
+
throw new Error(`invalid ref "${ref}" — refs look like "ref_12" and come from browser_snapshot`);
|
|
486
|
+
}
|
|
487
|
+
return `[data-apx-ref="${id}"]`;
|
|
488
|
+
}
|
|
489
|
+
if (selector !== undefined && selector !== null && String(selector).trim() !== "") {
|
|
490
|
+
return String(selector);
|
|
491
|
+
}
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
function requireTarget({ ref, selector }) {
|
|
496
|
+
const target = resolveTarget({ ref, selector });
|
|
497
|
+
if (!target) throw new Error("ref or selector required — call browser_snapshot first and act on a ref");
|
|
498
|
+
return target;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// Wait for the element, translating a missing ref into the one instruction
|
|
502
|
+
// that actually unblocks the model: take a new snapshot.
|
|
503
|
+
async function waitForTarget(page, target, ref, timeout = 10000) {
|
|
504
|
+
try {
|
|
505
|
+
await page.waitForSelector(target, { timeout });
|
|
506
|
+
} catch (e) {
|
|
507
|
+
if (ref) {
|
|
508
|
+
throw new Error(
|
|
509
|
+
`${ref} is no longer on the page — the DOM changed since the last browser_snapshot. ` +
|
|
510
|
+
`Call browser_snapshot again and use a fresh ref.`
|
|
511
|
+
);
|
|
512
|
+
}
|
|
513
|
+
throw e;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// Actions accept `snapshot: true` to return the post-action page state in the
|
|
518
|
+
// same round trip, which is what keeps a multi-step flow from costing one extra
|
|
519
|
+
// tool call per click.
|
|
520
|
+
async function maybeSnapshot(want) {
|
|
521
|
+
if (!want) return undefined;
|
|
522
|
+
try {
|
|
523
|
+
const s = await browser_snapshot();
|
|
524
|
+
return s.snapshot;
|
|
525
|
+
} catch {
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
export async function browser_snapshot({ selector, interactive_only = false, max_nodes } = {}) {
|
|
531
|
+
return onPage(async (page) => {
|
|
532
|
+
const cap = Math.min(Number(max_nodes) || MAX_SNAPSHOT_NODES, 1500);
|
|
533
|
+
const res = await page.evaluate(collectA11yNodes, {
|
|
534
|
+
rootSelector: selector ?? null,
|
|
535
|
+
interactiveOnly: !!interactive_only,
|
|
536
|
+
maxNodes: cap,
|
|
537
|
+
});
|
|
538
|
+
if (res?.error) throw new Error(res.error);
|
|
539
|
+
const snapshot = renderSnapshot(res.nodes);
|
|
540
|
+
return {
|
|
541
|
+
ok: true,
|
|
542
|
+
url: res.url,
|
|
543
|
+
title: res.title,
|
|
544
|
+
nodes: res.nodes.length,
|
|
545
|
+
truncated: !!res.truncated,
|
|
546
|
+
snapshot,
|
|
547
|
+
};
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
|
|
231
551
|
// ---------------------------------------------------------------------------
|
|
232
552
|
// Tool implementations
|
|
233
553
|
// ---------------------------------------------------------------------------
|
|
234
554
|
|
|
235
|
-
export async function browser_navigate({ url, launch_options, allow_dangerous, wait_until } = {}) {
|
|
555
|
+
export async function browser_navigate({ url, launch_options, allow_dangerous, wait_until, snapshot } = {}) {
|
|
236
556
|
if (!url) throw new Error("url required");
|
|
237
557
|
const page = await ensureBrowser({ launch_options, allow_dangerous });
|
|
238
558
|
|
|
@@ -272,16 +592,19 @@ export async function browser_navigate({ url, launch_options, allow_dangerous, w
|
|
|
272
592
|
title = "";
|
|
273
593
|
}
|
|
274
594
|
|
|
595
|
+
const snap = await maybeSnapshot(snapshot);
|
|
275
596
|
return {
|
|
276
597
|
ok: true,
|
|
277
598
|
url: page.url(),
|
|
278
599
|
status: response?.status() ?? null,
|
|
279
600
|
title,
|
|
280
601
|
wait_until: response ? (preferred) : null,
|
|
602
|
+
...(snap === undefined ? {} : { snapshot: snap }),
|
|
281
603
|
};
|
|
282
604
|
}
|
|
283
605
|
|
|
284
|
-
export async function browser_screenshot({ selector, full_page = false, width, height, encoded = false, save_path, save_to_tmp = false } = {}) {
|
|
606
|
+
export async function browser_screenshot({ selector, ref, full_page = false, width, height, encoded = false, save_path, save_to_tmp = false } = {}) {
|
|
607
|
+
const target = resolveTarget({ ref, selector });
|
|
285
608
|
const page = await ensureBrowser();
|
|
286
609
|
if (width || height) {
|
|
287
610
|
await page.setViewport({
|
|
@@ -291,10 +614,10 @@ export async function browser_screenshot({ selector, full_page = false, width, h
|
|
|
291
614
|
}
|
|
292
615
|
|
|
293
616
|
const buf = await withContextRetry(async () => {
|
|
294
|
-
const
|
|
295
|
-
if (
|
|
296
|
-
return
|
|
297
|
-
? await
|
|
617
|
+
const handle = target ? await page.$(target) : null;
|
|
618
|
+
if (target && !handle) throw new Error(`Element not found: ${ref || selector}`);
|
|
619
|
+
return handle
|
|
620
|
+
? await handle.screenshot({ type: "png", encoding: "base64" })
|
|
298
621
|
: await page.screenshot({ type: "png", encoding: "base64", fullPage: !!full_page });
|
|
299
622
|
});
|
|
300
623
|
|
|
@@ -331,49 +654,55 @@ export async function browser_screenshot({ selector, full_page = false, width, h
|
|
|
331
654
|
};
|
|
332
655
|
}
|
|
333
656
|
|
|
334
|
-
export async function browser_click({ selector } = {}) {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
await page
|
|
338
|
-
await page.click(
|
|
657
|
+
export async function browser_click({ selector, ref, snapshot } = {}) {
|
|
658
|
+
const target = requireTarget({ ref, selector });
|
|
659
|
+
const res = await onPage(async (page) => {
|
|
660
|
+
await waitForTarget(page, target, ref);
|
|
661
|
+
await page.click(target);
|
|
339
662
|
await page.waitForNetworkIdle({ timeout: 5000 }).catch(() => {});
|
|
340
|
-
return { ok: true, selector, url: page.url() };
|
|
663
|
+
return { ok: true, ref: ref ?? null, selector: selector ?? null, url: page.url() };
|
|
341
664
|
});
|
|
665
|
+
const snap = await maybeSnapshot(snapshot);
|
|
666
|
+
return snap === undefined ? res : { ...res, snapshot: snap };
|
|
342
667
|
}
|
|
343
668
|
|
|
344
|
-
export async function browser_type({ selector, text, clear = true } = {}) {
|
|
345
|
-
|
|
669
|
+
export async function browser_type({ selector, ref, text, clear = true, snapshot } = {}) {
|
|
670
|
+
const target = requireTarget({ ref, selector });
|
|
346
671
|
if (text === undefined) throw new Error("text required");
|
|
347
|
-
|
|
348
|
-
await page
|
|
349
|
-
await page.focus(
|
|
672
|
+
const res = await onPage(async (page) => {
|
|
673
|
+
await waitForTarget(page, target, ref);
|
|
674
|
+
await page.focus(target);
|
|
350
675
|
if (clear) {
|
|
351
676
|
await page.keyboard.down("Control");
|
|
352
677
|
await page.keyboard.press("KeyA");
|
|
353
678
|
await page.keyboard.up("Control");
|
|
354
679
|
await page.keyboard.press("Backspace");
|
|
355
680
|
}
|
|
356
|
-
await page.type(
|
|
357
|
-
return { ok: true, selector, typed: String(text).length };
|
|
681
|
+
await page.type(target, String(text), { delay: 20 });
|
|
682
|
+
return { ok: true, ref: ref ?? null, selector: selector ?? null, typed: String(text).length };
|
|
358
683
|
});
|
|
684
|
+
const snap = await maybeSnapshot(snapshot);
|
|
685
|
+
return snap === undefined ? res : { ...res, snapshot: snap };
|
|
359
686
|
}
|
|
360
687
|
|
|
361
|
-
export async function browser_select({ selector, value } = {}) {
|
|
362
|
-
|
|
688
|
+
export async function browser_select({ selector, ref, value, snapshot } = {}) {
|
|
689
|
+
const target = requireTarget({ ref, selector });
|
|
363
690
|
if (value === undefined) throw new Error("value required");
|
|
364
|
-
|
|
365
|
-
await page
|
|
366
|
-
await page.select(
|
|
367
|
-
return { ok: true, selector, value };
|
|
691
|
+
const res = await onPage(async (page) => {
|
|
692
|
+
await waitForTarget(page, target, ref);
|
|
693
|
+
await page.select(target, String(value));
|
|
694
|
+
return { ok: true, ref: ref ?? null, selector: selector ?? null, value };
|
|
368
695
|
});
|
|
696
|
+
const snap = await maybeSnapshot(snapshot);
|
|
697
|
+
return snap === undefined ? res : { ...res, snapshot: snap };
|
|
369
698
|
}
|
|
370
699
|
|
|
371
|
-
export async function browser_hover({ selector } = {}) {
|
|
372
|
-
|
|
700
|
+
export async function browser_hover({ selector, ref } = {}) {
|
|
701
|
+
const target = requireTarget({ ref, selector });
|
|
373
702
|
return onPage(async (page) => {
|
|
374
|
-
await page
|
|
375
|
-
await page.hover(
|
|
376
|
-
return { ok: true, selector };
|
|
703
|
+
await waitForTarget(page, target, ref);
|
|
704
|
+
await page.hover(target);
|
|
705
|
+
return { ok: true, ref: ref ?? null, selector: selector ?? null };
|
|
377
706
|
});
|
|
378
707
|
}
|
|
379
708
|
|
|
@@ -511,6 +840,7 @@ export function buildBrowserRouter(express) {
|
|
|
511
840
|
};
|
|
512
841
|
|
|
513
842
|
router.post("/navigate", wrap(browser_navigate));
|
|
843
|
+
router.post("/snapshot", wrap(browser_snapshot));
|
|
514
844
|
router.post("/screenshot", wrap(browser_screenshot));
|
|
515
845
|
router.post("/click", wrap(browser_click));
|
|
516
846
|
router.post("/type", wrap(browser_type));
|