@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
|
@@ -6,14 +6,58 @@
|
|
|
6
6
|
// POST /projects/:pid/agents/:slug/compact
|
|
7
7
|
// POST /projects/:pid/agents/:slug/conversations/:id/compact
|
|
8
8
|
// POST /projects/:pid/send (agent-to-agent)
|
|
9
|
+
import fs from "node:fs";
|
|
9
10
|
import { readAgents } from "#core/apc/parser.js";
|
|
10
|
-
import { listConversations, readConversation, deleteConversation } from "#core/stores/conversations.js";
|
|
11
|
-
import { listGlobalThreads, readGlobalThread, deleteGlobalThread } from "#core/stores/messages.js";
|
|
11
|
+
import { listConversations, readConversation, deleteConversation, truncateConversation, setConversationMeta, shapeConversationMessage } from "#core/stores/conversations.js";
|
|
12
|
+
import { listGlobalThreads, readGlobalThread, deleteGlobalThread, setGlobalThreadMeta, listProjectA2AThreads, readProjectA2AThread, listProjectGroupThreads, readProjectGroupThread, deleteGroupThread, deleteA2AThread, readProjectMessages, readA2APeerSession, dedupA2A } from "#core/stores/messages.js";
|
|
13
|
+
import { shortId } from "#core/util/ids.js";
|
|
14
|
+
|
|
15
|
+
// Prior turns of an a2a thread between `from` and `to`, oldest→newest, shaped as
|
|
16
|
+
// LLM messages from `viewer`'s side (its own lines = assistant, the peer's =
|
|
17
|
+
// user). This is what gives an a2a reply MEMORY: without it every --deliver is a
|
|
18
|
+
// stateless one-shot and the agent forgets the previous turn. Loaded BEFORE the
|
|
19
|
+
// current message is logged, so it excludes it.
|
|
20
|
+
function a2aPairHistory(storageRoot, from, to, viewer, limit = 24) {
|
|
21
|
+
const pair = new Set([from, to]);
|
|
22
|
+
const rows = readProjectMessages(storageRoot, { channel: "a2a", limit: 300 }).filter((m) => {
|
|
23
|
+
const parts = [m.agent_slug, m.author, m.meta?.from, m.meta?.to].filter(Boolean);
|
|
24
|
+
return parts.length > 0 && parts.every((s) => pair.has(s));
|
|
25
|
+
});
|
|
26
|
+
return dedupA2A(rows)
|
|
27
|
+
.sort((a, b) => (a.ts || "").localeCompare(b.ts || ""))
|
|
28
|
+
.slice(-limit)
|
|
29
|
+
.map((m) =>
|
|
30
|
+
m.author === viewer
|
|
31
|
+
? { role: "assistant", content: m.body || "" }
|
|
32
|
+
: { role: "user", content: `From ${m.author}:\n\n${m.body || ""}` },
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
/** The sender's working directory, if it still is one. This is untrusted input
|
|
36
|
+
* naming a directory we are about to spawn a coding CLI in, so it gets checked
|
|
37
|
+
* rather than believed; anything else falls back to the project path. */
|
|
38
|
+
function senderCwd(raw) {
|
|
39
|
+
if (!raw || typeof raw !== "string") return null;
|
|
40
|
+
try {
|
|
41
|
+
return fs.statSync(raw).isDirectory() ? raw : null;
|
|
42
|
+
} catch {
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
12
47
|
import { compactConversation } from "#core/stores/conversations-compactor.js";
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
48
|
+
import { getActiveTurnByKey, convTurnKey, superAgentTurnKey } from "../active-turns.js";
|
|
49
|
+
import { replyToPeer } from "#core/agent/a2a/reply.js";
|
|
50
|
+
import { resolvePeer, peerAddress, refusesCodeMode, NO_CODE_PEERS } from "#core/agent/a2a/peers.js";
|
|
51
|
+
import { createCodeSession, getCodeSession, appendTurn as appendCodeTurn } from "#core/stores/code-sessions.js";
|
|
52
|
+
import { CODE_MODES } from "#core/constants/code-modes.js";
|
|
53
|
+
import { RUNTIME_IDS } from "#core/runtimes/index.js";
|
|
54
|
+
import { resolveAgentModel } from "#core/agent/agent-model.js";
|
|
55
|
+
import { notifyOwnerViaRoby } from "#core/routines/delivery.js";
|
|
56
|
+
import { A2A_SEVERITY } from "#core/routines/signals.js";
|
|
57
|
+
import { nowIso, asyncRoute, a2aSlugThreadId, rejectA2AWrite } from "./shared.js";
|
|
58
|
+
import { faceResolverFor, readAgentsSafe } from "./thread-faces.js";
|
|
15
59
|
|
|
16
|
-
export function register(api, { project, config }) {
|
|
60
|
+
export function register(api, { projects, project, config, plugins, registries }) {
|
|
17
61
|
// The super-agent (default name "apx") is a pseudo-agent: it owns
|
|
18
62
|
// conversations per project but is NOT listed in AGENTS.md. Resolve its slug
|
|
19
63
|
// so `apx conversations list` (which defaults to the super-agent) works
|
|
@@ -22,38 +66,131 @@ export function register(api, { project, config }) {
|
|
|
22
66
|
const agentResolvable = (p, slug) =>
|
|
23
67
|
slug === superAgentSlug() || readAgents(p.path).some((a) => a.slug === slug);
|
|
24
68
|
|
|
69
|
+
// The inbox lists a2a "group chats" under a SYNTHETIC slug, `a2a:<pairId>`
|
|
70
|
+
// (see api/inbox.js) — a pair exchange is nobody's individual conversation,
|
|
71
|
+
// so it has no agents/<slug>/conversations/ directory. Those rows are opened
|
|
72
|
+
// through this same per-agent surface, so unless the slug resolves here every
|
|
73
|
+
// a2a row in the inbox dead-ends on "agent not found".
|
|
74
|
+
//
|
|
75
|
+
// NOT a URL-parsing problem: Express hands `a2a:cursor~roby` through intact,
|
|
76
|
+
// percent-encoded or not (verified both ways against the running daemon).
|
|
77
|
+
// The id was reaching the handler fine; there was simply no code path that
|
|
78
|
+
// could read a pair thread. `readProjectA2AThread` already existed and
|
|
79
|
+
// already returns the viewer's shape — it was never wired to a route.
|
|
80
|
+
|
|
25
81
|
api.get("/projects/:pid/agents/:slug/conversations", (req, res) => {
|
|
26
82
|
const p = project(req, res);
|
|
27
83
|
if (!p) return;
|
|
84
|
+
const listA2A = a2aSlugThreadId(req.params.slug);
|
|
85
|
+
if (listA2A !== null) {
|
|
86
|
+
const found = listProjectA2AThreads(p.storagePath).find((t) => t.id === listA2A);
|
|
87
|
+
const th = found && faceResolverFor(projects).decorate(found, readAgentsSafe(p.path));
|
|
88
|
+
// One pair id is one thread. Shaped like a conversation summary so the
|
|
89
|
+
// sidebar renders it beside the ordinary ones.
|
|
90
|
+
return res.json(th ? [{
|
|
91
|
+
id: th.id,
|
|
92
|
+
filename: `${th.id}.a2a`,
|
|
93
|
+
agent_slug: req.params.slug,
|
|
94
|
+
started_at: th.started_at || "",
|
|
95
|
+
last_turn_at: th.last_ts || th.started_at || "",
|
|
96
|
+
channel: "a2a",
|
|
97
|
+
messages: th.messages,
|
|
98
|
+
title: th.title,
|
|
99
|
+
participants: th.participants,
|
|
100
|
+
participant_faces: th.participant_faces,
|
|
101
|
+
preview: th.preview || undefined,
|
|
102
|
+
preview_at: th.last_ts || undefined,
|
|
103
|
+
}] : []);
|
|
104
|
+
}
|
|
105
|
+
if (!agentResolvable(p, req.params.slug))
|
|
106
|
+
return res.status(404).json({ error: "agent not found" });
|
|
107
|
+
res.json(
|
|
108
|
+
listConversations(p.storagePath, req.params.slug, {
|
|
109
|
+
includeArchived: req.query.include_archived === "1",
|
|
110
|
+
}).map((conversation) => ({
|
|
111
|
+
...conversation,
|
|
112
|
+
active_turn: getActiveTurnByKey(convTurnKey(p.id, conversation.id)),
|
|
113
|
+
})),
|
|
114
|
+
);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
// Rename, or put away. Archiving is the smaller decision — the file stays
|
|
118
|
+
// exactly where it is and only drops out of the lists that offer chats to
|
|
119
|
+
// resume, so it stays a decision you can take back.
|
|
120
|
+
api.patch("/projects/:pid/agents/:slug/conversations/:id", (req, res) => {
|
|
121
|
+
const p = project(req, res);
|
|
122
|
+
if (!p) return;
|
|
123
|
+
// An a2a thread is derived from the message ledger, not a file with
|
|
124
|
+
// frontmatter, so there is nothing to rename or archive. Say that, rather
|
|
125
|
+
// than the misleading "agent not found" this used to answer.
|
|
126
|
+
if (rejectA2AWrite(req, res, "renamed or archived")) return;
|
|
28
127
|
if (!agentResolvable(p, req.params.slug))
|
|
29
128
|
return res.status(404).json({ error: "agent not found" });
|
|
30
|
-
|
|
129
|
+
const { title, archived } = req.body || {};
|
|
130
|
+
if (title === undefined && archived === undefined)
|
|
131
|
+
return res.status(400).json({ error: "nothing to change" });
|
|
132
|
+
const ok = setConversationMeta(p.storagePath, req.params.slug, req.params.id, {
|
|
133
|
+
...(title !== undefined ? { title } : {}),
|
|
134
|
+
...(archived !== undefined ? { archived: !!archived } : {}),
|
|
135
|
+
});
|
|
136
|
+
if (!ok) return res.status(404).json({ error: "conversation not found" });
|
|
137
|
+
res.json({ ok: true });
|
|
31
138
|
});
|
|
32
139
|
|
|
33
140
|
api.get("/projects/:pid/agents/:slug/conversations/:id", (req, res) => {
|
|
34
141
|
const p = project(req, res);
|
|
35
142
|
if (!p) return;
|
|
143
|
+
const detailA2A = a2aSlugThreadId(req.params.slug);
|
|
144
|
+
if (detailA2A !== null) {
|
|
145
|
+
const found = readProjectA2AThread(p.storagePath, detailA2A || req.params.id);
|
|
146
|
+
if (!found) return res.status(404).json({ error: "conversation not found" });
|
|
147
|
+
const th = faceResolverFor(projects).decorate(found, readAgentsSafe(p.path));
|
|
148
|
+
return res.json({
|
|
149
|
+
id: th.id,
|
|
150
|
+
agent_slug: req.params.slug,
|
|
151
|
+
channel: "a2a",
|
|
152
|
+
messages: th.messages,
|
|
153
|
+
meta: {
|
|
154
|
+
channel: "a2a",
|
|
155
|
+
title: th.title,
|
|
156
|
+
participants: th.participants,
|
|
157
|
+
participant_faces: th.participant_faces,
|
|
158
|
+
},
|
|
159
|
+
});
|
|
160
|
+
}
|
|
36
161
|
const conv = readConversation(p.storagePath, req.params.slug, req.params.id);
|
|
37
162
|
if (!conv) return res.status(404).json({ error: "conversation not found" });
|
|
38
163
|
// Shape the response as the `ConversationDetail` the web client expects:
|
|
39
164
|
// `messages[]` (mapped from the parsed `turns`) + id/agent/channel. Without
|
|
40
165
|
// this the client's `detail.messages.filter(...)` throws on every load.
|
|
166
|
+
//
|
|
167
|
+
// `active_turn` is the turn being written RIGHT NOW, if any — so a surface
|
|
168
|
+
// opening (or re-opening) this chat mid-answer shows the partial and then
|
|
169
|
+
// follows the live "turn" frames, instead of a blank pane that fills all at
|
|
170
|
+
// once when the turn happens to finish.
|
|
41
171
|
res.json({
|
|
42
172
|
id: req.params.id,
|
|
43
173
|
agent_slug: req.params.slug,
|
|
44
174
|
channel: conv.fm?.channel,
|
|
45
|
-
messages: (conv.turns || []).map(
|
|
46
|
-
role: t.role,
|
|
47
|
-
content: t.content,
|
|
48
|
-
ts: t.ts,
|
|
49
|
-
})),
|
|
175
|
+
messages: (conv.turns || []).map(shapeConversationMessage),
|
|
50
176
|
meta: conv.fm || {},
|
|
177
|
+
active_turn: getActiveTurnByKey(convTurnKey(p.id, req.params.id)),
|
|
51
178
|
});
|
|
52
179
|
});
|
|
53
180
|
|
|
54
181
|
api.delete("/projects/:pid/agents/:slug/conversations/:id", (req, res) => {
|
|
55
182
|
const p = project(req, res);
|
|
56
183
|
if (!p) return;
|
|
184
|
+
// Deleting IS something an a2a thread can do — it is the one write on this
|
|
185
|
+
// surface that has a meaning for a derived thread, so it delegates to the
|
|
186
|
+
// pair delete instead of refusing. The refusals left below (rename, archive,
|
|
187
|
+
// compact, chat) are the ones with nothing to act on.
|
|
188
|
+
const delA2A = a2aSlugThreadId(req.params.slug);
|
|
189
|
+
if (delA2A !== null) {
|
|
190
|
+
const out = deleteA2AThread(p.storagePath, delA2A || req.params.id);
|
|
191
|
+
if (!out.removed) return res.status(404).json({ error: "conversation not found" });
|
|
192
|
+
return res.json({ ok: true, ...out });
|
|
193
|
+
}
|
|
57
194
|
if (!agentResolvable(p, req.params.slug))
|
|
58
195
|
return res.status(404).json({ error: "agent not found" });
|
|
59
196
|
const ok = deleteConversation(p.storagePath, req.params.slug, req.params.id);
|
|
@@ -61,32 +198,144 @@ export function register(api, { project, config }) {
|
|
|
61
198
|
res.json({ ok: true });
|
|
62
199
|
});
|
|
63
200
|
|
|
201
|
+
// Rewind a conversation to its first `turns` turns, dropping the rest. Backs
|
|
202
|
+
// "regenerate" and "edit & resend": the pane rewinds to a turn and the file
|
|
203
|
+
// must rewind with it, or a project agent (whose history the daemon rebuilds
|
|
204
|
+
// from this file) would keep answering with the dropped turns still present.
|
|
205
|
+
api.post("/projects/:pid/agents/:slug/conversations/:id/truncate", (req, res) => {
|
|
206
|
+
const p = project(req, res);
|
|
207
|
+
if (!p) return;
|
|
208
|
+
if (rejectA2AWrite(req, res, "truncated")) return;
|
|
209
|
+
if (!agentResolvable(p, req.params.slug))
|
|
210
|
+
return res.status(404).json({ error: "agent not found" });
|
|
211
|
+
const keepVisible = Number(req.body?.keep_visible);
|
|
212
|
+
if (!Number.isInteger(keepVisible) || keepVisible < 0)
|
|
213
|
+
return res.status(400).json({ error: "keep_visible must be a non-negative integer" });
|
|
214
|
+
const ok = truncateConversation(p.storagePath, req.params.slug, req.params.id, { keepVisible });
|
|
215
|
+
if (!ok) return res.status(404).json({ error: "conversation not found" });
|
|
216
|
+
res.json({ ok: true });
|
|
217
|
+
});
|
|
218
|
+
|
|
64
219
|
// ---- Super-agent channel threads ----
|
|
65
220
|
// The super-agent's chats (telegram, web quick-chat, desktop, deck …) live
|
|
66
221
|
// in the global per-channel ledger, not in per-agent conversation files.
|
|
67
222
|
// These endpoints surface that ledger as day-threads so the web Chats
|
|
68
223
|
// sidebar can list and reopen them.
|
|
224
|
+
//
|
|
225
|
+
// Scope: each project lists only the super-agent chats that happened in it.
|
|
226
|
+
// The default workspace (project 0) additionally owns every unstamped turn —
|
|
227
|
+
// Telegram, desktop and deck have no project of their own, so that is where
|
|
228
|
+
// those conversations live. Passing `undefined` for project 0, as this used
|
|
229
|
+
// to, means "no filter", and the unstamped-rows-belong-everywhere rule it
|
|
230
|
+
// paired with then listed the same ~90 Telegram threads under every project.
|
|
231
|
+
// Channel grouping is untouched: a project with its own Telegram routing
|
|
232
|
+
// still gets a Telegram group holding just its chats.
|
|
233
|
+
const threadScope = (p) => String(p.id);
|
|
234
|
+
|
|
69
235
|
api.get("/projects/:pid/super-agent/threads", (req, res) => {
|
|
70
236
|
const p = project(req, res);
|
|
71
237
|
if (!p) return;
|
|
72
|
-
|
|
238
|
+
// Global channel threads (telegram/web/desktop…) live in the cross-project
|
|
239
|
+
// ledger; a2a "group chats" are project-scoped, so they come from this
|
|
240
|
+
// project's own messages. Both fold into the same channel-grouped sidebar.
|
|
241
|
+
const global = listGlobalThreads({
|
|
242
|
+
project: threadScope(p),
|
|
243
|
+
includeArchived: req.query.include_archived === "1",
|
|
244
|
+
}).map((thread) => {
|
|
245
|
+
const active = getActiveTurnByKey(superAgentTurnKey(p.id, thread.channel));
|
|
246
|
+
return {
|
|
247
|
+
...thread,
|
|
248
|
+
active_turn: active?.thread_id === thread.id ? active : null,
|
|
249
|
+
};
|
|
250
|
+
});
|
|
251
|
+
let a2a = [];
|
|
252
|
+
try { a2a = listProjectA2AThreads(p.storagePath); } catch { /* best-effort */ }
|
|
253
|
+
let groups = [];
|
|
254
|
+
try { groups = listProjectGroupThreads(p.storagePath); } catch { /* best-effort */ }
|
|
255
|
+
// a2a and group threads carry their participants' faces and a title made of
|
|
256
|
+
// real names — the same decoration the inbox rows get, from the same
|
|
257
|
+
// resolver (thread-faces.js). Without it the sidebar had to re-derive faces
|
|
258
|
+
// from its own agent list (which does not know the super-agent or a coding
|
|
259
|
+
// CLI) and the thread header, having no list at all, fell back to printing
|
|
260
|
+
// the raw pair id: `andy~claude-code` where "Andy · Claude" belongs.
|
|
261
|
+
const faces = faceResolverFor(projects);
|
|
262
|
+
const agents = readAgentsSafe(p.path);
|
|
263
|
+
const decorated = [...a2a, ...groups].map((th) => faces.decorate(th, agents));
|
|
264
|
+
res.json([...global, ...decorated]);
|
|
73
265
|
});
|
|
74
266
|
|
|
75
267
|
api.get("/projects/:pid/super-agent/threads/:channel/:id", (req, res) => {
|
|
76
268
|
const p = project(req, res);
|
|
77
269
|
if (!p) return;
|
|
78
|
-
|
|
270
|
+
// a2a threads are keyed by participant-pair id, not a date — read them from
|
|
271
|
+
// the project ledger; everything else is a global channel+date thread.
|
|
272
|
+
const thread = req.params.channel === "a2a"
|
|
273
|
+
? readProjectA2AThread(p.storagePath, req.params.id)
|
|
274
|
+
: req.params.channel === "group"
|
|
275
|
+
? readProjectGroupThread(p.storagePath, req.params.id)
|
|
276
|
+
: readGlobalThread({
|
|
277
|
+
channel: req.params.channel,
|
|
278
|
+
date: req.params.id,
|
|
279
|
+
project: threadScope(p),
|
|
280
|
+
});
|
|
281
|
+
if (!thread) return res.status(404).json({ error: "thread not found" });
|
|
282
|
+
// Same decoration as the list: whoever opens a thread directly (a deep link,
|
|
283
|
+
// the phone, a pane that was handed no row) gets the faces and the name with
|
|
284
|
+
// the messages, instead of having to ask a second surface for them.
|
|
285
|
+
const decorated = faceResolverFor(projects).decorate(thread, readAgentsSafe(p.path));
|
|
286
|
+
const active = req.params.channel === "a2a" || req.params.channel === "group"
|
|
287
|
+
? null
|
|
288
|
+
: getActiveTurnByKey(superAgentTurnKey(p.id, req.params.channel));
|
|
289
|
+
res.json({
|
|
290
|
+
...decorated,
|
|
291
|
+
active_turn: active?.thread_id === req.params.id ? active : null,
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
|
|
295
|
+
api.delete("/projects/:pid/super-agent/threads/:channel/:id", (req, res) => {
|
|
296
|
+
const p = project(req, res);
|
|
297
|
+
if (!p) return;
|
|
298
|
+
// A group is a ledger thread of its own — delete every row for it, not a
|
|
299
|
+
// global channel+date file (which is what 404'd before).
|
|
300
|
+
//
|
|
301
|
+
// An a2a pair is the same shape of thing: rows in THIS project's ledger,
|
|
302
|
+
// not a global channel+date file. It fell through to `deleteGlobalThread`,
|
|
303
|
+
// which looks for a file named after the pair id and never finds one — so
|
|
304
|
+
// the panel's Delete answered 404 on every agent-to-agent chat, and there
|
|
305
|
+
// was no other way to remove one. Reading a thread nobody can delete is
|
|
306
|
+
// half a surface.
|
|
307
|
+
if (req.params.channel === "group" || req.params.channel === "a2a") {
|
|
308
|
+
const out = req.params.channel === "group"
|
|
309
|
+
? deleteGroupThread(p.storagePath, req.params.id)
|
|
310
|
+
: deleteA2AThread(p.storagePath, req.params.id);
|
|
311
|
+
try { projects.rebuild(p.id); } catch { /* best-effort */ }
|
|
312
|
+
if (!out.removed) return res.status(404).json({ error: "thread not found" });
|
|
313
|
+
return res.json({ ok: true, ...out });
|
|
314
|
+
}
|
|
315
|
+
const ok = deleteGlobalThread({
|
|
79
316
|
channel: req.params.channel,
|
|
80
317
|
date: req.params.id,
|
|
318
|
+
project: threadScope(p),
|
|
81
319
|
});
|
|
82
|
-
if (!
|
|
83
|
-
res.json(
|
|
320
|
+
if (!ok) return res.status(404).json({ error: "thread not found" });
|
|
321
|
+
res.json({ ok: true });
|
|
84
322
|
});
|
|
85
323
|
|
|
86
|
-
|
|
324
|
+
// A channel thread has no file of its own to carry a name, so the two
|
|
325
|
+
// decisions a reader can make about one — what to call it, whether to put it
|
|
326
|
+
// away — live in a small index beside the ledger. The messages are untouched.
|
|
327
|
+
api.patch("/projects/:pid/super-agent/threads/:channel/:id", (req, res) => {
|
|
87
328
|
const p = project(req, res);
|
|
88
329
|
if (!p) return;
|
|
89
|
-
const
|
|
330
|
+
const { title, archived } = req.body || {};
|
|
331
|
+
if (title === undefined && archived === undefined)
|
|
332
|
+
return res.status(400).json({ error: "nothing to change" });
|
|
333
|
+
const ok = setGlobalThreadMeta({
|
|
334
|
+
channel: req.params.channel,
|
|
335
|
+
date: req.params.id,
|
|
336
|
+
...(title !== undefined ? { title } : {}),
|
|
337
|
+
...(archived !== undefined ? { archived: !!archived } : {}),
|
|
338
|
+
});
|
|
90
339
|
if (!ok) return res.status(404).json({ error: "thread not found" });
|
|
91
340
|
res.json({ ok: true });
|
|
92
341
|
});
|
|
@@ -94,10 +343,15 @@ export function register(api, { project, config }) {
|
|
|
94
343
|
async function handleCompact(req, res, filename) {
|
|
95
344
|
const p = project(req, res);
|
|
96
345
|
if (!p) return;
|
|
346
|
+
if (rejectA2AWrite(req, res, "compacted")) return;
|
|
97
347
|
const agents = readAgents(p.path);
|
|
98
348
|
const agent = agents.find((a) => a.slug === req.params.slug);
|
|
99
349
|
if (!agent) return res.status(404).json({ error: "agent not found" });
|
|
100
|
-
const modelId = (
|
|
350
|
+
const modelId = await resolveAgentModel({
|
|
351
|
+
agent,
|
|
352
|
+
config: p.config || config,
|
|
353
|
+
override: (req.body || {}).model,
|
|
354
|
+
});
|
|
101
355
|
if (!modelId) return res.status(400).json({ error: "agent has no model" });
|
|
102
356
|
try {
|
|
103
357
|
const result = await compactConversation({
|
|
@@ -126,64 +380,254 @@ export function register(api, { project, config }) {
|
|
|
126
380
|
api.post("/projects/:pid/send", asyncRoute(async (req, res) => {
|
|
127
381
|
const p = project(req, res);
|
|
128
382
|
if (!p) return;
|
|
129
|
-
const { from, to, body, deliver = false, _depth = 0 } = req.body || {};
|
|
130
|
-
|
|
383
|
+
const { from, to: toRaw, body, deliver = false, _depth = 0, requested_by = null, severity = null, model = null, usage = null, code = false, background = false, timeout_s = null } = req.body || {};
|
|
384
|
+
// Two kinds of exchange, and the difference is real: a `chat` peer runs in
|
|
385
|
+
// its own read-only mode, a `code` peer may write. Chat is the default
|
|
386
|
+
// because receiving a message must not be enough to let the sender rewrite
|
|
387
|
+
// your checkout — opening a coding session is a decision.
|
|
388
|
+
const mode = code ? "code" : "chat";
|
|
389
|
+
// A conversation answers in seconds; a coding session does not. Background
|
|
390
|
+
// runs get the hour that `call_runtime` gives its own detached spawns.
|
|
391
|
+
const timeoutMs = (Number(timeout_s) || (background ? 3600 : 300)) * 1000;
|
|
392
|
+
if (!from || !toRaw || !body)
|
|
131
393
|
return res.status(400).json({ error: "from, to, body required" });
|
|
132
394
|
if (_depth > 3)
|
|
133
395
|
return res.status(429).json({ error: "a2a depth limit (3) exceeded" });
|
|
134
396
|
|
|
397
|
+
// Urgency tag: blocker|status|fyi. Only a known tag is kept — an unknown one
|
|
398
|
+
// is dropped rather than stored as a severity the detector can't map.
|
|
399
|
+
const sevTag = severity && A2A_SEVERITY[String(severity).toLowerCase()]
|
|
400
|
+
? String(severity).toLowerCase() : null;
|
|
401
|
+
const sevMeta = sevTag ? { severity: sevTag } : {};
|
|
402
|
+
|
|
135
403
|
const agents = readAgents(p.path);
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
404
|
+
// The SENDER may be a project agent, the super-agent, or an external
|
|
405
|
+
// identity that isn't registered anywhere — a coding CLI (claude/codex/…)
|
|
406
|
+
// relaying to an agent, a routine, a system actor. Requiring `from` to be an
|
|
407
|
+
// AGENTS.md agent is what blocked CLI→agent relays (404 "from not found").
|
|
408
|
+
// A synthetic sender ({slug}) is enough: the reply layer only reads `from.slug`,
|
|
409
|
+
// and the a2a log records the label. The RECIPIENT still has to exist, so a
|
|
410
|
+
// typo'd or wrong-project target fails loudly instead of vanishing.
|
|
411
|
+
const fromAgent = agents.find((a) => a.slug === from) || { slug: from, fields: {}, synthetic: true };
|
|
412
|
+
// The RECIPIENT is a PEER, not necessarily an agent: `to` may name an
|
|
413
|
+
// AGENTS.md agent or an external coding runtime (opencode, codex,
|
|
414
|
+
// claude-code, …), optionally with a `#thread` suffix that keeps two
|
|
415
|
+
// exchanges with the same peer from reading each other's mail. A name that
|
|
416
|
+
// nothing claims still fails loudly rather than vanishing.
|
|
417
|
+
const peer = resolvePeer(toRaw, agents, p.config || config);
|
|
418
|
+
if (!peer)
|
|
419
|
+
return res.status(404).json({
|
|
420
|
+
error: `no agent or runtime "${toRaw}" in project "${p.name}"`,
|
|
421
|
+
project: p.name,
|
|
422
|
+
available: agents.map((a) => a.slug),
|
|
423
|
+
runtimes: RUNTIME_IDS,
|
|
424
|
+
hint: "run `apx agent list --all` for agents and their projects; a runtime peer is any id in `runtimes`",
|
|
425
|
+
});
|
|
426
|
+
|
|
427
|
+
// One peer, one thread. Everything below files under the name the peer
|
|
428
|
+
// actually has — `Magui`, `magui`, `default`, `roby` and `apx` are not five
|
|
429
|
+
// correspondents. Addressing the super-agent by any of its aliases used to
|
|
430
|
+
// open a thread per alias, keyed by a string the inbox could not resolve to
|
|
431
|
+
// anyone; a project agent addressed by display name or in the wrong case did
|
|
432
|
+
// the same. The `:thread` suffix survives — that one IS a discriminator.
|
|
433
|
+
const to = peerAddress(peer);
|
|
434
|
+
|
|
435
|
+
if (mode === "code" && refusesCodeMode(peer)) {
|
|
436
|
+
return res.status(400).json({
|
|
437
|
+
error: `"${peer.runtime}" cannot be opened as a --code peer`,
|
|
438
|
+
no_code_peers: NO_CODE_PEERS,
|
|
439
|
+
hint:
|
|
440
|
+
`${peer.runtime} is a CLI you drive yourself — a message must not also start it writing to the same ` +
|
|
441
|
+
`checkout. Send without --code to ask it something, or open the coding session on another peer.`,
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
// Snapshot the prior conversation BEFORE we log the new message, so the
|
|
446
|
+
// reply sees history without the turn it is answering.
|
|
447
|
+
const history = deliver ? a2aPairHistory(p.storagePath, from, to, to) : [];
|
|
448
|
+
|
|
449
|
+
// Attribute the sender's message the way every other channel does: an
|
|
450
|
+
// explicit override wins (a caller that knows the real cost — a routine
|
|
451
|
+
// relaying its run — passes model/usage); otherwise stamp the sender agent's
|
|
452
|
+
// configured model, so an a2a message shows whose model spoke instead of a
|
|
453
|
+
// blank row. Usage stays absent on a plain relay — it spends no tokens.
|
|
454
|
+
const attrib = {};
|
|
455
|
+
const overrideModel = typeof model === "string" && model ? model : null;
|
|
456
|
+
let senderModel = overrideModel;
|
|
457
|
+
if (!senderModel && !fromAgent.synthetic) {
|
|
458
|
+
try { senderModel = await resolveAgentModel({ agent: fromAgent, config: p.config || config }); }
|
|
459
|
+
catch { /* no model resolvable → leave the row unattributed */ }
|
|
460
|
+
}
|
|
461
|
+
if (senderModel) attrib.model = senderModel;
|
|
462
|
+
if (usage && typeof usage === "object") attrib.usage = usage;
|
|
142
463
|
|
|
143
464
|
const ts = nowIso();
|
|
465
|
+
const messageId = shortId("a2a");
|
|
144
466
|
p.logMessage({
|
|
145
467
|
agent_slug: from,
|
|
146
468
|
channel: "a2a",
|
|
147
469
|
direction: "out",
|
|
148
470
|
author: from,
|
|
149
471
|
body,
|
|
150
|
-
meta: { to, depth: _depth },
|
|
472
|
+
meta: { to, depth: _depth, final: true, ...sevMeta, ...attrib, ...(requested_by ? { requested_by } : {}) },
|
|
151
473
|
ts,
|
|
474
|
+
external_id: messageId,
|
|
152
475
|
});
|
|
476
|
+
|
|
477
|
+
// A `blocker` is an alert, not a note for the next digest: Roby pings the
|
|
478
|
+
// owner in the act (canNudge's critical-bypass crosses budget and quiet
|
|
479
|
+
// hours). Done here — before the inbound row a watch would pick up later —
|
|
480
|
+
// so the ping never waits for a scheduled sweep. A successful ping stamps
|
|
481
|
+
// the inbound row `owner_notified` so the watch does not tell him twice; if
|
|
482
|
+
// it is held/skipped the flag is absent, so the watch remains the fallback.
|
|
483
|
+
let ownerNotify = null;
|
|
484
|
+
if (sevTag === "blocker") {
|
|
485
|
+
try {
|
|
486
|
+
ownerNotify = await notifyOwnerViaRoby(
|
|
487
|
+
{ project: p, plugins, registries, globalConfig: p.config || config },
|
|
488
|
+
{
|
|
489
|
+
routine: { name: `a2a:${from}->${to}`, id: "" },
|
|
490
|
+
agent: { slug: from, name: from },
|
|
491
|
+
text: body,
|
|
492
|
+
notify: body,
|
|
493
|
+
gate: { severity: "critical", scheduled: false, unsolicited: true, project_id: p.id ?? null },
|
|
494
|
+
severity: "critical",
|
|
495
|
+
},
|
|
496
|
+
);
|
|
497
|
+
} catch (e) {
|
|
498
|
+
ownerNotify = { skipped: true, reason: e?.message || String(e) };
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
const ownerNotified = ownerNotify?.sent === true;
|
|
502
|
+
|
|
153
503
|
p.logMessage({
|
|
154
504
|
agent_slug: to,
|
|
155
505
|
channel: "a2a",
|
|
156
506
|
direction: "in",
|
|
157
507
|
author: from,
|
|
158
508
|
body,
|
|
159
|
-
meta: {
|
|
509
|
+
meta: {
|
|
510
|
+
from, depth: _depth, ...sevMeta, ...attrib,
|
|
511
|
+
...(ownerNotified ? { owner_notified: true } : {}),
|
|
512
|
+
...(requested_by ? { requested_by } : {}),
|
|
513
|
+
},
|
|
160
514
|
ts,
|
|
515
|
+
external_id: messageId,
|
|
161
516
|
});
|
|
162
517
|
|
|
163
|
-
|
|
164
|
-
|
|
518
|
+
// Run the peer and file both halves of its answer. Returns the payload the
|
|
519
|
+
// caller gets back; NEVER throws, so the background path can fire it
|
|
520
|
+
// un-awaited without an unhandled rejection taking the daemon with it.
|
|
521
|
+
// A --code exchange IS a coding session, so it has to live where coding
|
|
522
|
+
// sessions live. Without this it exists only as an a2a thread and the Code
|
|
523
|
+
// panel — the one place you go to see what was built — never shows it.
|
|
524
|
+
// Sender is the user turn; the peer that does the work is the assistant,
|
|
525
|
+
// which is the same shape /code writes for its own sessions.
|
|
526
|
+
const openCodeSession = () => {
|
|
527
|
+
if (mode !== "code") return null;
|
|
528
|
+
const known = readA2APeerSession(p.storagePath, { from, to, key: "code_session_id" });
|
|
529
|
+
let session = known ? getCodeSession(p.storagePath, known) : null;
|
|
530
|
+
if (!session) {
|
|
531
|
+
session = createCodeSession(p.storagePath, {
|
|
532
|
+
projectId: p.id,
|
|
533
|
+
title: `a2a: ${from} -> ${to}`,
|
|
534
|
+
mode: CODE_MODES.BUILD,
|
|
535
|
+
agentSlug: to,
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
appendCodeTurn(p.storagePath, session.id, {
|
|
539
|
+
role: "user",
|
|
540
|
+
parts: [{ kind: "text", text: body }],
|
|
541
|
+
mode: CODE_MODES.BUILD,
|
|
542
|
+
});
|
|
543
|
+
return session;
|
|
544
|
+
};
|
|
545
|
+
|
|
546
|
+
const runReply = async () => {
|
|
547
|
+
const codeSession = openCodeSession();
|
|
165
548
|
try {
|
|
166
|
-
const result = await
|
|
549
|
+
const result = await replyToPeer({
|
|
550
|
+
peer,
|
|
551
|
+
project: p,
|
|
167
552
|
projectPath: p.path,
|
|
168
|
-
toAgent,
|
|
169
553
|
fromAgent,
|
|
554
|
+
fromAddress: from,
|
|
170
555
|
body,
|
|
171
556
|
config: p.config || config,
|
|
557
|
+
history,
|
|
558
|
+
projectId: p.id,
|
|
559
|
+
projects,
|
|
560
|
+
plugins,
|
|
561
|
+
registries,
|
|
562
|
+
// A runtime peer runs where the sender is, falling back to the
|
|
563
|
+
// project. It also continues the session this thread already opened
|
|
564
|
+
// instead of starting a stranger.
|
|
565
|
+
cwd: senderCwd(req.body?.cwd) || p.path,
|
|
566
|
+
projectName: p.name,
|
|
567
|
+
resumeSessionId: readA2APeerSession(p.storagePath, { from, to }),
|
|
568
|
+
mode,
|
|
569
|
+
timeoutMs,
|
|
172
570
|
});
|
|
173
571
|
|
|
572
|
+
const replyTs = nowIso();
|
|
573
|
+
const replyMessageId = shortId("a2a");
|
|
574
|
+
if (Array.isArray(result.trace)) {
|
|
575
|
+
for (const step of result.trace) {
|
|
576
|
+
if (!step?.tool) continue;
|
|
577
|
+
p.logMessage({
|
|
578
|
+
agent_slug: to,
|
|
579
|
+
channel: "a2a",
|
|
580
|
+
direction: "out",
|
|
581
|
+
type: "tool",
|
|
582
|
+
actor_kind: "agent",
|
|
583
|
+
actor_id: step.tool,
|
|
584
|
+
author: to,
|
|
585
|
+
body: typeof step.result === "string" ? step.result : JSON.stringify(step.result || ""),
|
|
586
|
+
meta: {
|
|
587
|
+
to: from,
|
|
588
|
+
tool: step.tool,
|
|
589
|
+
args: step.args,
|
|
590
|
+
result: step.result,
|
|
591
|
+
},
|
|
592
|
+
ts: replyTs,
|
|
593
|
+
});
|
|
594
|
+
}
|
|
595
|
+
}
|
|
174
596
|
p.logMessage({
|
|
175
597
|
agent_slug: to,
|
|
176
598
|
channel: "a2a",
|
|
177
599
|
direction: "out",
|
|
600
|
+
type: "agent",
|
|
601
|
+
actor_kind: "agent",
|
|
602
|
+
actor_id: to,
|
|
178
603
|
author: to,
|
|
179
604
|
body: result.text,
|
|
180
605
|
meta: {
|
|
181
606
|
to: from,
|
|
182
607
|
depth: _depth + 1,
|
|
183
608
|
reply_to: fromAgent.slug,
|
|
609
|
+
final: true,
|
|
610
|
+
model: result.model,
|
|
184
611
|
usage: result.usage,
|
|
612
|
+
// Where this thread's external session lives, so the NEXT turn
|
|
613
|
+
// resumes it. Stored on the ledger rather than in a side table: a
|
|
614
|
+
// thread that gets deleted takes its session pointer with it.
|
|
615
|
+
...(result.runtime ? { runtime: result.runtime } : {}),
|
|
616
|
+
...(result.mode ? { mode: result.mode } : {}),
|
|
617
|
+
...(result.sessionId ? { runtime_session_id: result.sessionId } : {}),
|
|
618
|
+
...(codeSession ? { code_session_id: codeSession.id } : {}),
|
|
185
619
|
},
|
|
620
|
+
ts: replyTs,
|
|
621
|
+
external_id: replyMessageId,
|
|
186
622
|
});
|
|
623
|
+
if (codeSession) {
|
|
624
|
+
appendCodeTurn(p.storagePath, codeSession.id, {
|
|
625
|
+
role: "assistant",
|
|
626
|
+
parts: [{ kind: "text", text: result.text }],
|
|
627
|
+
mode: CODE_MODES.BUILD,
|
|
628
|
+
...(result.model ? { model: result.model } : { model: result.runtime || to }),
|
|
629
|
+
});
|
|
630
|
+
}
|
|
187
631
|
p.logMessage({
|
|
188
632
|
agent_slug: from,
|
|
189
633
|
channel: "a2a",
|
|
@@ -191,13 +635,77 @@ export function register(api, { project, config }) {
|
|
|
191
635
|
author: to,
|
|
192
636
|
body: result.text,
|
|
193
637
|
meta: { from: to, depth: _depth + 1 },
|
|
638
|
+
ts: replyTs,
|
|
639
|
+
external_id: replyMessageId,
|
|
194
640
|
});
|
|
195
|
-
|
|
641
|
+
return {
|
|
642
|
+
text: result.text,
|
|
643
|
+
usage: result.usage,
|
|
644
|
+
...(result.runtime ? { runtime: result.runtime } : {}),
|
|
645
|
+
...(result.sessionId ? { session_id: result.sessionId } : {}),
|
|
646
|
+
...(result.sessionNote ? { session_note: result.sessionNote } : {}),
|
|
647
|
+
...(codeSession ? { code_session_id: codeSession.id } : {}),
|
|
648
|
+
};
|
|
196
649
|
} catch (e) {
|
|
197
|
-
|
|
650
|
+
// A peer that did not answer is news, and in the background there is no
|
|
651
|
+
// response left to carry it — so the failure goes on the thread, marked
|
|
652
|
+
// as a failure rather than dressed up as something the peer said.
|
|
653
|
+
p.logMessage({
|
|
654
|
+
agent_slug: to,
|
|
655
|
+
channel: "a2a",
|
|
656
|
+
direction: "out",
|
|
657
|
+
// attribution-exempt: a delivery failure, not a turn — nothing was
|
|
658
|
+
// spent and no model spoke, so there is no model or usage to record.
|
|
659
|
+
type: "agent",
|
|
660
|
+
actor_kind: "agent",
|
|
661
|
+
actor_id: to,
|
|
662
|
+
author: to,
|
|
663
|
+
body: `did not answer: ${e.message}`,
|
|
664
|
+
meta: {
|
|
665
|
+
to: from,
|
|
666
|
+
depth: _depth + 1,
|
|
667
|
+
reply_to: fromAgent.slug,
|
|
668
|
+
final: true,
|
|
669
|
+
failed: true,
|
|
670
|
+
failure_reason: e.message,
|
|
671
|
+
...(codeSession ? { code_session_id: codeSession.id } : {}),
|
|
672
|
+
},
|
|
673
|
+
});
|
|
674
|
+
// The coding session must show the failure too, or it reads as a
|
|
675
|
+
// request nobody ever answered.
|
|
676
|
+
if (codeSession) {
|
|
677
|
+
appendCodeTurn(p.storagePath, codeSession.id, {
|
|
678
|
+
role: "assistant",
|
|
679
|
+
parts: [{ kind: "text", text: `did not answer: ${e.message}` }],
|
|
680
|
+
mode: CODE_MODES.BUILD,
|
|
681
|
+
model: to,
|
|
682
|
+
});
|
|
683
|
+
}
|
|
684
|
+
return { error: e.message, ...(codeSession ? { code_session_id: codeSession.id } : {}) };
|
|
198
685
|
}
|
|
686
|
+
};
|
|
687
|
+
|
|
688
|
+
// An agent that inherits still replies: replyToPeer resolves the router
|
|
689
|
+
// default for it. `deliver` is the only gate here.
|
|
690
|
+
let reply = null;
|
|
691
|
+
if (deliver && background) {
|
|
692
|
+
// Un-awaited on purpose: a coding session can run for an hour, and the
|
|
693
|
+
// sender should not hold a socket open for it. The reply lands on the
|
|
694
|
+
// thread when it lands, and every surface that reads the thread sees it.
|
|
695
|
+
runReply();
|
|
696
|
+
reply = { status: "delivering", background: true, timeout_s: Math.round(timeoutMs / 1000) };
|
|
697
|
+
} else if (deliver) {
|
|
698
|
+
reply = await runReply();
|
|
199
699
|
}
|
|
200
700
|
|
|
201
|
-
res.json({
|
|
701
|
+
res.json({
|
|
702
|
+
from, to, body, ts, reply,
|
|
703
|
+
...(sevTag ? { severity: sevTag } : {}),
|
|
704
|
+
...(ownerNotify ? {
|
|
705
|
+
owner_notified: ownerNotified,
|
|
706
|
+
...(ownerNotify.line ? { owner_notified_line: ownerNotify.line } : {}),
|
|
707
|
+
...(!ownerNotified ? { owner_notify_reason: ownerNotify.reason || (ownerNotify.skipped ? "skipped" : "not sent") } : {}),
|
|
708
|
+
} : {}),
|
|
709
|
+
});
|
|
202
710
|
}));
|
|
203
711
|
}
|