@agentprojectcontext/apx 1.80.2 → 1.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -8
- package/skills/apc-context/SKILL.md +14 -7
- package/skills/apx/SKILL.md +62 -2
- package/skills/apx-mcp/SKILL.md +42 -15
- package/src/core/agent/a2a/peers.js +161 -0
- package/src/core/agent/a2a/reply.js +379 -27
- package/src/core/agent/abort.js +25 -0
- package/src/core/agent/agent-model.js +58 -0
- package/src/core/agent/agent-tools.js +101 -0
- package/src/core/agent/author-line.js +110 -0
- package/src/core/agent/build-agent-system.js +52 -18
- package/src/core/agent/channels/voice-context.js +17 -2
- package/src/core/agent/closing-floor.js +117 -0
- package/src/core/agent/constants.js +119 -11
- package/src/core/agent/engine-call.js +56 -0
- package/src/core/agent/group/run-group-turn.js +218 -0
- package/src/core/agent/group/turn-resolver.js +165 -0
- package/src/core/agent/judge.js +138 -11
- package/src/core/agent/loop/side-effects.js +106 -3
- package/src/core/agent/memory.js +31 -18
- package/src/core/agent/model-capabilities.js +47 -0
- package/src/core/agent/model-router.js +11 -40
- package/src/core/agent/prompt-builder.js +47 -0
- package/src/core/agent/prompts/channels/a2a.md +12 -0
- package/src/core/agent/prompts/channels/code.md +3 -1
- package/src/core/agent/prompts/channels/telegram.md +2 -0
- package/src/core/agent/prompts/channels/web_code.md +1 -1
- package/src/core/agent/prompts/channels/whatsapp.md +37 -0
- package/src/core/agent/prompts/core/agent-base.md +2 -0
- package/src/core/agent/prompts/discipline/action.md +1 -0
- package/src/core/agent/prompts/discipline/two-segment.md +2 -1
- package/src/core/agent/prompts/modes/mobility.md +36 -0
- package/src/core/agent/retry.js +42 -0
- package/src/core/agent/run-agent.js +322 -25
- package/src/core/agent/run-turn.js +253 -0
- package/src/core/agent/self-memory.js +18 -52
- package/src/core/agent/skills/agent-skills.js +118 -0
- package/src/core/agent/skills/catalog.js +1 -1
- package/src/core/agent/skills/declared.js +13 -0
- package/src/core/agent/skills/index-store.js +8 -1
- package/src/core/agent/skills/inspector.js +20 -3
- package/src/core/agent/skills/loader.js +18 -3
- package/src/core/agent/skills/media.js +121 -0
- package/src/core/agent/skills/origin.js +61 -0
- package/src/core/agent/skills/sections.js +136 -0
- package/src/core/agent/super-agent.js +54 -14
- package/src/core/agent/tools/handlers/_calendar.js +50 -0
- package/src/core/agent/tools/handlers/add-mcp.js +103 -0
- package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
- package/src/core/agent/tools/handlers/attach-media.js +56 -0
- package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
- package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
- package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
- package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
- package/src/core/agent/tools/handlers/call-agent.js +14 -6
- package/src/core/agent/tools/handlers/call-runtime.js +27 -49
- package/src/core/agent/tools/handlers/comment-task.js +78 -0
- package/src/core/agent/tools/handlers/complete-task.js +60 -0
- package/src/core/agent/tools/handlers/configure-agent.js +70 -0
- package/src/core/agent/tools/handlers/create-agent.js +68 -0
- package/src/core/agent/tools/handlers/create-task.js +41 -3
- package/src/core/agent/tools/handlers/import-agent.js +5 -5
- package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
- package/src/core/agent/tools/handlers/list-routines.js +46 -0
- package/src/core/agent/tools/handlers/list-tasks.js +8 -1
- package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
- package/src/core/agent/tools/handlers/read-skill.js +64 -0
- package/src/core/agent/tools/handlers/remember-routine.js +2 -8
- package/src/core/agent/tools/handlers/remember.js +82 -6
- package/src/core/agent/tools/handlers/remove-agent.js +42 -0
- package/src/core/agent/tools/handlers/run-routine.js +94 -0
- package/src/core/agent/tools/handlers/run-shell.js +44 -2
- package/src/core/agent/tools/handlers/send-telegram.js +41 -19
- package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
- package/src/core/agent/tools/handlers/view-media.js +69 -0
- package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
- package/src/core/agent/tools/helpers.js +36 -4
- package/src/core/agent/tools/names.js +64 -0
- package/src/core/agent/tools/registry-bridge.js +24 -1
- package/src/core/agent/tools/registry.js +79 -0
- package/src/core/agent/tools/tool-call-parser.js +136 -13
- package/src/core/agent/vision-bridge.js +69 -0
- package/src/core/apc/agent-identity.js +74 -0
- package/src/core/apc/agent-rename-refs.js +187 -0
- package/src/core/apc/agent-write.js +312 -0
- package/src/core/apc/agents-vault.js +1 -1
- package/src/core/apc/blob-keys.js +42 -0
- package/src/core/apc/frontmatter.js +166 -10
- package/src/core/apc/parser.js +33 -83
- package/src/core/apc/paths.js +4 -6
- package/src/core/apc/project-memory.js +44 -0
- package/src/core/apc/projects-helpers.js +33 -0
- package/src/core/apc/scaffold.js +36 -16
- package/src/core/channels/telegram/ask-callbacks.js +103 -0
- package/src/core/channels/telegram/dispatch.js +154 -30
- package/src/core/channels/telegram/helpers.js +59 -7
- package/src/core/channels/telegram/inbound/audio.js +26 -30
- package/src/core/channels/telegram/inbound/file.js +22 -32
- package/src/core/channels/telegram/inbound/photo.js +24 -28
- package/src/core/channels/telegram/progress-gate.js +76 -0
- package/src/core/channels/telegram/reply.js +151 -43
- package/src/core/channels/telegram/voice-note.js +150 -0
- package/src/core/config/index.js +53 -54
- package/src/core/config/paths.js +117 -31
- package/src/core/config/redact.js +89 -4
- package/src/core/config/secret-values.js +2 -4
- package/src/core/constants/actors.js +5 -0
- package/src/core/constants/channels.js +3 -1
- package/src/core/constants/task-categories.js +73 -0
- package/src/core/constants/task-fields.js +28 -0
- package/src/core/engines/_globs.js +33 -0
- package/src/core/engines/anthropic.js +19 -1
- package/src/core/engines/catalog.js +20 -0
- package/src/core/engines/gemini.js +84 -16
- package/src/core/engines/index.js +19 -3
- package/src/core/engines/mock.js +145 -1
- package/src/core/engines/openai-compatible.js +150 -15
- package/src/core/engines/presets.js +36 -9
- package/src/core/engines/zen.js +131 -0
- package/src/core/events/bus.js +140 -0
- package/src/core/events/mascot-notify.js +156 -0
- package/src/core/http-tools/browser.js +366 -36
- package/src/core/http-tools/catalog.js +206 -22
- package/src/core/http-tools/grep.js +62 -7
- package/src/core/http-tools/registry.js +3 -1
- package/src/core/i18n/en.js +34 -3
- package/src/core/i18n/es.js +36 -4
- package/src/core/i18n/index.js +5 -5
- package/src/core/i18n/pt.js +32 -3
- package/src/core/identity/self.js +14 -1
- package/src/core/images/engines/a1111.js +219 -0
- package/src/core/images/engines/index.js +187 -0
- package/src/core/images/engines/mock.js +74 -0
- package/src/core/images/engines/openai.js +130 -0
- package/src/core/images/engines/sdcpp.js +204 -0
- package/src/core/images/engines/shared.js +218 -0
- package/src/core/images/generate.js +260 -0
- package/src/core/integrations/catalog.js +8 -3
- package/src/core/integrations/plugins/_google-oauth.js +179 -0
- package/src/core/integrations/plugins/asana.js +7 -3
- package/src/core/integrations/plugins/calendar.js +404 -0
- package/src/core/integrations/store.js +2 -0
- package/src/core/memory/broker.js +16 -1
- package/src/core/memory/compactor.js +19 -3
- package/src/core/memory/consolidate.js +2 -2
- package/src/core/memory/dated-log.js +66 -0
- package/src/core/memory/embed-engines/custom.js +59 -0
- package/src/core/memory/embed-engines/gemini.js +9 -3
- package/src/core/memory/embed-engines/index.js +87 -15
- package/src/core/memory/embeddings.js +52 -24
- package/src/core/memory/index.js +13 -3
- package/src/core/memory/indexer.js +83 -27
- package/src/core/memory/prune.js +182 -0
- package/src/core/memory/store.js +22 -0
- package/src/core/memory/summarizer.js +72 -8
- package/src/core/mobility/answer.js +80 -0
- package/src/core/mobility/geofence.js +667 -0
- package/src/core/mobility/osm-route.js +282 -0
- package/src/core/mobility/preferences.js +91 -0
- package/src/core/mobility/state.js +245 -0
- package/src/core/mobility/trip-event.js +384 -0
- package/src/core/net/tailscale.js +168 -0
- package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
- package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
- package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
- package/src/core/profiles/bundled/secretary/profile.json +3 -1
- package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
- package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
- package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
- package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
- package/src/core/profiles/lifecycle.js +243 -19
- package/src/core/profiles/paths.js +12 -0
- package/src/core/profiles/store.js +47 -0
- package/src/core/routines/active-runs.js +213 -0
- package/src/core/routines/delivery.js +612 -0
- package/src/core/routines/header.js +88 -0
- package/src/core/routines/index.js +26 -0
- package/src/core/routines/run-log.js +78 -0
- package/src/core/routines/runner.js +629 -66
- package/src/core/routines/signals.js +75 -0
- package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
- package/src/core/runtime-skills/apx/SKILL.md +93 -1
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
- package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
- package/src/core/runtime-skills/apx-commitment/SKILL.md +134 -0
- package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
- package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
- package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
- package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
- package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
- package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
- package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
- package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
- package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
- package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
- package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
- package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
- package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
- package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
- package/src/core/runtimes/_spawn.js +9 -1
- package/src/core/runtimes/claude-code.js +11 -2
- package/src/core/runtimes/codex.js +44 -10
- package/src/core/runtimes/index.js +17 -2
- package/src/core/runtimes/opencode.js +88 -9
- package/src/core/runtimes/outcome.js +119 -0
- package/src/core/sessions/index.js +193 -1
- package/src/core/stores/agent-inbox.js +109 -23
- package/src/core/stores/code-sessions.js +21 -0
- package/src/core/stores/commitments.js +27 -3
- package/src/core/stores/conversations.js +220 -20
- package/src/core/stores/deliveries.js +177 -0
- package/src/core/stores/media-archive.js +228 -0
- package/src/core/stores/messages.js +1096 -112
- package/src/core/stores/organization.js +34 -0
- package/src/core/stores/project-memory.js +71 -0
- package/src/core/stores/routine-memory.js +16 -8
- package/src/core/stores/routines.js +27 -49
- package/src/core/stores/sessions.js +4 -8
- package/src/core/stores/tasks.js +212 -18
- package/src/core/stores/turn-record.js +209 -0
- package/src/core/tasks/columns.js +136 -0
- package/src/core/tasks/comment-turn.js +258 -0
- package/src/core/util/time.js +13 -0
- package/src/core/voice/engines/index.js +54 -1
- package/src/core/voice/engines/openai.js +50 -4
- package/src/core/voice/opus.js +67 -0
- package/src/core/voice/pronounceable.js +43 -0
- package/src/core/voice/transcription.js +4 -0
- package/src/core/voice/tts.js +114 -24
- package/src/host/daemon/active-turns.js +188 -0
- package/src/host/daemon/api/admin-config.js +9 -0
- package/src/host/daemon/api/agents.js +99 -90
- package/src/host/daemon/api/artifact-preview.js +7 -6
- package/src/host/daemon/api/artifacts.js +3 -2
- package/src/host/daemon/api/code.js +55 -9
- package/src/host/daemon/api/commitments.js +11 -0
- package/src/host/daemon/api/confirm.js +3 -2
- package/src/host/daemon/api/conversations.js +543 -35
- package/src/host/daemon/api/deck.js +9 -8
- package/src/host/daemon/api/deliveries.js +33 -0
- package/src/host/daemon/api/desktop.js +5 -4
- package/src/host/daemon/api/embeddings.js +15 -6
- package/src/host/daemon/api/engines.js +59 -8
- package/src/host/daemon/api/exec.js +437 -121
- package/src/host/daemon/api/groups.js +215 -0
- package/src/host/daemon/api/images.js +107 -0
- package/src/host/daemon/api/inbox.js +123 -2
- package/src/host/daemon/api/integrations.js +64 -2
- package/src/host/daemon/api/mcps.js +7 -6
- package/src/host/daemon/api/media.js +283 -0
- package/src/host/daemon/api/mobility.js +177 -0
- package/src/host/daemon/api/net.js +182 -0
- package/src/host/daemon/api/pairing.js +38 -5
- package/src/host/daemon/api/profiles.js +30 -2
- package/src/host/daemon/api/routines.js +36 -4
- package/src/host/daemon/api/runtimes.js +74 -39
- package/src/host/daemon/api/sessions-search.js +7 -2
- package/src/host/daemon/api/sessions.js +44 -2
- package/src/host/daemon/api/shared.js +127 -20
- package/src/host/daemon/api/skills.js +11 -4
- package/src/host/daemon/api/super-agent.js +384 -53
- package/src/host/daemon/api/tasks.js +180 -10
- package/src/host/daemon/api/telegram.js +11 -10
- package/src/host/daemon/api/thread-faces.js +159 -0
- package/src/host/daemon/api/top-level.js +3 -3
- package/src/host/daemon/api/transcribe.js +11 -10
- package/src/host/daemon/api/tts.js +97 -4
- package/src/host/daemon/api/turn-abort.js +23 -0
- package/src/host/daemon/api/turns.js +49 -0
- package/src/host/daemon/api/voice.js +5 -4
- package/src/host/daemon/api/web.js +98 -0
- package/src/host/daemon/api.js +39 -0
- package/src/host/daemon/delivery-sweep.js +58 -0
- package/src/host/daemon/desktop-ws.js +5 -23
- package/src/host/daemon/events-ws.js +273 -0
- package/src/host/daemon/index.js +59 -15
- package/src/host/daemon/plugins/desktop/index.js +17 -4
- package/src/host/daemon/plugins/telegram/index.js +78 -40
- package/src/host/daemon/pty-bridge.py +99 -0
- package/src/host/daemon/routines-scheduler.js +1 -0
- package/src/host/daemon/smoke.js +1 -2
- package/src/host/daemon/terminal-ws.js +132 -0
- package/src/host/daemon/tts-keepwarm.js +87 -0
- package/src/host/daemon/wakeup.js +11 -6
- package/src/host/daemon/whisper-server.js +44 -0
- package/src/host/daemon/whisper-server.py +70 -13
- package/src/host/daemon/ws-auth.js +28 -0
- package/src/interfaces/android/app/build.gradle +42 -0
- package/src/interfaces/android/app/proguard-rules.pro +4 -0
- package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
- package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
- package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
- package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
- package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
- package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
- package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
- package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
- package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
- package/src/interfaces/android/build.gradle +3 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
- package/src/interfaces/android/gradle.properties +3 -0
- package/src/interfaces/android/gradlew +248 -0
- package/src/interfaces/android/gradlew.bat +82 -0
- package/src/interfaces/android/settings.gradle +18 -0
- package/src/interfaces/cli/commands/a2a.js +145 -4
- package/src/interfaces/cli/commands/agent.js +247 -22
- package/src/interfaces/cli/commands/code.js +1 -1
- package/src/interfaces/cli/commands/commitment.js +5 -0
- package/src/interfaces/cli/commands/config.js +85 -6
- package/src/interfaces/cli/commands/exec.js +90 -1
- package/src/interfaces/cli/commands/image.js +314 -0
- package/src/interfaces/cli/commands/mcp.js +87 -23
- package/src/interfaces/cli/commands/memory.js +35 -22
- package/src/interfaces/cli/commands/panel.js +94 -0
- package/src/interfaces/cli/commands/profile.js +14 -0
- package/src/interfaces/cli/commands/project.js +29 -0
- package/src/interfaces/cli/commands/routine.js +45 -10
- package/src/interfaces/cli/commands/runtime.js +30 -7
- package/src/interfaces/cli/commands/session.js +90 -38
- package/src/interfaces/cli/commands/sessions.js +35 -2
- package/src/interfaces/cli/commands/skills.js +15 -9
- package/src/interfaces/cli/commands/status.js +2 -3
- package/src/interfaces/cli/commands/task.js +54 -5
- package/src/interfaces/cli/commands/telegram.js +12 -4
- package/src/interfaces/cli/commands/transcribe.js +177 -0
- package/src/interfaces/cli/help/index.js +311 -72
- package/src/interfaces/cli/http.js +61 -13
- package/src/interfaces/cli/index.js +1 -1
- package/src/interfaces/cli/routes/agent.js +5 -4
- package/src/interfaces/cli/routes/commitment.js +3 -2
- package/src/interfaces/cli/routes/config.js +7 -2
- package/src/interfaces/cli/routes/image.js +11 -0
- package/src/interfaces/cli/routes/index.js +2 -0
- package/src/interfaces/cli/routes/log.js +1 -1
- package/src/interfaces/cli/routes/memory.js +3 -2
- package/src/interfaces/cli/routes/panel.js +15 -2
- package/src/interfaces/cli/routes/profile.js +3 -2
- package/src/interfaces/cli/routes/transcribe.js +10 -0
- package/src/interfaces/cli/stdin.js +29 -0
- package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
- package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
- package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
- package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
- package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
- package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
- package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
- package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
- package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
- package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
- package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
- package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
- package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
- package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
- package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
- package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
- package/src/interfaces/desktop/assets/notification.mp3 +0 -0
- package/src/interfaces/desktop/main.js +473 -29
- package/src/interfaces/desktop/mascot-blobs.js +41 -0
- package/src/interfaces/desktop/mascot-preload.js +32 -0
- package/src/interfaces/desktop/mascot.css +186 -0
- package/src/interfaces/desktop/mascot.html +40 -0
- package/src/interfaces/desktop/mascot.js +163 -0
- package/src/interfaces/desktop/preload.js +10 -0
- package/src/interfaces/desktop/renderer.js +308 -48
- package/src/interfaces/desktop/style.css +34 -0
- package/src/interfaces/mcp-server/index.js +87 -0
- package/src/interfaces/tui/_shims/util-locale.ts +0 -2
- package/src/interfaces/tui/app.tsx +0 -6
- package/src/interfaces/tui/attach.ts +0 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
- package/src/interfaces/tui/plugin/api.tsx +0 -3
- package/src/interfaces/tui/plugin/runtime.ts +0 -3
- package/src/interfaces/tui/thread.ts +0 -16
- package/src/interfaces/web/README.md +22 -14
- package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
- package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
- package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/dist/index.html +22 -6
- package/src/interfaces/web/dist/index.html.br +0 -0
- package/src/interfaces/web/dist/index.html.gz +0 -0
- package/src/interfaces/web/dist/manifest.webmanifest +25 -0
- package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/dist/sw.js +106 -0
- package/src/interfaces/web/dist/sw.js.br +0 -0
- package/src/interfaces/web/dist/sw.js.gz +0 -0
- package/src/interfaces/web/eslint.config.js +83 -0
- package/src/interfaces/web/index.html +20 -4
- package/src/interfaces/web/package-lock.json +1651 -1280
- package/src/interfaces/web/package.json +9 -10
- package/src/interfaces/web/pnpm-lock.yaml +867 -869
- package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/public/manifest.webmanifest +25 -0
- package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/public/sw.js +106 -0
- package/src/interfaces/web/src/App.tsx +106 -10
- package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
- package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
- package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
- package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
- package/src/interfaces/web/src/components/Combobox.tsx +201 -0
- package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
- package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
- package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
- package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
- package/src/interfaces/web/src/components/Roby.tsx +5 -3
- package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
- package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
- package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
- package/src/interfaces/web/src/components/Toast.tsx +50 -14
- package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
- package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
- package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
- package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
- package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
- package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
- package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
- package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
- package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
- package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
- package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
- package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
- package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
- package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
- package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
- package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
- package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
- package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
- package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
- package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
- package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
- package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
- package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
- package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
- package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
- package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
- package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
- package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
- package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
- package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
- package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
- package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
- package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
- package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
- package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
- package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
- package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
- package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
- package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
- package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
- package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
- package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
- package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
- package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
- package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
- package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
- package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
- package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
- package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
- package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
- package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
- package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
- package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
- package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
- package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
- package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
- package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
- package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
- package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
- package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
- package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
- package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
- package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
- package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
- package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
- package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
- package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
- package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
- package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
- package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
- package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
- package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
- package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
- package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
- package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
- package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
- package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
- package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
- package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
- package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
- package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
- package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
- package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
- package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
- package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
- package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
- package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
- package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
- package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
- package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
- package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
- package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
- package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
- package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
- package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
- package/src/interfaces/web/src/components/ui.tsx +62 -23
- package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
- package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
- package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
- package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
- package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
- package/src/interfaces/web/src/constants/index.ts +1 -0
- package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
- package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
- package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
- package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
- package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
- package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
- package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
- package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
- package/src/interfaces/web/src/i18n/en.ts +832 -175
- package/src/interfaces/web/src/i18n/es.ts +841 -188
- package/src/interfaces/web/src/lib/api/agents.ts +23 -4
- package/src/interfaces/web/src/lib/api/code.ts +17 -0
- package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
- package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
- package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
- package/src/interfaces/web/src/lib/api/engines.ts +14 -0
- package/src/interfaces/web/src/lib/api/groups.ts +93 -0
- package/src/interfaces/web/src/lib/api/images.ts +193 -0
- package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
- package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
- package/src/interfaces/web/src/lib/api/media.ts +126 -0
- package/src/interfaces/web/src/lib/api/net.ts +44 -0
- package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
- package/src/interfaces/web/src/lib/api/projects.ts +9 -1
- package/src/interfaces/web/src/lib/api/routines.ts +9 -1
- package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
- package/src/interfaces/web/src/lib/api/skills.ts +8 -0
- package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
- package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
- package/src/interfaces/web/src/lib/api/tools.ts +2 -0
- package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
- package/src/interfaces/web/src/lib/api/turns.ts +20 -0
- package/src/interfaces/web/src/lib/api/voice.ts +72 -2
- package/src/interfaces/web/src/lib/api.ts +3 -0
- package/src/interfaces/web/src/lib/channels.ts +214 -0
- package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
- package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
- package/src/interfaces/web/src/lib/code-context.ts +0 -2
- package/src/interfaces/web/src/lib/http.ts +51 -17
- package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
- package/src/interfaces/web/src/lib/live.ts +252 -0
- package/src/interfaces/web/src/lib/net.ts +211 -0
- package/src/interfaces/web/src/lib/notify.ts +331 -0
- package/src/interfaces/web/src/lib/projectNav.ts +40 -0
- package/src/interfaces/web/src/lib/pwa.ts +115 -0
- package/src/interfaces/web/src/lib/qvox.ts +24 -0
- package/src/interfaces/web/src/lib/slug.ts +3 -0
- package/src/interfaces/web/src/lib/tone.ts +150 -0
- package/src/interfaces/web/src/main.tsx +15 -4
- package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
- package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
- package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
- package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
- package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
- package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
- package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
- package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
- package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
- package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
- package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
- package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
- package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
- package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
- package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
- package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
- package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
- package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
- package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
- package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
- package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
- package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
- package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
- package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
- package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
- package/src/interfaces/web/src/styles.css +106 -31
- package/src/interfaces/web/src/types/daemon.ts +246 -2
- package/src/interfaces/web/src/vite-env.d.ts +20 -0
- package/src/interfaces/tui/plugin/command-shim.ts +0 -109
- package/src/interfaces/web/components.json +0 -25
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
- package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
- package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
- package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
- package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
- package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
- package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
- package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
- package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
- package/src/interfaces/web/src/components/ui/card.tsx +0 -103
- package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
- package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
- package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
- package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
- package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
- package/src/interfaces/web/src/components/ui/command.tsx +0 -196
- package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
- package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
- package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
- package/src/interfaces/web/src/components/ui/field.tsx +0 -236
- package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
- package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
- package/src/interfaces/web/src/components/ui/item.tsx +0 -201
- package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
- package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
- package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
- package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
- package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
- package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
- package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
- package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
- package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
- package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
- package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
- package/src/interfaces/web/src/components/ui/table.tsx +0 -116
- package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
- package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
- package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
|
@@ -12,10 +12,12 @@ export const CHANNELS = Object.freeze({
|
|
|
12
12
|
API: "api",
|
|
13
13
|
WEB: "web", // Web admin big chat
|
|
14
14
|
WEB_SIDEBAR: "web_sidebar", // Web admin docked sidebar
|
|
15
|
-
WEB_CODE: "web_code", // Web admin `/
|
|
15
|
+
WEB_CODE: "web_code", // Web admin `/code` (OpenCode-style)
|
|
16
16
|
DECK: "deck", // Mobile cockpit dashboard
|
|
17
17
|
DESKTOP: "desktop", // Electron capsule (always voice mode)
|
|
18
18
|
CODE: "code", // `apx code` — terminal coding session
|
|
19
|
+
A2A: "a2a", // Agent-to-agent relay (project-scoped ledger)
|
|
20
|
+
LOG: "log", // Readable, never delivered (routine abstentions)
|
|
19
21
|
DIRECT: "direct", // Planned: 1:1 channel that isn't a chat platform
|
|
20
22
|
WHATSAPP: "whatsapp", // Planned: WhatsApp bot integration
|
|
21
23
|
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// What KIND of thing a task is — orthogonal to `state` (open/done/dropped),
|
|
2
|
+
// to `status` (pending/running/…), and to `tags`.
|
|
3
|
+
//
|
|
4
|
+
// Tags stay exactly what they were: free-form labels the owner invents. A
|
|
5
|
+
// category is a closed set the SYSTEM can act on, which is the whole point:
|
|
6
|
+
// "this is an errand, at this place" is a fact the daemon can route on without
|
|
7
|
+
// asking a model to read the title and guess. That guess is what a category
|
|
8
|
+
// replaces — a mobility reminder for a categorised task costs no geocoding,
|
|
9
|
+
// no place search and no LLM call.
|
|
10
|
+
//
|
|
11
|
+
// Registry pattern (AGENTS.md): adding a category is one entry here plus its
|
|
12
|
+
// two i18n keys. Nothing else switches on the id.
|
|
13
|
+
export const TASK_CATEGORIES = Object.freeze({
|
|
14
|
+
// The default. A task that is just a task.
|
|
15
|
+
general: Object.freeze({ id: "general", icon: "circle-dot", locatable: false }),
|
|
16
|
+
// Something to do while out — an errand with a place. `locatable` is what
|
|
17
|
+
// makes the mobility geofence consider it, and what makes the web offer the
|
|
18
|
+
// place fields.
|
|
19
|
+
trip: Object.freeze({ id: "trip", icon: "car", locatable: true }),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
export const TASK_CATEGORY_IDS = Object.freeze(Object.keys(TASK_CATEGORIES));
|
|
23
|
+
export const DEFAULT_TASK_CATEGORY = "general";
|
|
24
|
+
|
|
25
|
+
/** Unknown or missing → the default. Never throws: this reads stored data. */
|
|
26
|
+
export function normalizeTaskCategory(value) {
|
|
27
|
+
const id = String(value || "").trim().toLowerCase();
|
|
28
|
+
return TASK_CATEGORY_IDS.includes(id) ? id : DEFAULT_TASK_CATEGORY;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Can a task of this category carry a place? */
|
|
32
|
+
export function categoryIsLocatable(value) {
|
|
33
|
+
return TASK_CATEGORIES[normalizeTaskCategory(value)].locatable === true;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function finite(value) {
|
|
37
|
+
const number = Number(value);
|
|
38
|
+
return Number.isFinite(number) ? number : null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function text(value, max) {
|
|
42
|
+
return typeof value === "string" ? value.trim().slice(0, max) : "";
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A task's place, normalized. Returns null when there is nothing usable —
|
|
47
|
+
* a half-filled location is worse than none, because everything downstream
|
|
48
|
+
* would treat it as an answer.
|
|
49
|
+
*
|
|
50
|
+
* `place` alone is valid: it names somewhere without pinning it, which is
|
|
51
|
+
* still enough for a reminder to be worth reading. Coordinates are only kept
|
|
52
|
+
* as a pair, and only when both are in range.
|
|
53
|
+
*/
|
|
54
|
+
export function normalizeTaskLocation(value) {
|
|
55
|
+
if (!value || typeof value !== "object") return null;
|
|
56
|
+
const place = text(value.place ?? value.name, 200);
|
|
57
|
+
const address = text(value.address, 300);
|
|
58
|
+
const latitude = finite(value.latitude ?? value.lat);
|
|
59
|
+
const longitude = finite(value.longitude ?? value.lon ?? value.lng);
|
|
60
|
+
const pinned =
|
|
61
|
+
latitude != null && longitude != null &&
|
|
62
|
+
latitude >= -90 && latitude <= 90 &&
|
|
63
|
+
longitude >= -180 && longitude <= 180;
|
|
64
|
+
if (!place && !address && !pinned) return null;
|
|
65
|
+
return {
|
|
66
|
+
...(place ? { place } : {}),
|
|
67
|
+
...(address ? { address } : {}),
|
|
68
|
+
...(pinned ? { latitude, longitude } : {}),
|
|
69
|
+
// How close counts as "there". Absent means the caller had no opinion and
|
|
70
|
+
// the mobility default applies.
|
|
71
|
+
...(finite(value.radius_m) != null ? { radius_m: finite(value.radius_m) } : {}),
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OWNER_ACTOR_ID } from "./actors.js";
|
|
2
|
+
|
|
3
|
+
export const TASK_PRIORITIES = Object.freeze(["low", "normal", "high", "urgent"]);
|
|
4
|
+
export const DEFAULT_TASK_PRIORITY = "normal";
|
|
5
|
+
|
|
6
|
+
export const TASK_REMINDER_FREQUENCIES = Object.freeze(["none", "once", "daily", "weekly"]);
|
|
7
|
+
export const DEFAULT_TASK_REMINDER_FREQUENCY = "none";
|
|
8
|
+
|
|
9
|
+
/** `human` is accepted at every write boundary; storage stays canonical. */
|
|
10
|
+
export function normalizeTaskAssignee(value) {
|
|
11
|
+
const assignee = typeof value === "string" ? value.trim() : "";
|
|
12
|
+
if (!assignee) return null;
|
|
13
|
+
return ["human", OWNER_ACTOR_ID].includes(assignee.toLowerCase())
|
|
14
|
+
? OWNER_ACTOR_ID
|
|
15
|
+
: assignee;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function normalizeTaskPriority(value) {
|
|
19
|
+
const priority = String(value || "").trim().toLowerCase();
|
|
20
|
+
return TASK_PRIORITIES.includes(priority) ? priority : DEFAULT_TASK_PRIORITY;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function normalizeTaskReminderFrequency(value) {
|
|
24
|
+
const frequency = String(value || "").trim().toLowerCase();
|
|
25
|
+
return TASK_REMINDER_FREQUENCIES.includes(frequency)
|
|
26
|
+
? frequency
|
|
27
|
+
: DEFAULT_TASK_REMINDER_FREQUENCY;
|
|
28
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// Shell-style glob matching for model ids.
|
|
2
|
+
//
|
|
3
|
+
// Several adapters gate a wire-format quirk on WHICH model is answering rather
|
|
4
|
+
// than on which provider it came from: Gemini's thought signatures, DeepSeek's
|
|
5
|
+
// reasoning replay. Declaring those as glob patterns keeps "which models need
|
|
6
|
+
// this" a list an operator can read and a config key can override, instead of
|
|
7
|
+
// a branch buried in the serialiser.
|
|
8
|
+
//
|
|
9
|
+
// Patterns match the bare model id (no `<provider>:` prefix): `*` is any run of
|
|
10
|
+
// characters, `?` a single one. Matching is case-insensitive.
|
|
11
|
+
|
|
12
|
+
function globToRegExp(pattern) {
|
|
13
|
+
const escaped = String(pattern).replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
14
|
+
return new RegExp(`^${escaped.replace(/\*/g, ".*").replace(/\?/g, ".")}$`, "i");
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Does `model` match any of `patterns`? An empty list matches nothing. */
|
|
18
|
+
export function matchesModelGlob(model, patterns) {
|
|
19
|
+
if (!Array.isArray(patterns) || patterns.length === 0) return false;
|
|
20
|
+
const id = String(model || "");
|
|
21
|
+
return patterns.some((p) => globToRegExp(p).test(id));
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve "which models use this mechanism" from config, falling back to the
|
|
26
|
+
* adapter's built-in list.
|
|
27
|
+
*
|
|
28
|
+
* A configured array REPLACES the default — it is the whole answer to the
|
|
29
|
+
* question, so an install can also opt out entirely with an explicit `[]`.
|
|
30
|
+
*/
|
|
31
|
+
export function modelListFromConfig(configured, builtIn) {
|
|
32
|
+
return Array.isArray(configured) ? configured : builtIn;
|
|
33
|
+
}
|
|
@@ -9,6 +9,24 @@ function getKey(config) {
|
|
|
9
9
|
return config.api_key || process.env.ANTHROPIC_API_KEY || "";
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
/** Anthropic multimodal content blocks. Images ride on `m.images` the same
|
|
13
|
+
* way Gemini/OpenAI adapters read them — without this, Claude never saw
|
|
14
|
+
* photos attached to a turn. */
|
|
15
|
+
function contentForAnthropic(m) {
|
|
16
|
+
const text = typeof m.content === "string" ? m.content : JSON.stringify(m.content ?? "");
|
|
17
|
+
const imgs = Array.isArray(m.images)
|
|
18
|
+
? m.images.filter((im) => im && im.data && im.mime)
|
|
19
|
+
: [];
|
|
20
|
+
if (!imgs.length) return text;
|
|
21
|
+
return [
|
|
22
|
+
...(text ? [{ type: "text", text }] : []),
|
|
23
|
+
...imgs.map((im) => ({
|
|
24
|
+
type: "image",
|
|
25
|
+
source: { type: "base64", media_type: im.mime, data: im.data },
|
|
26
|
+
})),
|
|
27
|
+
];
|
|
28
|
+
}
|
|
29
|
+
|
|
12
30
|
export default {
|
|
13
31
|
id: "anthropic",
|
|
14
32
|
needsApiKey: true,
|
|
@@ -39,7 +57,7 @@ export default {
|
|
|
39
57
|
temperature,
|
|
40
58
|
messages: messages.map((m) => ({
|
|
41
59
|
role: m.role === "assistant" ? "assistant" : "user",
|
|
42
|
-
content:
|
|
60
|
+
content: contentForAnthropic(m),
|
|
43
61
|
})),
|
|
44
62
|
};
|
|
45
63
|
if (system) body.system = system;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
// { error }. Pure transport — no daemon dependencies. Both the daemon HTTP
|
|
4
4
|
// adapter and CLI commands can reuse this.
|
|
5
5
|
import { fetchJsonWithTimeout } from "./_health.js";
|
|
6
|
+
import { ZEN_HEADERS } from "./zen.js";
|
|
6
7
|
|
|
7
8
|
export const DEFAULT_BASE = {
|
|
8
9
|
openai: "https://api.openai.com/v1",
|
|
@@ -11,6 +12,7 @@ export const DEFAULT_BASE = {
|
|
|
11
12
|
gemini: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
12
13
|
anthropic: "https://api.anthropic.com/v1",
|
|
13
14
|
ollama: "http://localhost:11434",
|
|
15
|
+
zen: "https://opencode.ai/zen/v1",
|
|
14
16
|
};
|
|
15
17
|
|
|
16
18
|
// Gemini's native models endpoint returns a much richer catalog than the
|
|
@@ -66,6 +68,24 @@ export async function listModels(engine, baseUrl, apiKey) {
|
|
|
66
68
|
return { models };
|
|
67
69
|
}
|
|
68
70
|
|
|
71
|
+
// Zen publishes its catalog without a key, so the model picker can be filled
|
|
72
|
+
// before the user has one — useful, since choosing a model is how you decide
|
|
73
|
+
// whether the provider is worth signing up for.
|
|
74
|
+
if (engine === "zen") {
|
|
75
|
+
const r = await fetchJsonWithTimeout(`${base || DEFAULT_BASE.zen}/models`, {
|
|
76
|
+
timeoutMs: 5000,
|
|
77
|
+
headers: { ...ZEN_HEADERS, ...(apiKey ? { authorization: `Bearer ${apiKey}` } : {}) },
|
|
78
|
+
});
|
|
79
|
+
if (!r.ok) return { error: r.reason || `HTTP ${r.status}` };
|
|
80
|
+
const list = Array.isArray(r.json?.data) ? r.json.data : [];
|
|
81
|
+
const ids = list.map((m) => m?.id).filter(Boolean);
|
|
82
|
+
// Free-tier ids first. The catalog mixes models that bill at zero with
|
|
83
|
+
// Claude/GPT/Gemini ones that very much do not, under names that don't say
|
|
84
|
+
// which is which — so the cheap ones are the ones you scroll to first.
|
|
85
|
+
const free = (id) => /-free$/.test(id) || id === "big-pickle";
|
|
86
|
+
return { models: [...ids.filter(free).sort(), ...ids.filter((id) => !free(id)).sort()] };
|
|
87
|
+
}
|
|
88
|
+
|
|
69
89
|
// openai-compatible family: openai, groq, openrouter, azure, custom
|
|
70
90
|
if (!apiKey) return { error: "falta api_key" };
|
|
71
91
|
if (!base) return { error: "falta base_url" };
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
// Direct fetch, no SDK. Supports function calling (Gemini's name for tool
|
|
3
3
|
// use) so it can drive the super-agent loop on parity with Groq / OpenAI.
|
|
4
4
|
import { randomUUID } from "node:crypto";
|
|
5
|
+
import { matchesModelGlob, modelListFromConfig } from "./_globs.js";
|
|
6
|
+
import { streamSseDataEvents } from "./_streaming.js";
|
|
5
7
|
|
|
6
8
|
const API_BASE = "https://generativelanguage.googleapis.com/v1beta/models";
|
|
7
9
|
|
|
@@ -71,6 +73,55 @@ function markExhausted(model, key, now = Date.now()) {
|
|
|
71
73
|
exhausted.set(cooldownKey(model, key), reset.getTime());
|
|
72
74
|
}
|
|
73
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Read a `streamGenerateContent?alt=sse` response and rebuild the single
|
|
78
|
+
* response object the non-streaming path returns, so everything downstream —
|
|
79
|
+
* thought filtering, functionCall extraction, thought-signature replay — runs
|
|
80
|
+
* on one shape and stays unaware that streaming happened.
|
|
81
|
+
*
|
|
82
|
+
* Visible text deltas are handed to `onToken` as they arrive. Thought parts are
|
|
83
|
+
* NOT: they are the model's internal reasoning, and the desktop speaks what it
|
|
84
|
+
* streams.
|
|
85
|
+
*/
|
|
86
|
+
async function readGeminiStream(response, onToken) {
|
|
87
|
+
const parts = [];
|
|
88
|
+
let finishReason = null;
|
|
89
|
+
let usageMetadata = null;
|
|
90
|
+
|
|
91
|
+
const isTextPart = (p) => typeof p?.text === "string" && !(p.functionCall || p.function_call);
|
|
92
|
+
|
|
93
|
+
for await (const evt of streamSseDataEvents(response)) {
|
|
94
|
+
const cand = evt?.candidates?.[0];
|
|
95
|
+
if (evt?.usageMetadata) usageMetadata = evt.usageMetadata;
|
|
96
|
+
if (cand?.finishReason) finishReason = cand.finishReason;
|
|
97
|
+
|
|
98
|
+
for (const p of cand?.content?.parts || []) {
|
|
99
|
+
if (isTextPart(p) && !p.thought && p.text) {
|
|
100
|
+
try { onToken(p.text); } catch { /* a consumer throwing must not kill the turn */ }
|
|
101
|
+
}
|
|
102
|
+
// Text arrives in fragments; fold consecutive same-kind text parts back
|
|
103
|
+
// into one so the replayed model turn matches what a single-shot call
|
|
104
|
+
// would have produced. functionCall parts always arrive whole.
|
|
105
|
+
const last = parts[parts.length - 1];
|
|
106
|
+
if (
|
|
107
|
+
isTextPart(p) && last && isTextPart(last) &&
|
|
108
|
+
Boolean(last.thought) === Boolean(p.thought)
|
|
109
|
+
) {
|
|
110
|
+
last.text += p.text || "";
|
|
111
|
+
const sig = p.thoughtSignature || p.thought_signature;
|
|
112
|
+
if (sig) last.thoughtSignature = sig;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
parts.push({ ...p });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
candidates: [{ content: { parts }, finishReason }],
|
|
121
|
+
...(usageMetadata ? { usageMetadata } : {}),
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
|
|
74
125
|
/** Did this response mean "this key has no quota left", as opposed to a real error? */
|
|
75
126
|
function isQuotaError(status, json) {
|
|
76
127
|
if (status === 429) return true;
|
|
@@ -150,21 +201,13 @@ export const THOUGHT_SIGNATURE_MODELS = [
|
|
|
150
201
|
"gemini-5*",
|
|
151
202
|
];
|
|
152
203
|
|
|
153
|
-
function globToRegExp(pattern) {
|
|
154
|
-
const escaped = String(pattern).replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
155
|
-
return new RegExp(`^${escaped.replace(/\*/g, ".*").replace(/\?/g, ".")}$`, "i");
|
|
156
|
-
}
|
|
157
|
-
|
|
158
204
|
// Per-install override, no code change required:
|
|
159
205
|
// engines.gemini.thought_signature_models: ["gemini-3*", "my-tuned-model*"]
|
|
160
|
-
// A configured list REPLACES the built-in default — it is the whole answer to
|
|
161
|
-
// "which models use this mechanism", so an install can also opt out entirely
|
|
162
|
-
// with an explicit empty list.
|
|
163
206
|
export function modelUsesThoughtSignatures(model, config = {}) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
207
|
+
return matchesModelGlob(
|
|
208
|
+
model,
|
|
209
|
+
modelListFromConfig(config?.thought_signature_models, THOUGHT_SIGNATURE_MODELS)
|
|
210
|
+
);
|
|
168
211
|
}
|
|
169
212
|
|
|
170
213
|
function historyHasSignature(messages) {
|
|
@@ -193,7 +236,7 @@ function signaturesRequired(model, messages, config) {
|
|
|
193
236
|
// their thoughtSignature) that the signing families require in every
|
|
194
237
|
// subsequent turn. Falling back to reconstruction handles messages that came
|
|
195
238
|
// from a non-Gemini engine or were serialised before this field was added.
|
|
196
|
-
function toGeminiContents(messages, { model = "", config = {} } = {}) {
|
|
239
|
+
export function toGeminiContents(messages, { model = "", config = {} } = {}) {
|
|
197
240
|
const requireSignatures = signaturesRequired(model, messages, config);
|
|
198
241
|
const out = [];
|
|
199
242
|
// tool_call ids whose functionCall part we could not replay with a valid
|
|
@@ -231,6 +274,16 @@ function toGeminiContents(messages, { model = "", config = {} } = {}) {
|
|
|
231
274
|
} else {
|
|
232
275
|
out.push({ role: "user", parts: [part] });
|
|
233
276
|
}
|
|
277
|
+
// A multimodal tool result (view_media) carries images the model should
|
|
278
|
+
// SEE. A functionResponse can't hold pixels, so the image rides on a
|
|
279
|
+
// following user turn with a short cue, right after the result.
|
|
280
|
+
if (Array.isArray(m.images) && m.images.length) {
|
|
281
|
+
const imgParts = [{ text: `(imagen de ${name})` }];
|
|
282
|
+
for (const img of m.images) {
|
|
283
|
+
if (img?.data && img?.mime) imgParts.push({ inlineData: { mimeType: img.mime, data: img.data } });
|
|
284
|
+
}
|
|
285
|
+
if (imgParts.length > 1) out.push({ role: "user", parts: imgParts });
|
|
286
|
+
}
|
|
234
287
|
continue;
|
|
235
288
|
}
|
|
236
289
|
|
|
@@ -334,6 +387,7 @@ export default {
|
|
|
334
387
|
toolChoice,
|
|
335
388
|
config = {},
|
|
336
389
|
signal,
|
|
390
|
+
onToken,
|
|
337
391
|
}) {
|
|
338
392
|
const keys = getKeys(config);
|
|
339
393
|
if (!keys.length) throw new Error("gemini: no api_key (set GEMINI_API_KEY or engines.gemini.api_key)");
|
|
@@ -366,20 +420,34 @@ export default {
|
|
|
366
420
|
// request, not the turn.
|
|
367
421
|
const order = fresh.length ? fresh : keys;
|
|
368
422
|
|
|
423
|
+
// Streaming is opt-in per call: the caller wants tokens as they land, and
|
|
424
|
+
// the turn isn't forcing a function call (mode ANY produces a call, not
|
|
425
|
+
// prose — there'd be nothing to stream). Same request body either way; only
|
|
426
|
+
// the endpoint and how the response is read differ, so the key rotation and
|
|
427
|
+
// error handling below stay shared.
|
|
428
|
+
const wantsStream =
|
|
429
|
+
typeof onToken === "function" && toolChoice !== "required" && toolChoice !== "any";
|
|
430
|
+
|
|
369
431
|
let json;
|
|
370
432
|
let lastError = null;
|
|
371
433
|
for (let i = 0; i < order.length; i++) {
|
|
372
434
|
const key = order[i];
|
|
373
|
-
const
|
|
435
|
+
const verb = wantsStream ? "streamGenerateContent?alt=sse&" : "generateContent?";
|
|
436
|
+
const url = `${API_BASE}/${encodeURIComponent(model)}:${verb}key=${key}`;
|
|
374
437
|
const res = await fetch(url, {
|
|
375
438
|
method: "POST",
|
|
376
439
|
headers: { "content-type": "application/json" },
|
|
377
440
|
body: JSON.stringify(body),
|
|
378
441
|
signal,
|
|
379
442
|
});
|
|
380
|
-
const payload = await res.json();
|
|
381
443
|
|
|
382
|
-
|
|
444
|
+
// An SSE response body must not be read as JSON, so settle the ok/error
|
|
445
|
+
// question on the status first and only then choose how to read it.
|
|
446
|
+
if (res.ok) {
|
|
447
|
+
json = wantsStream ? await readGeminiStream(res, onToken) : await res.json();
|
|
448
|
+
break;
|
|
449
|
+
}
|
|
450
|
+
const payload = await res.json().catch(() => ({}));
|
|
383
451
|
|
|
384
452
|
if (isQuotaError(res.status, payload)) {
|
|
385
453
|
markExhausted(model, key);
|
|
@@ -17,9 +17,10 @@ import groq from "./groq.js";
|
|
|
17
17
|
import openrouter from "./openrouter.js";
|
|
18
18
|
import ollama from "./ollama.js";
|
|
19
19
|
import gemini from "./gemini.js";
|
|
20
|
+
import zen from "./zen.js";
|
|
20
21
|
import mock from "./mock.js";
|
|
21
22
|
|
|
22
|
-
const ADAPTERS = { anthropic, openai, groq, openrouter, ollama, gemini, mock };
|
|
23
|
+
const ADAPTERS = { anthropic, openai, groq, openrouter, ollama, gemini, zen, mock };
|
|
23
24
|
|
|
24
25
|
export function resolveProvider(modelId) {
|
|
25
26
|
if (typeof modelId !== "string" || !modelId) {
|
|
@@ -38,6 +39,18 @@ export function resolveProvider(modelId) {
|
|
|
38
39
|
);
|
|
39
40
|
}
|
|
40
41
|
|
|
42
|
+
/**
|
|
43
|
+
* The adapter behind a provider *slug*. A slug is not always an adapter id:
|
|
44
|
+
* a provider named "carlos" running on Ollama is stored as
|
|
45
|
+
* `engines.carlos = { engine: "ollama", … }`, and "carlos:llama3.2" has to
|
|
46
|
+
* reach the ollama adapter. Falls back to the slug itself, which is the case
|
|
47
|
+
* for the stock providers whose slug already is the engine id.
|
|
48
|
+
*/
|
|
49
|
+
export function adapterForSlug(slug, config) {
|
|
50
|
+
const cfg = (config && config.engines && config.engines[slug]) || {};
|
|
51
|
+
return getAdapter(cfg.engine || slug);
|
|
52
|
+
}
|
|
53
|
+
|
|
41
54
|
export function getAdapter(provider) {
|
|
42
55
|
const a = ADAPTERS[provider];
|
|
43
56
|
if (!a) {
|
|
@@ -48,10 +61,12 @@ export function getAdapter(provider) {
|
|
|
48
61
|
return a;
|
|
49
62
|
}
|
|
50
63
|
|
|
51
|
-
export async function callEngine({ modelId, system, messages, config, temperature, maxTokens, tools, toolChoice, signal, onToken }) {
|
|
64
|
+
export async function callEngine({ modelId, system, messages, config, temperature, maxTokens, tools, toolChoice, signal, onToken, onReasoningToken }) {
|
|
52
65
|
const { provider, model } = resolveProvider(modelId);
|
|
53
|
-
const adapter = getAdapter(provider);
|
|
54
66
|
const providerCfg = (config && config.engines && config.engines[provider]) || {};
|
|
67
|
+
// `provider` here is the slug the user configured, which only coincides with
|
|
68
|
+
// the adapter id for the stock providers.
|
|
69
|
+
const adapter = getAdapter(providerCfg.engine || provider);
|
|
55
70
|
// The per-provider `default_max_tokens` set in the web admin (Provider modal
|
|
56
71
|
// slider) acts as a floor: callers may ask for more, but never less. This
|
|
57
72
|
// matters for "thinking" models (e.g. Gemini 3.x) whose internal reasoning
|
|
@@ -73,6 +88,7 @@ export async function callEngine({ modelId, system, messages, config, temperatur
|
|
|
73
88
|
config: providerCfg,
|
|
74
89
|
signal,
|
|
75
90
|
onToken,
|
|
91
|
+
onReasoningToken,
|
|
76
92
|
});
|
|
77
93
|
}
|
|
78
94
|
|
package/src/core/engines/mock.js
CHANGED
|
@@ -10,9 +10,26 @@ export default {
|
|
|
10
10
|
return { ok: true, soft: true };
|
|
11
11
|
},
|
|
12
12
|
|
|
13
|
-
async chat({ system, messages, model = "mock", tools }) {
|
|
13
|
+
async chat({ system, messages, model = "mock", tools, signal }) {
|
|
14
|
+
const forcedStatus = String(model).match(/^fail-(\d{3})$/)?.[1];
|
|
15
|
+
if (forcedStatus) throw new Error(`mock ${forcedStatus}: forced test failure`);
|
|
14
16
|
const last = [...messages].reverse().find((m) => m.role === "user");
|
|
15
17
|
const userText = last?.content || "";
|
|
18
|
+
// `[mock:slow:<ms>]` → hold each step for <ms> before answering, and honor
|
|
19
|
+
// the abort signal while holding. A real engine call takes time, and
|
|
20
|
+
// anything about what happens DURING a turn — cancelling it, interrupting
|
|
21
|
+
// it, watching it stream — cannot be tested against a mock that finishes a
|
|
22
|
+
// 400-step loop in under a second. Capped so a typo cannot hang a suite.
|
|
23
|
+
const slowMs = Math.min(parseInt(userText.match(/\[mock:slow:(\d+)\]/)?.[1] ?? "0", 10) || 0, 5000);
|
|
24
|
+
if (slowMs) {
|
|
25
|
+
await new Promise((resolve, reject) => {
|
|
26
|
+
const t = setTimeout(resolve, slowMs);
|
|
27
|
+
signal?.addEventListener?.("abort", () => {
|
|
28
|
+
clearTimeout(t);
|
|
29
|
+
reject(Object.assign(new Error("aborted"), { name: "AbortError" }));
|
|
30
|
+
}, { once: true });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
16
33
|
// Mirror real engines: tool calls are only possible when the caller offers
|
|
17
34
|
// tools. The loop withholds them on its tool-free wrap-up step, and we must
|
|
18
35
|
// honor that here — otherwise the mock would keep "calling" tools the model
|
|
@@ -22,6 +39,16 @@ export default {
|
|
|
22
39
|
const loopTool = userText.match(/\[mock:loop:([a-z_]+)\]/)?.[1];
|
|
23
40
|
const finishSummary = userText.match(/\[mock:finish:([^\]]*)\]/)?.[1];
|
|
24
41
|
const hasToolResult = messages.some((m) => m.role === "tool");
|
|
42
|
+
// `[mock:system]` → the whole system prompt comes back as the answer, so a
|
|
43
|
+
// test can assert what the LOOP actually handed the engine rather than what
|
|
44
|
+
// the prompt builder returned in isolation.
|
|
45
|
+
if (/\[mock:system\]/.test(userText)) {
|
|
46
|
+
return {
|
|
47
|
+
text: String(system || ""),
|
|
48
|
+
usage: { input_tokens: userText.length, output_tokens: 0 },
|
|
49
|
+
raw: { model, mock: true },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
25
52
|
// `[mock:empty]` → a dud turn (no text, no tools) to exercise the loop's
|
|
26
53
|
// empty-retry / never-end-silent guard.
|
|
27
54
|
if (/\[mock:empty\]/.test(userText)) {
|
|
@@ -84,6 +111,123 @@ export default {
|
|
|
84
111
|
return mkToolCall(requestedTool, "mock-call-1");
|
|
85
112
|
}
|
|
86
113
|
|
|
114
|
+
// `[mock:cutoff]` → prose that hit the output cap: text, no tool calls,
|
|
115
|
+
// finish_reason "length". Models the turn that composed its work instead of
|
|
116
|
+
// doing it and ran out of budget. The SECOND time (once the loop has asked
|
|
117
|
+
// for the action) it calls the tool, so a test can assert the recovery.
|
|
118
|
+
if (/\[mock:cutoff:([a-z_]+)\]/.test(userText) || messages.some((m) => /\[mock:cutoff:/.test(String(m.content || "")))) {
|
|
119
|
+
const tool = messages
|
|
120
|
+
.map((m) => String(m.content || "").match(/\[mock:cutoff:([a-z_]+)\]/)?.[1])
|
|
121
|
+
.find(Boolean);
|
|
122
|
+
const nudged = messages.some((m) => /output limit and was cut off/i.test(String(m.content || "")));
|
|
123
|
+
if (nudged && toolsAvailable) return mkToolCall(tool, "mock-cutoff-1");
|
|
124
|
+
return {
|
|
125
|
+
text: "Idea 1: ... Idea 2: ... Idea 3: ... and then the budget ran ou",
|
|
126
|
+
finish_reason: "length",
|
|
127
|
+
usage: { input_tokens: userText.length, output_tokens: 512 },
|
|
128
|
+
raw: { model, mock: true },
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// `[mock:prose:<tool>]` → the leak of 2026-08-26: a model that WRITES the
|
|
133
|
+
// call instead of making it, copying the shape out of its own history,
|
|
134
|
+
// stale result and all. No tool_calls, so the API considers the turn
|
|
135
|
+
// finished and the loop is one step from delivering a transcript as the
|
|
136
|
+
// answer. Once the recovered call has run it answers normally, so a test
|
|
137
|
+
// can assert both halves: the tool fired, and none of it was spoken.
|
|
138
|
+
const proseTool =
|
|
139
|
+
userText.match(/\[mock:prose:([a-z_]+)\]/)?.[1] ||
|
|
140
|
+
messages.map((m) => String(m.content || "").match(/\[mock:prose:([a-z_]+)\]/)?.[1]).find(Boolean);
|
|
141
|
+
if (proseTool) {
|
|
142
|
+
if (hasToolResult) {
|
|
143
|
+
return {
|
|
144
|
+
text: "Listo, ya lo miré.",
|
|
145
|
+
usage: { input_tokens: userText.length, output_tokens: 8 },
|
|
146
|
+
raw: { model, mock: true },
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
return {
|
|
150
|
+
text: `Reviso eso y te confirmo. [tool ${proseTool}] {"project":"acme"} → ya estaba hecho`,
|
|
151
|
+
usage: { input_tokens: userText.length, output_tokens: 48 },
|
|
152
|
+
raw: { model, mock: true },
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// `[mock:fabricate:<tool>]` → the leak of 2026-08-29, one copy generation
|
|
157
|
+
// past `[mock:prose:…]`: a model that writes the whole TRANSCRIPT — several
|
|
158
|
+
// annotation lines with invented commands and invented output, then a
|
|
159
|
+
// confident report that the work is done. Nothing here is recoverable (no
|
|
160
|
+
// structured call, and the name is a paraphrase of the real tool's), so the
|
|
161
|
+
// only correct move is to refuse the text and ask for the real work. Once
|
|
162
|
+
// corrected it calls the tool, so a test can assert the recovery.
|
|
163
|
+
const fabricateTool =
|
|
164
|
+
userText.match(/\[mock:fabricate:([a-z_]+)\]/)?.[1] ||
|
|
165
|
+
messages.map((m) => String(m.content || "").match(/\[mock:fabricate:([a-z_]+)\]/)?.[1]).find(Boolean);
|
|
166
|
+
if (fabricateTool) {
|
|
167
|
+
const corrected = messages.some((m) =>
|
|
168
|
+
/written as if tools had run/i.test(String(m.content || "")),
|
|
169
|
+
);
|
|
170
|
+
if (corrected && toolsAvailable) return mkToolCall(fabricateTool, "mock-fabricate-1");
|
|
171
|
+
if (hasToolResult) {
|
|
172
|
+
return {
|
|
173
|
+
text: "Listo, ahora sí lo hice.",
|
|
174
|
+
usage: { input_tokens: userText.length, output_tokens: 8 },
|
|
175
|
+
raw: { model, mock: true },
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
text:
|
|
180
|
+
"[result: shell] adb devices → List of devices attached\n" +
|
|
181
|
+
"[result: shell] adb shell input keyevent 66 — send pressed\n\n" +
|
|
182
|
+
"Listo, ya se lo mandé.",
|
|
183
|
+
usage: { input_tokens: userText.length, output_tokens: 48 },
|
|
184
|
+
raw: { model, mock: true },
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// `[mock:copyomitted]` → the leak of 2026-09-02: the model copies the
|
|
189
|
+
// history annotation that stands in for a redacted answer and sends it as
|
|
190
|
+
// its whole reply, so Manu got `[omitted: this turn contained data that may
|
|
191
|
+
// be stale …]` in Telegram, twice. The reply is markup end to end — there
|
|
192
|
+
// is no answer inside it to rescue — so the loop must end the turn empty
|
|
193
|
+
// and let the surface's never-silent floor speak, never pass this on.
|
|
194
|
+
// Answers the same way every step on purpose: the empty retry re-sends the
|
|
195
|
+
// conversation unchanged, so a model that produces this once produces it
|
|
196
|
+
// again, and the loop has to hold anyway.
|
|
197
|
+
if (/\[mock:copyomitted\]/.test(userText)) {
|
|
198
|
+
return {
|
|
199
|
+
text:
|
|
200
|
+
"[omitted: this turn contained data that may be stale — call the " +
|
|
201
|
+
"tool again instead of repeating it]",
|
|
202
|
+
usage: { input_tokens: userText.length, output_tokens: 23 },
|
|
203
|
+
raw: { model, mock: true },
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// `mock:truncated` → a degenerate answer: non-empty, but far too small to
|
|
208
|
+
// stand in for anything. Models the flaky provider response that used to
|
|
209
|
+
// get written over a whole conversation as its "summary".
|
|
210
|
+
if (model === "truncated" || model === "mock:truncated") {
|
|
211
|
+
return {
|
|
212
|
+
text: "USER_CONTEXT:\n- Owner",
|
|
213
|
+
usage: { input_tokens: userText.length, output_tokens: 6 },
|
|
214
|
+
raw: { model, mock: true },
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// `[mock:reply:<text>]` → the model answers with exactly <text>. For tests
|
|
219
|
+
// about what the LOOP does with an answer rather than about producing one:
|
|
220
|
+
// the abstention marker is only interesting if the reply starts with it,
|
|
221
|
+
// and the default echo prefixes everything with "[mock:…] received:".
|
|
222
|
+
const replyText = userText.match(/\[mock:reply:([^\]]*)\]/)?.[1];
|
|
223
|
+
if (replyText !== undefined) {
|
|
224
|
+
return {
|
|
225
|
+
text: replyText,
|
|
226
|
+
usage: { input_tokens: userText.length, output_tokens: replyText.length },
|
|
227
|
+
raw: { model, mock: true },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
87
231
|
const sysHint = system ? ` (system: ${system.slice(0, 40)}…)` : "";
|
|
88
232
|
return {
|
|
89
233
|
text: `[mock:${model}] received: ${userText}${sysHint}`,
|