@agentprojectcontext/apx 1.80.2 → 1.89.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +9 -8
- package/skills/apc-context/SKILL.md +14 -7
- package/skills/apx/SKILL.md +62 -2
- package/skills/apx-mcp/SKILL.md +42 -15
- package/src/core/agent/a2a/peers.js +161 -0
- package/src/core/agent/a2a/reply.js +379 -27
- package/src/core/agent/abort.js +25 -0
- package/src/core/agent/agent-model.js +58 -0
- package/src/core/agent/agent-tools.js +101 -0
- package/src/core/agent/author-line.js +110 -0
- package/src/core/agent/build-agent-system.js +52 -18
- package/src/core/agent/channels/voice-context.js +17 -2
- package/src/core/agent/closing-floor.js +117 -0
- package/src/core/agent/constants.js +119 -11
- package/src/core/agent/engine-call.js +56 -0
- package/src/core/agent/group/run-group-turn.js +218 -0
- package/src/core/agent/group/turn-resolver.js +165 -0
- package/src/core/agent/judge.js +138 -11
- package/src/core/agent/loop/side-effects.js +106 -3
- package/src/core/agent/memory.js +31 -18
- package/src/core/agent/model-capabilities.js +47 -0
- package/src/core/agent/model-router.js +11 -40
- package/src/core/agent/prompt-builder.js +47 -0
- package/src/core/agent/prompts/channels/a2a.md +12 -0
- package/src/core/agent/prompts/channels/code.md +3 -1
- package/src/core/agent/prompts/channels/telegram.md +2 -0
- package/src/core/agent/prompts/channels/web_code.md +1 -1
- package/src/core/agent/prompts/channels/whatsapp.md +37 -0
- package/src/core/agent/prompts/core/agent-base.md +2 -0
- package/src/core/agent/prompts/discipline/action.md +1 -0
- package/src/core/agent/prompts/discipline/two-segment.md +2 -1
- package/src/core/agent/prompts/modes/mobility.md +36 -0
- package/src/core/agent/retry.js +42 -0
- package/src/core/agent/run-agent.js +322 -25
- package/src/core/agent/run-turn.js +253 -0
- package/src/core/agent/self-memory.js +18 -52
- package/src/core/agent/skills/agent-skills.js +118 -0
- package/src/core/agent/skills/catalog.js +1 -1
- package/src/core/agent/skills/declared.js +13 -0
- package/src/core/agent/skills/index-store.js +8 -1
- package/src/core/agent/skills/inspector.js +20 -3
- package/src/core/agent/skills/loader.js +18 -3
- package/src/core/agent/skills/media.js +121 -0
- package/src/core/agent/skills/origin.js +61 -0
- package/src/core/agent/skills/sections.js +136 -0
- package/src/core/agent/super-agent.js +54 -14
- package/src/core/agent/tools/handlers/_calendar.js +50 -0
- package/src/core/agent/tools/handlers/add-mcp.js +103 -0
- package/src/core/agent/tools/handlers/asana-create-task.js +3 -1
- package/src/core/agent/tools/handlers/attach-media.js +56 -0
- package/src/core/agent/tools/handlers/calendar-create-event.js +38 -0
- package/src/core/agent/tools/handlers/calendar-find-slot.js +39 -0
- package/src/core/agent/tools/handlers/calendar-list-events.js +39 -0
- package/src/core/agent/tools/handlers/calendar-update-event.js +35 -0
- package/src/core/agent/tools/handlers/call-agent.js +14 -6
- package/src/core/agent/tools/handlers/call-runtime.js +27 -49
- package/src/core/agent/tools/handlers/comment-task.js +78 -0
- package/src/core/agent/tools/handlers/complete-task.js +60 -0
- package/src/core/agent/tools/handlers/configure-agent.js +70 -0
- package/src/core/agent/tools/handlers/create-agent.js +68 -0
- package/src/core/agent/tools/handlers/create-task.js +41 -3
- package/src/core/agent/tools/handlers/import-agent.js +5 -5
- package/src/core/agent/tools/handlers/list-mcp-tools.js +83 -0
- package/src/core/agent/tools/handlers/list-routines.js +46 -0
- package/src/core/agent/tools/handlers/list-tasks.js +8 -1
- package/src/core/agent/tools/handlers/mark-commitment.js +57 -0
- package/src/core/agent/tools/handlers/read-skill.js +64 -0
- package/src/core/agent/tools/handlers/remember-routine.js +2 -8
- package/src/core/agent/tools/handlers/remember.js +82 -6
- package/src/core/agent/tools/handlers/remove-agent.js +42 -0
- package/src/core/agent/tools/handlers/run-routine.js +94 -0
- package/src/core/agent/tools/handlers/run-shell.js +44 -2
- package/src/core/agent/tools/handlers/send-telegram.js +41 -19
- package/src/core/agent/tools/handlers/set-agent-prompt.js +44 -0
- package/src/core/agent/tools/handlers/view-media.js +69 -0
- package/src/core/agent/tools/handlers/write-agent-memory.js +52 -0
- package/src/core/agent/tools/helpers.js +36 -4
- package/src/core/agent/tools/names.js +64 -0
- package/src/core/agent/tools/registry-bridge.js +24 -1
- package/src/core/agent/tools/registry.js +79 -0
- package/src/core/agent/tools/tool-call-parser.js +136 -13
- package/src/core/agent/vision-bridge.js +69 -0
- package/src/core/apc/agent-identity.js +74 -0
- package/src/core/apc/agent-rename-refs.js +187 -0
- package/src/core/apc/agent-write.js +312 -0
- package/src/core/apc/agents-vault.js +1 -1
- package/src/core/apc/blob-keys.js +42 -0
- package/src/core/apc/frontmatter.js +166 -10
- package/src/core/apc/parser.js +33 -83
- package/src/core/apc/paths.js +4 -6
- package/src/core/apc/project-memory.js +44 -0
- package/src/core/apc/projects-helpers.js +33 -0
- package/src/core/apc/scaffold.js +36 -16
- package/src/core/channels/telegram/ask-callbacks.js +103 -0
- package/src/core/channels/telegram/dispatch.js +154 -30
- package/src/core/channels/telegram/helpers.js +59 -7
- package/src/core/channels/telegram/inbound/audio.js +26 -30
- package/src/core/channels/telegram/inbound/file.js +22 -32
- package/src/core/channels/telegram/inbound/photo.js +24 -28
- package/src/core/channels/telegram/progress-gate.js +76 -0
- package/src/core/channels/telegram/reply.js +151 -43
- package/src/core/channels/telegram/voice-note.js +150 -0
- package/src/core/config/index.js +53 -54
- package/src/core/config/paths.js +117 -31
- package/src/core/config/redact.js +89 -4
- package/src/core/config/secret-values.js +2 -4
- package/src/core/constants/actors.js +5 -0
- package/src/core/constants/channels.js +3 -1
- package/src/core/constants/task-categories.js +73 -0
- package/src/core/constants/task-fields.js +28 -0
- package/src/core/engines/_globs.js +33 -0
- package/src/core/engines/anthropic.js +19 -1
- package/src/core/engines/catalog.js +20 -0
- package/src/core/engines/gemini.js +84 -16
- package/src/core/engines/index.js +19 -3
- package/src/core/engines/mock.js +145 -1
- package/src/core/engines/openai-compatible.js +150 -15
- package/src/core/engines/presets.js +36 -9
- package/src/core/engines/zen.js +131 -0
- package/src/core/events/bus.js +140 -0
- package/src/core/events/mascot-notify.js +156 -0
- package/src/core/http-tools/browser.js +366 -36
- package/src/core/http-tools/catalog.js +206 -22
- package/src/core/http-tools/grep.js +62 -7
- package/src/core/http-tools/registry.js +3 -1
- package/src/core/i18n/en.js +34 -3
- package/src/core/i18n/es.js +36 -4
- package/src/core/i18n/index.js +5 -5
- package/src/core/i18n/pt.js +32 -3
- package/src/core/identity/self.js +14 -1
- package/src/core/images/engines/a1111.js +219 -0
- package/src/core/images/engines/index.js +187 -0
- package/src/core/images/engines/mock.js +74 -0
- package/src/core/images/engines/openai.js +130 -0
- package/src/core/images/engines/sdcpp.js +204 -0
- package/src/core/images/engines/shared.js +218 -0
- package/src/core/images/generate.js +260 -0
- package/src/core/integrations/catalog.js +8 -3
- package/src/core/integrations/plugins/_google-oauth.js +179 -0
- package/src/core/integrations/plugins/asana.js +7 -3
- package/src/core/integrations/plugins/calendar.js +404 -0
- package/src/core/integrations/store.js +2 -0
- package/src/core/memory/broker.js +16 -1
- package/src/core/memory/compactor.js +19 -3
- package/src/core/memory/consolidate.js +2 -2
- package/src/core/memory/dated-log.js +66 -0
- package/src/core/memory/embed-engines/custom.js +59 -0
- package/src/core/memory/embed-engines/gemini.js +9 -3
- package/src/core/memory/embed-engines/index.js +87 -15
- package/src/core/memory/embeddings.js +52 -24
- package/src/core/memory/index.js +13 -3
- package/src/core/memory/indexer.js +83 -27
- package/src/core/memory/prune.js +182 -0
- package/src/core/memory/store.js +22 -0
- package/src/core/memory/summarizer.js +72 -8
- package/src/core/mobility/answer.js +80 -0
- package/src/core/mobility/geofence.js +667 -0
- package/src/core/mobility/osm-route.js +282 -0
- package/src/core/mobility/preferences.js +91 -0
- package/src/core/mobility/state.js +245 -0
- package/src/core/mobility/trip-event.js +384 -0
- package/src/core/net/tailscale.js +168 -0
- package/src/core/profiles/bundled/secretary/PROFILE.md +32 -42
- package/src/core/profiles/bundled/secretary/config.schema.es.json +68 -0
- package/src/core/profiles/bundled/secretary/config.schema.json +30 -2
- package/src/core/profiles/bundled/secretary/profile.json +3 -1
- package/src/core/profiles/bundled/secretary/routines/a2a-sweep.json +20 -0
- package/src/core/profiles/bundled/secretary/routines/day-close.json +4 -1
- package/src/core/profiles/bundled/secretary/routines/day-open.json +7 -1
- package/src/core/profiles/bundled/secretary/routines/watch.json +13 -2
- package/src/core/profiles/lifecycle.js +243 -19
- package/src/core/profiles/paths.js +12 -0
- package/src/core/profiles/store.js +47 -0
- package/src/core/routines/active-runs.js +213 -0
- package/src/core/routines/delivery.js +612 -0
- package/src/core/routines/header.js +88 -0
- package/src/core/routines/index.js +26 -0
- package/src/core/routines/run-log.js +78 -0
- package/src/core/routines/runner.js +629 -66
- package/src/core/routines/signals.js +75 -0
- package/src/core/runtime-skills/apc-context/SKILL.md +14 -7
- package/src/core/runtime-skills/apx/SKILL.md +93 -1
- package/src/core/runtime-skills/apx-agency-agents/SKILL.md +2 -2
- package/src/core/runtime-skills/apx-agent/SKILL.md +134 -19
- package/src/core/runtime-skills/apx-commitment/SKILL.md +134 -0
- package/src/core/runtime-skills/apx-image/SKILL.md +60 -0
- package/src/core/runtime-skills/apx-integrations/SKILL.md +82 -0
- package/src/core/runtime-skills/apx-mcp/SKILL.md +45 -14
- package/src/core/runtime-skills/apx-mcp-builder/SKILL.md +4 -4
- package/src/core/runtime-skills/apx-profile/SKILL.md +27 -2
- package/src/core/runtime-skills/apx-project/SKILL.md +23 -2
- package/src/core/runtime-skills/apx-routine/SKILL.md +40 -17
- package/src/core/runtime-skills/apx-runtime/SKILL.md +124 -14
- package/src/core/runtime-skills/apx-sessions/SKILL.md +7 -6
- package/src/core/runtime-skills/apx-skill-builder/SKILL.md +15 -13
- package/src/core/runtime-skills/apx-task/SKILL.md +79 -26
- package/src/core/runtime-skills/apx-telegram/SKILL.md +12 -12
- package/src/core/runtime-skills/apx-transcribe/SKILL.md +56 -0
- package/src/core/runtime-skills/apx-voice/SKILL.md +27 -8
- package/src/core/runtime-skills/claude-code/SKILL.md +8 -0
- package/src/core/runtime-skills/openrouter/SKILL.md +8 -2
- package/src/core/runtimes/_spawn.js +9 -1
- package/src/core/runtimes/claude-code.js +11 -2
- package/src/core/runtimes/codex.js +44 -10
- package/src/core/runtimes/index.js +17 -2
- package/src/core/runtimes/opencode.js +88 -9
- package/src/core/runtimes/outcome.js +119 -0
- package/src/core/sessions/index.js +193 -1
- package/src/core/stores/agent-inbox.js +109 -23
- package/src/core/stores/code-sessions.js +21 -0
- package/src/core/stores/commitments.js +27 -3
- package/src/core/stores/conversations.js +220 -20
- package/src/core/stores/deliveries.js +177 -0
- package/src/core/stores/media-archive.js +228 -0
- package/src/core/stores/messages.js +1096 -112
- package/src/core/stores/organization.js +34 -0
- package/src/core/stores/project-memory.js +71 -0
- package/src/core/stores/routine-memory.js +16 -8
- package/src/core/stores/routines.js +27 -49
- package/src/core/stores/sessions.js +4 -8
- package/src/core/stores/tasks.js +212 -18
- package/src/core/stores/turn-record.js +209 -0
- package/src/core/tasks/columns.js +136 -0
- package/src/core/tasks/comment-turn.js +258 -0
- package/src/core/util/time.js +13 -0
- package/src/core/voice/engines/index.js +54 -1
- package/src/core/voice/engines/openai.js +50 -4
- package/src/core/voice/opus.js +67 -0
- package/src/core/voice/pronounceable.js +43 -0
- package/src/core/voice/transcription.js +4 -0
- package/src/core/voice/tts.js +114 -24
- package/src/host/daemon/active-turns.js +188 -0
- package/src/host/daemon/api/admin-config.js +9 -0
- package/src/host/daemon/api/agents.js +99 -90
- package/src/host/daemon/api/artifact-preview.js +7 -6
- package/src/host/daemon/api/artifacts.js +3 -2
- package/src/host/daemon/api/code.js +55 -9
- package/src/host/daemon/api/commitments.js +11 -0
- package/src/host/daemon/api/confirm.js +3 -2
- package/src/host/daemon/api/conversations.js +543 -35
- package/src/host/daemon/api/deck.js +9 -8
- package/src/host/daemon/api/deliveries.js +33 -0
- package/src/host/daemon/api/desktop.js +5 -4
- package/src/host/daemon/api/embeddings.js +15 -6
- package/src/host/daemon/api/engines.js +59 -8
- package/src/host/daemon/api/exec.js +437 -121
- package/src/host/daemon/api/groups.js +215 -0
- package/src/host/daemon/api/images.js +107 -0
- package/src/host/daemon/api/inbox.js +123 -2
- package/src/host/daemon/api/integrations.js +64 -2
- package/src/host/daemon/api/mcps.js +7 -6
- package/src/host/daemon/api/media.js +283 -0
- package/src/host/daemon/api/mobility.js +177 -0
- package/src/host/daemon/api/net.js +182 -0
- package/src/host/daemon/api/pairing.js +38 -5
- package/src/host/daemon/api/profiles.js +30 -2
- package/src/host/daemon/api/routines.js +36 -4
- package/src/host/daemon/api/runtimes.js +74 -39
- package/src/host/daemon/api/sessions-search.js +7 -2
- package/src/host/daemon/api/sessions.js +44 -2
- package/src/host/daemon/api/shared.js +127 -20
- package/src/host/daemon/api/skills.js +11 -4
- package/src/host/daemon/api/super-agent.js +384 -53
- package/src/host/daemon/api/tasks.js +180 -10
- package/src/host/daemon/api/telegram.js +11 -10
- package/src/host/daemon/api/thread-faces.js +159 -0
- package/src/host/daemon/api/top-level.js +3 -3
- package/src/host/daemon/api/transcribe.js +11 -10
- package/src/host/daemon/api/tts.js +97 -4
- package/src/host/daemon/api/turn-abort.js +23 -0
- package/src/host/daemon/api/turns.js +49 -0
- package/src/host/daemon/api/voice.js +5 -4
- package/src/host/daemon/api/web.js +98 -0
- package/src/host/daemon/api.js +39 -0
- package/src/host/daemon/delivery-sweep.js +58 -0
- package/src/host/daemon/desktop-ws.js +5 -23
- package/src/host/daemon/events-ws.js +273 -0
- package/src/host/daemon/index.js +59 -15
- package/src/host/daemon/plugins/desktop/index.js +17 -4
- package/src/host/daemon/plugins/telegram/index.js +78 -40
- package/src/host/daemon/pty-bridge.py +99 -0
- package/src/host/daemon/routines-scheduler.js +1 -0
- package/src/host/daemon/smoke.js +1 -2
- package/src/host/daemon/terminal-ws.js +132 -0
- package/src/host/daemon/tts-keepwarm.js +87 -0
- package/src/host/daemon/wakeup.js +11 -6
- package/src/host/daemon/whisper-server.js +44 -0
- package/src/host/daemon/whisper-server.py +70 -13
- package/src/host/daemon/ws-auth.js +28 -0
- package/src/interfaces/android/app/build.gradle +42 -0
- package/src/interfaces/android/app/proguard-rules.pro +4 -0
- package/src/interfaces/android/app/src/main/AndroidManifest.xml +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AlertScreen.java +139 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/AndroidAutoDetector.java +106 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxCarAppService.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ApxPreferences.java +165 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarAlertStore.java +84 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageActionReceiver.java +47 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/CarMessageNotification.java +152 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonAddress.java +35 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DaemonClient.java +339 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/DeviceLocation.java +38 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ErrandScreen.java +127 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MainActivity.java +872 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationDetector.java +63 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsNavigationListenerService.java +453 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MapsShareIntentParser.java +93 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotBlobCatalog.java +66 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotOverlayService.java +448 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MascotView.java +249 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/MessageFrameParser.java +240 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/NotifyChannels.java +69 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityActionReceiver.java +78 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/ProximityNotification.java +161 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/StartupReceiver.java +57 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelEventGate.java +62 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TravelStatusBanner.java +116 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripLocationService.java +272 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripPlacesSheet.java +203 -0
- package/src/interfaces/android/app/src/main/java/dev/agentprojectcontext/apx/TripScreen.java +182 -0
- package/src/interfaces/android/app/src/main/res/drawable/app_background.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_app.xml +10 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_launcher_foreground.xml +12 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_apx_notification.xml +22 -0
- package/src/interfaces/android/app/src/main/res/drawable/ic_trip_car.xml +37 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/apx_logo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_amatista.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_aqua.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_brasa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_campana.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_caracol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_carbon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cobalto.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cometa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_coral.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_cubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_eclipse.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_faro.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_gajo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_iris.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_kiwi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_laguna.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_lila.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_menta.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_nimbo.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_noche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_onyx.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_orbita.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_ovni.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_papa.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_parche.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_peon.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_perla.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_pino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_quad.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_rubi.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_saturno.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trebol.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_trino.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_volcan.png +0 -0
- package/src/interfaces/android/app/src/main/res/drawable-nodpi/mascot_zafiro.png +0 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
- package/src/interfaces/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
- package/src/interfaces/android/app/src/main/res/raw/apx_notification.mp3 +0 -0
- package/src/interfaces/android/app/src/main/res/values/colors.xml +4 -0
- package/src/interfaces/android/app/src/main/res/values/strings.xml +25 -0
- package/src/interfaces/android/app/src/main/res/values/styles.xml +10 -0
- package/src/interfaces/android/app/src/main/res/values-v31/styles.xml +14 -0
- package/src/interfaces/android/app/src/main/res/xml/automotive_app_desc.xml +9 -0
- package/src/interfaces/android/app/src/main/res/xml/network_security_config.xml +10 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/AndroidAutoDetectorTest.java +85 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/CarAlertStoreTest.java +104 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/DaemonAddressTest.java +23 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsNavigationDetectorTest.java +69 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MapsShareIntentParserTest.java +31 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/MessageFrameParserTest.java +180 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TravelEventGateTest.java +64 -0
- package/src/interfaces/android/app/src/test/java/dev/agentprojectcontext/apx/TripPlacesSheetTest.java +66 -0
- package/src/interfaces/android/build.gradle +3 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/src/interfaces/android/gradle/wrapper/gradle-wrapper.properties +9 -0
- package/src/interfaces/android/gradle.properties +3 -0
- package/src/interfaces/android/gradlew +248 -0
- package/src/interfaces/android/gradlew.bat +82 -0
- package/src/interfaces/android/settings.gradle +18 -0
- package/src/interfaces/cli/commands/a2a.js +145 -4
- package/src/interfaces/cli/commands/agent.js +247 -22
- package/src/interfaces/cli/commands/code.js +1 -1
- package/src/interfaces/cli/commands/commitment.js +5 -0
- package/src/interfaces/cli/commands/config.js +85 -6
- package/src/interfaces/cli/commands/exec.js +90 -1
- package/src/interfaces/cli/commands/image.js +314 -0
- package/src/interfaces/cli/commands/mcp.js +87 -23
- package/src/interfaces/cli/commands/memory.js +35 -22
- package/src/interfaces/cli/commands/panel.js +94 -0
- package/src/interfaces/cli/commands/profile.js +14 -0
- package/src/interfaces/cli/commands/project.js +29 -0
- package/src/interfaces/cli/commands/routine.js +45 -10
- package/src/interfaces/cli/commands/runtime.js +30 -7
- package/src/interfaces/cli/commands/session.js +90 -38
- package/src/interfaces/cli/commands/sessions.js +35 -2
- package/src/interfaces/cli/commands/skills.js +15 -9
- package/src/interfaces/cli/commands/status.js +2 -3
- package/src/interfaces/cli/commands/task.js +54 -5
- package/src/interfaces/cli/commands/telegram.js +12 -4
- package/src/interfaces/cli/commands/transcribe.js +177 -0
- package/src/interfaces/cli/help/index.js +311 -72
- package/src/interfaces/cli/http.js +61 -13
- package/src/interfaces/cli/index.js +1 -1
- package/src/interfaces/cli/routes/agent.js +5 -4
- package/src/interfaces/cli/routes/commitment.js +3 -2
- package/src/interfaces/cli/routes/config.js +7 -2
- package/src/interfaces/cli/routes/image.js +11 -0
- package/src/interfaces/cli/routes/index.js +2 -0
- package/src/interfaces/cli/routes/log.js +1 -1
- package/src/interfaces/cli/routes/memory.js +3 -2
- package/src/interfaces/cli/routes/panel.js +15 -2
- package/src/interfaces/cli/routes/profile.js +3 -2
- package/src/interfaces/cli/routes/transcribe.js +10 -0
- package/src/interfaces/cli/stdin.js +29 -0
- package/src/interfaces/desktop/assets/blobs/amatista.png +0 -0
- package/src/interfaces/desktop/assets/blobs/aqua.png +0 -0
- package/src/interfaces/desktop/assets/blobs/brasa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/campana.png +0 -0
- package/src/interfaces/desktop/assets/blobs/caracol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/carbon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cobalto.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cometa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/coral.png +0 -0
- package/src/interfaces/desktop/assets/blobs/cubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/eclipse.png +0 -0
- package/src/interfaces/desktop/assets/blobs/faro.png +0 -0
- package/src/interfaces/desktop/assets/blobs/gajo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/iris.png +0 -0
- package/src/interfaces/desktop/assets/blobs/kiwi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/laguna.png +0 -0
- package/src/interfaces/desktop/assets/blobs/lila.png +0 -0
- package/src/interfaces/desktop/assets/blobs/menta.png +0 -0
- package/src/interfaces/desktop/assets/blobs/nimbo.png +0 -0
- package/src/interfaces/desktop/assets/blobs/noche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/onyx.png +0 -0
- package/src/interfaces/desktop/assets/blobs/orbita.png +0 -0
- package/src/interfaces/desktop/assets/blobs/ovni.png +0 -0
- package/src/interfaces/desktop/assets/blobs/papa.png +0 -0
- package/src/interfaces/desktop/assets/blobs/parche.png +0 -0
- package/src/interfaces/desktop/assets/blobs/peon.png +0 -0
- package/src/interfaces/desktop/assets/blobs/perla.png +0 -0
- package/src/interfaces/desktop/assets/blobs/pino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/quad.png +0 -0
- package/src/interfaces/desktop/assets/blobs/rubi.png +0 -0
- package/src/interfaces/desktop/assets/blobs/saturno.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trebol.png +0 -0
- package/src/interfaces/desktop/assets/blobs/trino.png +0 -0
- package/src/interfaces/desktop/assets/blobs/volcan.png +0 -0
- package/src/interfaces/desktop/assets/blobs/zafiro.png +0 -0
- package/src/interfaces/desktop/assets/notification.mp3 +0 -0
- package/src/interfaces/desktop/main.js +473 -29
- package/src/interfaces/desktop/mascot-blobs.js +41 -0
- package/src/interfaces/desktop/mascot-preload.js +32 -0
- package/src/interfaces/desktop/mascot.css +186 -0
- package/src/interfaces/desktop/mascot.html +40 -0
- package/src/interfaces/desktop/mascot.js +163 -0
- package/src/interfaces/desktop/preload.js +10 -0
- package/src/interfaces/desktop/renderer.js +308 -48
- package/src/interfaces/desktop/style.css +34 -0
- package/src/interfaces/mcp-server/index.js +87 -0
- package/src/interfaces/tui/_shims/util-locale.ts +0 -2
- package/src/interfaces/tui/app.tsx +0 -6
- package/src/interfaces/tui/attach.ts +0 -1
- package/src/interfaces/tui/context/sdk-apx.tsx +0 -4
- package/src/interfaces/tui/plugin/api.tsx +0 -3
- package/src/interfaces/tui/plugin/runtime.ts +0 -3
- package/src/interfaces/tui/thread.ts +0 -16
- package/src/interfaces/web/README.md +22 -14
- package/src/interfaces/web/dist/assets/claude-XtpLmGtF.webp +0 -0
- package/src/interfaces/web/dist/assets/codex-DExPUgvh.webp +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css +32 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.br +0 -0
- package/src/interfaces/web/dist/assets/index-BEoRgIqd.css.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js +1074 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.gz +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map +1 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.br +0 -0
- package/src/interfaces/web/dist/assets/index-C6fXHc1p.js.map.gz +0 -0
- package/src/interfaces/web/dist/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/dist/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/dist/index.html +22 -6
- package/src/interfaces/web/dist/index.html.br +0 -0
- package/src/interfaces/web/dist/index.html.gz +0 -0
- package/src/interfaces/web/dist/manifest.webmanifest +25 -0
- package/src/interfaces/web/dist/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/dist/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/dist/sw.js +106 -0
- package/src/interfaces/web/dist/sw.js.br +0 -0
- package/src/interfaces/web/dist/sw.js.gz +0 -0
- package/src/interfaces/web/eslint.config.js +83 -0
- package/src/interfaces/web/index.html +20 -4
- package/src/interfaces/web/package-lock.json +1651 -1280
- package/src/interfaces/web/package.json +9 -10
- package/src/interfaces/web/pnpm-lock.yaml +867 -869
- package/src/interfaces/web/public/favicon/dark/site.webmanifest +12 -6
- package/src/interfaces/web/public/favicon/white/site.webmanifest +12 -6
- package/src/interfaces/web/public/manifest.webmanifest +25 -0
- package/src/interfaces/web/public/modules/blobs/amatista.png +0 -0
- package/src/interfaces/web/public/modules/blobs/aqua.png +0 -0
- package/src/interfaces/web/public/modules/blobs/brasa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/campana.png +0 -0
- package/src/interfaces/web/public/modules/blobs/caracol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/carbon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cobalto.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cometa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/coral.png +0 -0
- package/src/interfaces/web/public/modules/blobs/cubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/eclipse.png +0 -0
- package/src/interfaces/web/public/modules/blobs/faro.png +0 -0
- package/src/interfaces/web/public/modules/blobs/gajo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/iris.png +0 -0
- package/src/interfaces/web/public/modules/blobs/kiwi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/laguna.png +0 -0
- package/src/interfaces/web/public/modules/blobs/lila.png +0 -0
- package/src/interfaces/web/public/modules/blobs/menta.png +0 -0
- package/src/interfaces/web/public/modules/blobs/nimbo.png +0 -0
- package/src/interfaces/web/public/modules/blobs/noche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/onyx.png +0 -0
- package/src/interfaces/web/public/modules/blobs/orbita.png +0 -0
- package/src/interfaces/web/public/modules/blobs/ovni.png +0 -0
- package/src/interfaces/web/public/modules/blobs/papa.png +0 -0
- package/src/interfaces/web/public/modules/blobs/parche.png +0 -0
- package/src/interfaces/web/public/modules/blobs/peon.png +0 -0
- package/src/interfaces/web/public/modules/blobs/perla.png +0 -0
- package/src/interfaces/web/public/modules/blobs/pino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/quad.png +0 -0
- package/src/interfaces/web/public/modules/blobs/rubi.png +0 -0
- package/src/interfaces/web/public/modules/blobs/saturno.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trebol.png +0 -0
- package/src/interfaces/web/public/modules/blobs/trino.png +0 -0
- package/src/interfaces/web/public/modules/blobs/volcan.png +0 -0
- package/src/interfaces/web/public/modules/blobs/zafiro.png +0 -0
- package/src/interfaces/web/public/sw.js +106 -0
- package/src/interfaces/web/src/App.tsx +106 -10
- package/src/interfaces/web/src/assets/cli/claude.webp +0 -0
- package/src/interfaces/web/src/assets/cli/codex.webp +0 -0
- package/src/interfaces/web/src/assets/cli/cursor.svg +1 -0
- package/src/interfaces/web/src/assets/cli/opencode.png +0 -0
- package/src/interfaces/web/src/components/Combobox.tsx +201 -0
- package/src/interfaces/web/src/components/MobileHint.tsx +95 -0
- package/src/interfaces/web/src/components/MobileLinkDialog.tsx +156 -0
- package/src/interfaces/web/src/components/ModelCombobox.tsx +21 -113
- package/src/interfaces/web/src/components/{routines/ReadOnlyBlock.tsx → ReadOnlyBlock.tsx} +13 -4
- package/src/interfaces/web/src/components/Roby.tsx +5 -3
- package/src/interfaces/web/src/components/RobyBubble.tsx +23 -5
- package/src/interfaces/web/src/components/RowMenu.tsx +46 -0
- package/src/interfaces/web/src/components/TimezoneSelect.tsx +4 -1
- package/src/interfaces/web/src/components/Toast.tsx +50 -14
- package/src/interfaces/web/src/components/UiSelect.tsx +12 -5
- package/src/interfaces/web/src/components/agents/AgentAvatar.tsx +171 -0
- package/src/interfaces/web/src/components/agents/AgentFormFields.tsx +42 -11
- package/src/interfaces/web/src/components/agents/AgentModelBadge.tsx +157 -0
- package/src/interfaces/web/src/components/agents/AgentModelSelect.tsx +57 -0
- package/src/interfaces/web/src/components/agents/AgentSkillsPicker.tsx +115 -0
- package/src/interfaces/web/src/components/agents/BlobAvatar.tsx +50 -0
- package/src/interfaces/web/src/components/agents/blobPresets.ts +50 -0
- package/src/interfaces/web/src/components/agents/modelCatalog.ts +66 -0
- package/src/interfaces/web/src/components/chat/ActionGroup.tsx +162 -0
- package/src/interfaces/web/src/components/chat/AskAnswersCard.tsx +4 -3
- package/src/interfaces/web/src/components/chat/AskQuestionsCard.tsx +1 -1
- package/src/interfaces/web/src/components/chat/Attachment.tsx +220 -0
- package/src/interfaces/web/src/components/chat/ChatList.tsx +226 -51
- package/src/interfaces/web/src/components/chat/ChatRowActivity.tsx +45 -0
- package/src/interfaces/web/src/components/chat/Composer.tsx +672 -23
- package/src/interfaces/web/src/components/chat/ComposerCommands.tsx +175 -0
- package/src/interfaces/web/src/components/chat/ComposerSuggest.tsx +215 -0
- package/src/interfaces/web/src/components/chat/ContextBar.tsx +133 -65
- package/src/interfaces/web/src/components/chat/InlineAskPanel.tsx +107 -47
- package/src/interfaces/web/src/components/chat/MessageBubble.tsx +460 -119
- package/src/interfaces/web/src/components/chat/MessageList.tsx +165 -18
- package/src/interfaces/web/src/components/chat/ReasoningBlock.tsx +58 -0
- package/src/interfaces/web/src/components/chat/SessionPicker.tsx +182 -0
- package/src/interfaces/web/src/components/chat/SkillTrace.tsx +183 -0
- package/src/interfaces/web/src/components/chat/ToolCall.tsx +11 -11
- package/src/interfaces/web/src/components/code/CodeContextTab.tsx +87 -53
- package/src/interfaces/web/src/components/code/CodeFileTree.tsx +11 -52
- package/src/interfaces/web/src/components/code/CodeFileViewer.tsx +5 -4
- package/src/interfaces/web/src/components/code/CodeProjectPicker.tsx +31 -7
- package/src/interfaces/web/src/components/code/CodeSessionList.tsx +32 -11
- package/src/interfaces/web/src/components/code/CodeSidePanel.tsx +33 -3
- package/src/interfaces/web/src/components/code/CodeTerminal.tsx +5 -4
- package/src/interfaces/web/src/components/code/NewCodeSessionDialog.tsx +164 -0
- package/src/interfaces/web/src/components/commitments/CommitmentDetail.tsx +162 -0
- package/src/interfaces/web/src/components/commitments/CommitmentFormDialog.tsx +158 -0
- package/src/interfaces/web/src/components/commitments/CommitmentList.tsx +194 -0
- package/src/interfaces/web/src/components/commitments/commitmentState.tsx +46 -0
- package/src/interfaces/web/src/components/common/BulkActionBar.tsx +60 -0
- package/src/interfaces/web/src/components/common/ConfirmDialog.tsx +4 -1
- package/src/interfaces/web/src/components/common/SelectCheckbox.tsx +40 -0
- package/src/interfaces/web/src/components/common/TabNav.tsx +1 -1
- package/src/interfaces/web/src/components/cron/CronPicker.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileBrowser.tsx +1 -1
- package/src/interfaces/web/src/components/files/FileTree.tsx +6 -4
- package/src/interfaces/web/src/components/files/FileViewer.tsx +9 -5
- package/src/interfaces/web/src/components/files/MarkdownPreview.tsx +45 -9
- package/src/interfaces/web/src/components/images/ImageDefaultsCard.tsx +93 -0
- package/src/interfaces/web/src/components/images/ImageProviderList.tsx +142 -0
- package/src/interfaces/web/src/components/images/ImageProviderModal.tsx +263 -0
- package/src/interfaces/web/src/components/images/ImageTestCard.tsx +142 -0
- package/src/interfaces/web/src/components/inbox/ChannelFilter.tsx +178 -0
- package/src/interfaces/web/src/components/inbox/InboxList.tsx +77 -81
- package/src/interfaces/web/src/components/inbox/InboxRowItem.tsx +140 -0
- package/src/interfaces/web/src/components/integrations/ComingSoonPlugin.tsx +2 -2
- package/src/interfaces/web/src/components/integrations/PluginConnect.tsx +208 -30
- package/src/interfaces/web/src/components/integrations/PluginToolsSection.tsx +1 -1
- package/src/interfaces/web/src/components/layout/ProjectAvatar.tsx +39 -24
- package/src/interfaces/web/src/components/layout/ProjectSidebar.tsx +253 -58
- package/src/interfaces/web/src/components/memory/MemoryBrowser.tsx +94 -47
- package/src/interfaces/web/src/components/routines/ExecutionsList.tsx +202 -90
- package/src/interfaces/web/src/components/routines/RoutineDetail.tsx +28 -6
- package/src/interfaces/web/src/components/routines/RoutineEditor.tsx +16 -5
- package/src/interfaces/web/src/components/routines/RoutineList.tsx +49 -9
- package/src/interfaces/web/src/components/routines/VarTextarea.tsx +1 -1
- package/src/interfaces/web/src/components/routines/runChat.ts +121 -0
- package/src/interfaces/web/src/components/sessions/SessionDetail.tsx +148 -0
- package/src/interfaces/web/src/components/sessions/SessionTerminal.tsx +98 -0
- package/src/interfaces/web/src/components/settings/AccessPanel.tsx +205 -0
- package/src/interfaces/web/src/components/settings/DefaultRouterCard.tsx +246 -101
- package/src/interfaces/web/src/components/settings/DesktopSettingsPanel.tsx +36 -2
- package/src/interfaces/web/src/components/settings/DevicesPanel.tsx +19 -6
- package/src/interfaces/web/src/components/settings/EmbedProviderList.tsx +274 -0
- package/src/interfaces/web/src/components/settings/EnginesPanel.tsx +26 -6
- package/src/interfaces/web/src/components/settings/MemoryPanel.tsx +118 -119
- package/src/interfaces/web/src/components/settings/NudgePanel.tsx +4 -3
- package/src/interfaces/web/src/components/settings/PairDeviceDialog.tsx +15 -4
- package/src/interfaces/web/src/components/settings/PanelPrefs.tsx +374 -0
- package/src/interfaces/web/src/components/settings/ProfilePanel.tsx +70 -2
- package/src/interfaces/web/src/components/settings/RoutingPanel.tsx +2 -1
- package/src/interfaces/web/src/components/settings/SkillsInspectorPanel.tsx +102 -43
- package/src/interfaces/web/src/components/settings/SkillsManager.tsx +76 -21
- package/src/interfaces/web/src/components/settings/SkillsSettings.tsx +10 -3
- package/src/interfaces/web/src/components/settings/SuperAgentPanel.tsx +8 -0
- package/src/interfaces/web/src/components/settings/TelegramChannelsPanel.tsx +11 -2
- package/src/interfaces/web/src/components/settings/TelegramContactsPanel.tsx +19 -8
- package/src/interfaces/web/src/components/settings/TelegramRolesPanel.tsx +12 -2
- package/src/interfaces/web/src/components/settings/WebPanel.tsx +22 -31
- package/src/interfaces/web/src/components/settings/providers/ProviderCard.tsx +15 -3
- package/src/interfaces/web/src/components/settings/providers/ProviderModal.tsx +97 -66
- package/src/interfaces/web/src/components/settings/providers/ProviderTestDialog.tsx +150 -0
- package/src/interfaces/web/src/components/settings/providers/typeStyles.ts +67 -25
- package/src/interfaces/web/src/components/settings/providers/types.ts +3 -0
- package/src/interfaces/web/src/components/tasks/TaskBoard.tsx +201 -0
- package/src/interfaces/web/src/components/tasks/TaskColumnsDialog.tsx +243 -0
- package/src/interfaces/web/src/components/tasks/TaskComments.tsx +167 -0
- package/src/interfaces/web/src/components/tasks/TaskDetail.tsx +335 -0
- package/src/interfaces/web/src/components/tasks/TaskFormDialog.tsx +406 -0
- package/src/interfaces/web/src/components/tasks/TaskList.tsx +258 -0
- package/src/interfaces/web/src/components/tasks/TaskSubtasks.tsx +126 -0
- package/src/interfaces/web/src/components/tasks/columns.ts +51 -0
- package/src/interfaces/web/src/components/tasks/taskStatus.tsx +159 -34
- package/src/interfaces/web/src/components/tasks/taskViewPrefs.ts +73 -0
- package/src/interfaces/web/src/components/tasks/useTaskColumns.ts +31 -0
- package/src/interfaces/web/src/components/ui/chat-input.tsx +136 -12
- package/src/interfaces/web/src/components/ui/context-menu.tsx +15 -198
- package/src/interfaces/web/src/components/ui/dialog.tsx +3 -2
- package/src/interfaces/web/src/components/ui/filter-chips.tsx +4 -0
- package/src/interfaces/web/src/components/ui/popover.tsx +14 -49
- package/src/interfaces/web/src/components/ui/sheet.tsx +2 -1
- package/src/interfaces/web/src/components/ui/spinner.tsx +2 -1
- package/src/interfaces/web/src/components/ui.tsx +62 -23
- package/src/interfaces/web/src/components/voice/VoiceProviderList.tsx +2 -1
- package/src/interfaces/web/src/components/voice/VoiceProviderModal.tsx +66 -8
- package/src/interfaces/web/src/components/voice/VoiceQvoxInstallCard.tsx +63 -0
- package/src/interfaces/web/src/components/voice/VoiceQvoxStatusCard.tsx +51 -0
- package/src/interfaces/web/src/components/voice/VoiceSttCard.tsx +4 -3
- package/src/interfaces/web/src/components/voice/VoiceTestCard.tsx +38 -4
- package/src/interfaces/web/src/constants/index.ts +1 -0
- package/src/interfaces/web/src/hooks/useChannelPrefs.ts +39 -0
- package/src/interfaces/web/src/hooks/useChat.ts +1092 -85
- package/src/interfaces/web/src/hooks/useChatActivity.ts +24 -0
- package/src/interfaces/web/src/hooks/useInbox.ts +26 -4
- package/src/interfaces/web/src/hooks/useLiveMessages.ts +16 -0
- package/src/interfaces/web/src/hooks/useOllamaModels.ts +79 -0
- package/src/interfaces/web/src/hooks/useRecorder.ts +198 -0
- package/src/interfaces/web/src/hooks/useTokenBootstrap.ts +23 -6
- package/src/interfaces/web/src/i18n/en.ts +832 -175
- package/src/interfaces/web/src/i18n/es.ts +841 -188
- package/src/interfaces/web/src/lib/api/agents.ts +23 -4
- package/src/interfaces/web/src/lib/api/code.ts +17 -0
- package/src/interfaces/web/src/lib/api/commitments.ts +7 -1
- package/src/interfaces/web/src/lib/api/conversations.ts +38 -11
- package/src/interfaces/web/src/lib/api/embeddings.ts +3 -0
- package/src/interfaces/web/src/lib/api/engines.ts +14 -0
- package/src/interfaces/web/src/lib/api/groups.ts +93 -0
- package/src/interfaces/web/src/lib/api/images.ts +193 -0
- package/src/interfaces/web/src/lib/api/inbox.ts +29 -5
- package/src/interfaces/web/src/lib/api/integrations.ts +9 -0
- package/src/interfaces/web/src/lib/api/media.ts +126 -0
- package/src/interfaces/web/src/lib/api/net.ts +44 -0
- package/src/interfaces/web/src/lib/api/profiles.ts +12 -0
- package/src/interfaces/web/src/lib/api/projects.ts +9 -1
- package/src/interfaces/web/src/lib/api/routines.ts +9 -1
- package/src/interfaces/web/src/lib/api/sessions.ts +18 -0
- package/src/interfaces/web/src/lib/api/skills.ts +8 -0
- package/src/interfaces/web/src/lib/api/super_agent.ts +3 -0
- package/src/interfaces/web/src/lib/api/tasks.ts +46 -6
- package/src/interfaces/web/src/lib/api/tools.ts +2 -0
- package/src/interfaces/web/src/lib/api/transcribe.ts +31 -0
- package/src/interfaces/web/src/lib/api/turns.ts +20 -0
- package/src/interfaces/web/src/lib/api/voice.ts +72 -2
- package/src/interfaces/web/src/lib/api.ts +3 -0
- package/src/interfaces/web/src/lib/channels.ts +214 -0
- package/src/interfaces/web/src/lib/chat-activity.ts +175 -0
- package/src/interfaces/web/src/lib/chat-prefs.ts +48 -0
- package/src/interfaces/web/src/lib/code-context.ts +0 -2
- package/src/interfaces/web/src/lib/http.ts +51 -17
- package/src/interfaces/web/src/lib/inbox-selection.ts +29 -0
- package/src/interfaces/web/src/lib/live.ts +252 -0
- package/src/interfaces/web/src/lib/net.ts +211 -0
- package/src/interfaces/web/src/lib/notify.ts +331 -0
- package/src/interfaces/web/src/lib/projectNav.ts +40 -0
- package/src/interfaces/web/src/lib/pwa.ts +115 -0
- package/src/interfaces/web/src/lib/qvox.ts +24 -0
- package/src/interfaces/web/src/lib/slug.ts +3 -0
- package/src/interfaces/web/src/lib/tone.ts +150 -0
- package/src/interfaces/web/src/main.tsx +15 -4
- package/src/interfaces/web/src/screens/ApxAdminScreen.tsx +33 -11
- package/src/interfaces/web/src/screens/InboxScreen.tsx +126 -71
- package/src/interfaces/web/src/screens/ProjectScreen.tsx +8 -4
- package/src/interfaces/web/src/screens/SettingsScreen.tsx +7 -4
- package/src/interfaces/web/src/screens/base/AgentDefaultsTab.tsx +30 -9
- package/src/interfaces/web/src/screens/base/CommitmentsTab.tsx +150 -168
- package/src/interfaces/web/src/screens/base/LogsTab.tsx +8 -7
- package/src/interfaces/web/src/screens/base/SessionsTab.tsx +99 -37
- package/src/interfaces/web/src/screens/base/WorkspacesTab.tsx +1 -1
- package/src/interfaces/web/src/screens/mobile/MobileChat.tsx +85 -0
- package/src/interfaces/web/src/screens/mobile/MobileChatList.tsx +244 -0
- package/src/interfaces/web/src/screens/mobile/MobileCommitments.tsx +350 -0
- package/src/interfaces/web/src/screens/mobile/MobileScreen.tsx +138 -0
- package/src/interfaces/web/src/screens/mobile/MobileTabBar.tsx +105 -0
- package/src/interfaces/web/src/screens/mobile/MobileTasks.tsx +407 -0
- package/src/interfaces/web/src/screens/mobile/NewChatSheet.tsx +313 -0
- package/src/interfaces/web/src/screens/mobile/mobileList.tsx +194 -0
- package/src/interfaces/web/src/screens/mobile/routes.ts +239 -0
- package/src/interfaces/web/src/screens/modules/CodeScreen.tsx +135 -64
- package/src/interfaces/web/src/screens/modules/DeckScreen.tsx +0 -1
- package/src/interfaces/web/src/screens/modules/ImagesScreen.tsx +172 -0
- package/src/interfaces/web/src/screens/modules/VoiceScreen.tsx +36 -4
- package/src/interfaces/web/src/screens/project/AgentBrainGraph.tsx +117 -30
- package/src/interfaces/web/src/screens/project/AgentDetailScreen.tsx +537 -92
- package/src/interfaces/web/src/screens/project/AgentsTab.tsx +344 -93
- package/src/interfaces/web/src/screens/project/ArtifactsTab.tsx +1 -1
- package/src/interfaces/web/src/screens/project/ChatTab.tsx +1160 -94
- package/src/interfaces/web/src/screens/project/IntegrationsTab.tsx +3 -2
- package/src/interfaces/web/src/screens/project/McpsTab.tsx +62 -14
- package/src/interfaces/web/src/screens/project/Overview.tsx +36 -15
- package/src/interfaces/web/src/screens/project/RoutinesTab.tsx +93 -8
- package/src/interfaces/web/src/screens/project/SkillsTab.tsx +4 -1
- package/src/interfaces/web/src/screens/project/StructureTab.tsx +5 -4
- package/src/interfaces/web/src/screens/project/TasksTab.tsx +351 -129
- package/src/interfaces/web/src/screens/project/VarsTab.tsx +17 -5
- package/src/interfaces/web/src/styles.css +106 -31
- package/src/interfaces/web/src/types/daemon.ts +246 -2
- package/src/interfaces/web/src/vite-env.d.ts +20 -0
- package/src/interfaces/tui/plugin/command-shim.ts +0 -109
- package/src/interfaces/web/components.json +0 -25
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js +0 -849
- package/src/interfaces/web/dist/assets/index-CvEoGtTf.js.map +0 -1
- package/src/interfaces/web/dist/assets/index-DzBBXFaO.css +0 -1
- package/src/interfaces/web/src/components/tasks/TaskDetailPanel.tsx +0 -142
- package/src/interfaces/web/src/components/ui/accordion.tsx +0 -72
- package/src/interfaces/web/src/components/ui/alert-dialog.tsx +0 -187
- package/src/interfaces/web/src/components/ui/alert.tsx +0 -76
- package/src/interfaces/web/src/components/ui/aspect-ratio.tsx +0 -22
- package/src/interfaces/web/src/components/ui/avatar.tsx +0 -107
- package/src/interfaces/web/src/components/ui/breadcrumb.tsx +0 -125
- package/src/interfaces/web/src/components/ui/button-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/calendar.tsx +0 -221
- package/src/interfaces/web/src/components/ui/card.tsx +0 -103
- package/src/interfaces/web/src/components/ui/carousel.tsx +0 -242
- package/src/interfaces/web/src/components/ui/chart.tsx +0 -371
- package/src/interfaces/web/src/components/ui/checkbox.tsx +0 -29
- package/src/interfaces/web/src/components/ui/collapsible.tsx +0 -19
- package/src/interfaces/web/src/components/ui/combobox.tsx +0 -295
- package/src/interfaces/web/src/components/ui/command.tsx +0 -196
- package/src/interfaces/web/src/components/ui/direction.tsx +0 -4
- package/src/interfaces/web/src/components/ui/drawer.tsx +0 -134
- package/src/interfaces/web/src/components/ui/empty.tsx +0 -104
- package/src/interfaces/web/src/components/ui/field.tsx +0 -236
- package/src/interfaces/web/src/components/ui/hover-card.tsx +0 -51
- package/src/interfaces/web/src/components/ui/input-otp.tsx +0 -85
- package/src/interfaces/web/src/components/ui/item.tsx +0 -201
- package/src/interfaces/web/src/components/ui/menubar.tsx +0 -280
- package/src/interfaces/web/src/components/ui/native-select.tsx +0 -61
- package/src/interfaces/web/src/components/ui/navigation-menu.tsx +0 -168
- package/src/interfaces/web/src/components/ui/pagination.tsx +0 -130
- package/src/interfaces/web/src/components/ui/progress.tsx +0 -83
- package/src/interfaces/web/src/components/ui/radio-group.tsx +0 -36
- package/src/interfaces/web/src/components/ui/resizable.tsx +0 -50
- package/src/interfaces/web/src/components/ui/scroll-area.tsx +0 -53
- package/src/interfaces/web/src/components/ui/sidebar.tsx +0 -726
- package/src/interfaces/web/src/components/ui/slider.tsx +0 -52
- package/src/interfaces/web/src/components/ui/sonner.tsx +0 -49
- package/src/interfaces/web/src/components/ui/table.tsx +0 -116
- package/src/interfaces/web/src/components/ui/toggle-group.tsx +0 -87
- package/src/interfaces/web/src/components/ui/toggle.tsx +0 -45
- package/src/interfaces/web/src/hooks/use-mobile.ts +0 -19
- package/src/interfaces/web/src/screens/base/GlobalTasksTab.tsx +0 -161
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
// Run one full group turn: persist the owner's line, walk the mention cascade
|
|
2
|
+
// (turn-resolver.js), and for each speaker call the SAME turn engine the 1:1
|
|
3
|
+
// chat uses (run-turn.js) — so agents run their real tools instead of narrating
|
|
4
|
+
// them — streaming tokens back tagged by speaker. Everything persists to the
|
|
5
|
+
// message ledger via the group helpers (stores/messages.js); there is no
|
|
6
|
+
// separate group store.
|
|
7
|
+
import { wasAbortedBySignal } from "#core/agent/abort.js";
|
|
8
|
+
import { resolveAgentModel } from "#core/agent/agent-model.js";
|
|
9
|
+
import { buildAgentSystem } from "#core/agent/build-agent-system.js";
|
|
10
|
+
import { groupToolIters } from "#core/agent/constants.js";
|
|
11
|
+
import { runAgentTurn } from "#core/agent/run-turn.js";
|
|
12
|
+
import { readAgents } from "#core/apc/parser.js";
|
|
13
|
+
import { CHANNELS } from "#core/constants/channels.js";
|
|
14
|
+
import {
|
|
15
|
+
appendGroupAgentMessage,
|
|
16
|
+
appendGroupOwnerMessage,
|
|
17
|
+
lastGroupOwnerMessage,
|
|
18
|
+
readProjectGroupThread,
|
|
19
|
+
} from "#core/stores/messages.js";
|
|
20
|
+
import { resolveGroupTurn } from "./turn-resolver.js";
|
|
21
|
+
|
|
22
|
+
const displayName = (a) => a.fields?.Name || a.slug;
|
|
23
|
+
|
|
24
|
+
// System addendum that turns a normal agent into a group participant. No "you
|
|
25
|
+
// have no tools" line — in a group the agent keeps its real toolset; this only
|
|
26
|
+
// frames the room and the @-mention protocol.
|
|
27
|
+
function groupSystemBlock({ me, ownerName, others }) {
|
|
28
|
+
const roster = others.length ? others.join(", ") : "(nadie más por ahora)";
|
|
29
|
+
return [
|
|
30
|
+
"## Group chat",
|
|
31
|
+
`You are in a group chat with **${ownerName}** (the owner) and these other agents: ${roster}.`,
|
|
32
|
+
"The conversation transcript is shown to you with each line prefixed by who said it.",
|
|
33
|
+
`Reply ONLY as yourself (**${me}**), in your own voice, concisely. Never write anyone else's lines, and never speak for the owner.`,
|
|
34
|
+
"**How to bring someone in:** the ONLY way another participant hears you and gets a turn is if you write their handle with an @ and their exact slug — e.g. `" + others.map((x) => x.match(/@[a-z0-9_-]+/)?.[0]).filter(Boolean).join("`, `") + "`. Writing just their NAME (without the @slug) does NOT reach them.",
|
|
35
|
+
"@-mention another agent with their exact @slug only if they actually need to reply. If you can close the turn yourself, don't cite anyone. A short acknowledgement is fine — don't pad.",
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function reasonLine({ reason, byOwner, ownerName, nameFor, me }) {
|
|
40
|
+
if (byOwner) return `${ownerName} addressed the group and it's your turn, ${me}. Reply now.`;
|
|
41
|
+
return `${nameFor(reason)} tagged you (@${me}) into the conversation. Reply now.`;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {object} args
|
|
46
|
+
* @param {object} args.p resolved project (db entry: path, storagePath, config, logMessage)
|
|
47
|
+
* @param {string} args.gid group id
|
|
48
|
+
* @param {string} args.text the owner's message body
|
|
49
|
+
* @param {string} args.ownerName display name for the owner in the transcript
|
|
50
|
+
* @param {object} args.config global config (fallback for the project's)
|
|
51
|
+
* @param {object} args.projects projects registry (for runAgentTurn tool handlers)
|
|
52
|
+
* @param {object} [args.plugins]
|
|
53
|
+
* @param {object} [args.registries]
|
|
54
|
+
* @param {string} [args.from] regenerate: slug of the speaker to resume from
|
|
55
|
+
* @param {string|null} [args.reason] regenerate: who pulled that speaker in (null = owner)
|
|
56
|
+
* @param {AbortSignal} [args.signal] the owner pressed Stop: aborts the speaker
|
|
57
|
+
* mid-run and stops the cascade behind it (see the catch in runAgent)
|
|
58
|
+
* @param {(ev:object)=>void} [args.onEvent] stream sink: owner_message/speaker_start/speaker_delta/speaker_final/speaker_aborted/done
|
|
59
|
+
* @returns {Promise<{messages: object[]}>}
|
|
60
|
+
*/
|
|
61
|
+
export async function runGroupTurn({ p, gid, text, attachments = [], media = null, rerun = false, from = null, reason = null, ownerName = "Owner", config, projects, plugins, registries, signal = null, onEvent = () => { } }) {
|
|
62
|
+
const thread = readProjectGroupThread(p.storagePath, gid);
|
|
63
|
+
if (!thread) throw new Error(`group ${gid} not found`);
|
|
64
|
+
|
|
65
|
+
// Regenerate: reuse the LAST owner turn already in the thread (the caller
|
|
66
|
+
// truncated from the target bubble onward), without appending a new owner
|
|
67
|
+
// line. If `from` is set, resume the cascade at that speaker and leave
|
|
68
|
+
// earlier replies this turn untouched.
|
|
69
|
+
let resume = null;
|
|
70
|
+
if (rerun) {
|
|
71
|
+
const seed = lastGroupOwnerMessage(p.storagePath, gid);
|
|
72
|
+
if (seed == null) throw new Error("nothing to regenerate: the group has no owner message yet");
|
|
73
|
+
text = seed;
|
|
74
|
+
if (from) {
|
|
75
|
+
resume = {
|
|
76
|
+
from,
|
|
77
|
+
reason: reason || "owner",
|
|
78
|
+
byOwner: !reason,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Resolve each participant against its home project when the room was built
|
|
84
|
+
// cross-project (inbox / mobile). Same-project rooms keep the host roster.
|
|
85
|
+
const homes = thread.homes && typeof thread.homes === "object" ? thread.homes : null;
|
|
86
|
+
const resolveHome = (slug) => {
|
|
87
|
+
const homeId = homes?.[slug];
|
|
88
|
+
if (homeId == null || homeId === "" || String(homeId) === String(p.id)) return p;
|
|
89
|
+
try {
|
|
90
|
+
const home = projects?.get?.(homeId);
|
|
91
|
+
return home?.path ? home : p;
|
|
92
|
+
} catch {
|
|
93
|
+
return p;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const bySlug = new Map(); // slug -> { agent, project }
|
|
97
|
+
for (const slug of thread.participants || []) {
|
|
98
|
+
const home = resolveHome(slug);
|
|
99
|
+
const agent = readAgents(home.path).find((a) => a.slug === slug);
|
|
100
|
+
if (agent) bySlug.set(slug, { agent, project: home });
|
|
101
|
+
}
|
|
102
|
+
const agents = [...bySlug.values()].map((x) => x.agent);
|
|
103
|
+
if (!agents.length) throw new Error("group has no resolvable agents");
|
|
104
|
+
if (from && !bySlug.has(from))
|
|
105
|
+
throw new Error(`agent ${from} is not in this group`);
|
|
106
|
+
|
|
107
|
+
const nameFor = (author) =>
|
|
108
|
+
author === "owner" ? ownerName : (bySlug.get(author) ? displayName(bySlug.get(author).agent) : author);
|
|
109
|
+
|
|
110
|
+
const participants = [
|
|
111
|
+
{ slug: "owner", name: ownerName, kind: "owner" },
|
|
112
|
+
...[...bySlug.entries()].map(([slug, { agent }]) => ({ slug, name: displayName(agent), kind: "agent" })),
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
// The owner's line first, so it's part of the transcript everyone reads.
|
|
116
|
+
// (A regenerate reuses the owner line already there — don't duplicate it.)
|
|
117
|
+
if (!rerun) {
|
|
118
|
+
appendGroupOwnerMessage(p.logMessage, gid, text, media);
|
|
119
|
+
onEvent({ type: "owner_message" });
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const cfg = p.config || config;
|
|
123
|
+
const said = [];
|
|
124
|
+
|
|
125
|
+
const runAgent = async (slug, ctx) => {
|
|
126
|
+
const hit = bySlug.get(slug);
|
|
127
|
+
if (!hit) throw new Error(`agent ${slug} is not in this group`);
|
|
128
|
+
const { agent, project: agentProject } = hit;
|
|
129
|
+
const modelId = await resolveAgentModel({ agent, config: cfg });
|
|
130
|
+
if (!modelId) throw new Error(`no model for agent ${slug}`);
|
|
131
|
+
|
|
132
|
+
const me = displayName(agent);
|
|
133
|
+
const others = participants
|
|
134
|
+
.filter((x) => x.kind === "agent" && x.slug !== slug)
|
|
135
|
+
.map((x) => `${x.name} (@${x.slug})`);
|
|
136
|
+
const system = buildAgentSystem(agentProject, agent, {
|
|
137
|
+
invocation: "engine",
|
|
138
|
+
caller: ctx.byOwner ? "user" : ctx.reason,
|
|
139
|
+
globalConfig: cfg,
|
|
140
|
+
extraParts: [groupSystemBlock({ me, ownerName, others })],
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Fresh read each time: earlier speakers this turn are already persisted, so
|
|
144
|
+
// a later cascade speaker sees what was just said. Tool rows stay out of the
|
|
145
|
+
// transcript text — they are execution noise; the answer bubble is enough.
|
|
146
|
+
const current = readProjectGroupThread(p.storagePath, gid);
|
|
147
|
+
const transcript = current.messages
|
|
148
|
+
.filter((m) => m.role === "user" || (m.role === "assistant" && m.content))
|
|
149
|
+
.map((m) => `${m.role === "user" ? ownerName : (nameFor(m.agent) || "agent")}: ${m.content}`)
|
|
150
|
+
.join("\n");
|
|
151
|
+
const directive = reasonLine({ reason: ctx.reason, byOwner: ctx.byOwner, ownerName, nameFor, me });
|
|
152
|
+
|
|
153
|
+
onEvent({ type: "speaker_start", slug, reason: ctx.byOwner ? null : ctx.reason });
|
|
154
|
+
// What this speaker has produced so far, kept alongside the stream so an
|
|
155
|
+
// interrupted reply can still be written to the room. runAgentTurn throws on
|
|
156
|
+
// abort and takes its text and trace with it.
|
|
157
|
+
const partialTrace = [];
|
|
158
|
+
let partialText = "";
|
|
159
|
+
let result;
|
|
160
|
+
try {
|
|
161
|
+
result = await runAgentTurn({
|
|
162
|
+
p: agentProject, agent, modelId, system,
|
|
163
|
+
prompt: `${transcript}\n\n---\n${directive}`,
|
|
164
|
+
previousMessages: [],
|
|
165
|
+
// The owner's image rides on this turn for every speaker answering it, so
|
|
166
|
+
// a vision model actually sees what was sent (not just the "[image
|
|
167
|
+
// attached]" marker already folded into the transcript text).
|
|
168
|
+
attachments,
|
|
169
|
+
channel: CHANNELS.WEB,
|
|
170
|
+
// NOT the web channel's budget, even though the channel above says web:
|
|
171
|
+
// that string picks the channel PROMPT, and a room fans one owner message
|
|
172
|
+
// out into up to MAX_TURNS_PER_MESSAGE of these runs. See GROUP_TOOL_ITERS.
|
|
173
|
+
maxIters: groupToolIters(cfg),
|
|
174
|
+
tools: true,
|
|
175
|
+
projects, plugins, registries, config: cfg,
|
|
176
|
+
signal,
|
|
177
|
+
onEvent: (ev) => {
|
|
178
|
+
if (ev?.type === "tool_result" && ev.trace) partialTrace.push(ev.trace);
|
|
179
|
+
onEvent(ev);
|
|
180
|
+
},
|
|
181
|
+
onToken: (chunk) => { partialText += chunk; onEvent({ type: "speaker_delta", slug, delta: chunk }); },
|
|
182
|
+
});
|
|
183
|
+
} catch (e) {
|
|
184
|
+
if (!wasAbortedBySignal(e, signal)) throw e;
|
|
185
|
+
// The owner stopped the room mid-reply. Whatever streamed is real work they
|
|
186
|
+
// watched happen, so it stays in the transcript with the tool rows that
|
|
187
|
+
// really ran — the next owner message reads this as history, exactly as the
|
|
188
|
+
// 1:1 chat does with an interrupted turn. Returning "" parses no mentions,
|
|
189
|
+
// and the resolver's own signal check stops the queue behind us.
|
|
190
|
+
const partial = partialText.trim();
|
|
191
|
+
if (partial || partialTrace.length) {
|
|
192
|
+
appendGroupAgentMessage(p.logMessage, gid, {
|
|
193
|
+
slug, body: partial,
|
|
194
|
+
reason: ctx.byOwner ? null : ctx.reason,
|
|
195
|
+
model: modelId, trace: partialTrace,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
onEvent({ type: "speaker_aborted", slug, text: partial });
|
|
199
|
+
return "";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const reply = (result.text || "").trim() || "…";
|
|
203
|
+
appendGroupAgentMessage(p.logMessage, gid, {
|
|
204
|
+
slug, body: reply,
|
|
205
|
+
reason: ctx.byOwner ? null : ctx.reason,
|
|
206
|
+
model: result.model, usage: result.usage,
|
|
207
|
+
trace: result.trace,
|
|
208
|
+
media: result.media,
|
|
209
|
+
});
|
|
210
|
+
said.push({ slug, text: reply });
|
|
211
|
+
onEvent({ type: "speaker_final", slug, model: result.model || modelId, usage: result.usage });
|
|
212
|
+
return reply;
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
await resolveGroupTurn({ text, participants, runAgent, resume, signal });
|
|
216
|
+
onEvent({ type: "done" });
|
|
217
|
+
return { messages: said };
|
|
218
|
+
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
// Group chat turn-taking (option C + cross-mentions).
|
|
2
|
+
//
|
|
3
|
+
// A group conversation is the owner plus N agents in one room. Who speaks on a
|
|
4
|
+
// given human message is decided by @mentions, and mentions CASCADE: if the
|
|
5
|
+
// owner writes "@naty …", Naty speaks; if Naty's reply names "@candela",
|
|
6
|
+
// Candela speaks next — even though the owner never addressed her. With no
|
|
7
|
+
// mention at all, the FIRST agent in the room takes the turn.
|
|
8
|
+
//
|
|
9
|
+
// This module is pure orchestration: it parses mentions and walks the cascade,
|
|
10
|
+
// delegating the actual model call to a `runAgent(slug, ctx)` callback the
|
|
11
|
+
// caller injects. That keeps the turn logic unit-testable without engines.
|
|
12
|
+
|
|
13
|
+
// Agents keep talking as long as they @-mention someone. The only loop guard
|
|
14
|
+
// is a ceiling: one human message can produce at most this many agent replies
|
|
15
|
+
// (A↔B ping-pong included). After that the cascade stops even if they still cite.
|
|
16
|
+
//
|
|
17
|
+
// Exported because it is half of the group tool budget: each of these replies is
|
|
18
|
+
// a full tool-loop run, so this number multiplies GROUP_TOOL_ITERS into what one
|
|
19
|
+
// owner message may actually cost (see agent/constants.js).
|
|
20
|
+
export const MAX_TURNS_PER_MESSAGE = 10;
|
|
21
|
+
|
|
22
|
+
// Strip diacritics + lowercase so "@Natalia", "@natalia" and "@natália" all
|
|
23
|
+
// resolve to the same participant.
|
|
24
|
+
function norm(s) {
|
|
25
|
+
return String(s || "")
|
|
26
|
+
.normalize("NFD")
|
|
27
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.trim();
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Build the set of tokens that address a participant: its slug and every word
|
|
34
|
+
* of its display name (so "@naty" matches slug `naty` and "@Natalia" matches
|
|
35
|
+
* the agent whose Name is "Natalia"). Multi-word names also match on the full
|
|
36
|
+
* name joined without spaces ("@analytics-bot", "@AnaLucia").
|
|
37
|
+
*/
|
|
38
|
+
function aliasesFor(participant) {
|
|
39
|
+
const out = new Set();
|
|
40
|
+
const add = (v) => { const n = norm(v); if (n) out.add(n); };
|
|
41
|
+
add(participant.slug);
|
|
42
|
+
if (participant.name) {
|
|
43
|
+
add(participant.name);
|
|
44
|
+
add(participant.name.replace(/\s+/g, ""));
|
|
45
|
+
for (const w of String(participant.name).split(/\s+/)) add(w);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Parse @mentions out of a message body and resolve them to participant slugs.
|
|
52
|
+
* Only AGENT participants can be addressed (mentioning the owner is a no-op —
|
|
53
|
+
* the owner speaks by typing, not by being summoned). The author never mentions
|
|
54
|
+
* themselves into another turn.
|
|
55
|
+
*
|
|
56
|
+
* @param {string} text
|
|
57
|
+
* @param {Array<{slug,name,kind}>} participants
|
|
58
|
+
* @param {string} [authorSlug] slug of who wrote `text`, excluded from the result
|
|
59
|
+
* @returns {string[]} ordered, de-duplicated slugs of mentioned agents
|
|
60
|
+
*/
|
|
61
|
+
export function parseMentions(text, participants, authorSlug) {
|
|
62
|
+
const agents = participants.filter((p) => p.kind !== "owner");
|
|
63
|
+
// Longest alias first so "@ana-lucia" wins over a bare "@ana".
|
|
64
|
+
const table = agents
|
|
65
|
+
.map((p) => ({ slug: p.slug, aliases: [...aliasesFor(p)] }))
|
|
66
|
+
.flatMap((p) => p.aliases.map((a) => ({ slug: p.slug, alias: a })))
|
|
67
|
+
.sort((a, b) => b.alias.length - a.alias.length);
|
|
68
|
+
|
|
69
|
+
const found = [];
|
|
70
|
+
const seen = new Set();
|
|
71
|
+
// @token where token is a run of letters/digits/_/- (mentions never span
|
|
72
|
+
// spaces). We scan raw matches and resolve each against the alias table.
|
|
73
|
+
const re = /@([\p{L}\p{N}_-]+)/gu;
|
|
74
|
+
let m;
|
|
75
|
+
while ((m = re.exec(text)) !== null) {
|
|
76
|
+
const token = norm(m[1]);
|
|
77
|
+
const hit = table.find((t) => t.alias === token);
|
|
78
|
+
if (!hit) continue;
|
|
79
|
+
if (hit.slug === authorSlug) continue;
|
|
80
|
+
if (seen.has(hit.slug)) continue;
|
|
81
|
+
seen.add(hit.slug);
|
|
82
|
+
found.push(hit.slug);
|
|
83
|
+
}
|
|
84
|
+
return found;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Decide who speaks first for a human message: the agents it mentions, in
|
|
89
|
+
* order; or, if it mentions nobody, the first agent in the room.
|
|
90
|
+
*
|
|
91
|
+
* @returns {string[]} slugs to seed the cascade with
|
|
92
|
+
*/
|
|
93
|
+
export function seedSpeakers(text, participants) {
|
|
94
|
+
const mentioned = parseMentions(text, participants, "owner");
|
|
95
|
+
if (mentioned.length) return mentioned;
|
|
96
|
+
const firstAgent = participants.find((p) => p.kind !== "owner");
|
|
97
|
+
return firstAgent ? [firstAgent.slug] : [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Walk a full group turn. Starting from the human message, run each seeded
|
|
102
|
+
* speaker; scan every reply for @mentions and queue those agents — even if
|
|
103
|
+
* they already spoke this turn, so a back-and-forth keeps going until nobody
|
|
104
|
+
* cites anyone (or the ceiling is hit).
|
|
105
|
+
*
|
|
106
|
+
* @param {object} args
|
|
107
|
+
* @param {string} args.text the human message body
|
|
108
|
+
* @param {Array} args.participants [{slug,name,kind}], agents in room order
|
|
109
|
+
* @param {(slug:string, ctx:{reason:string, byOwner:boolean}) => Promise<string>} args.runAgent
|
|
110
|
+
* Runs one agent's turn against the current transcript and returns its
|
|
111
|
+
* reply text. The resolver appends it before scanning for mentions.
|
|
112
|
+
* @param {(slug:string) => void} [args.onSpeakerStart] fires before each run
|
|
113
|
+
* @param {number} [args.maxTurns]
|
|
114
|
+
* @param {AbortSignal} [args.signal]
|
|
115
|
+
* The owner stopped the room. Checked between speakers so an interrupted
|
|
116
|
+
* cascade does not start the NEXT agent's turn: the speaker that was
|
|
117
|
+
* mid-run is aborted through its own run's signal, and this stops the
|
|
118
|
+
* queue behind it. Without it "stop" only ever ended one reply of ten.
|
|
119
|
+
* @param {{from:string, reason?:string, byOwner?:boolean}} [args.resume]
|
|
120
|
+
* Regenerating one bubble: start from `from` instead of re-seeding the
|
|
121
|
+
* whole room from the owner line. Earlier replies this turn stay put;
|
|
122
|
+
* a new @mention can still pull those speakers in again.
|
|
123
|
+
* @returns {Promise<Array<{slug,text}>>} the replies in the order they were said
|
|
124
|
+
*/
|
|
125
|
+
export async function resolveGroupTurn({
|
|
126
|
+
text,
|
|
127
|
+
participants,
|
|
128
|
+
runAgent,
|
|
129
|
+
onSpeakerStart,
|
|
130
|
+
maxTurns = MAX_TURNS_PER_MESSAGE,
|
|
131
|
+
resume = null,
|
|
132
|
+
signal = null,
|
|
133
|
+
}) {
|
|
134
|
+
const replies = [];
|
|
135
|
+
// Each queue entry remembers WHY the agent is speaking: addressed by the
|
|
136
|
+
// owner, or pulled in by another agent's mention. The reason is handed to
|
|
137
|
+
// runAgent so the prompt can frame it ("owner asked you" vs "naty tagged you").
|
|
138
|
+
// A regenerate of one bubble resumes from that speaker; a fresh turn seeds
|
|
139
|
+
// from the owner's @mentions (or the first agent in the room).
|
|
140
|
+
const queue = resume?.from
|
|
141
|
+
? [{ slug: resume.from, reason: resume.reason || "owner", byOwner: resume.byOwner !== false }]
|
|
142
|
+
: seedSpeakers(text, participants).map((slug) => ({ slug, reason: "owner", byOwner: true }));
|
|
143
|
+
|
|
144
|
+
while (queue.length && replies.length < maxTurns) {
|
|
145
|
+
if (signal?.aborted) break;
|
|
146
|
+
const { slug, reason, byOwner } = queue.shift();
|
|
147
|
+
const participant = participants.find((p) => p.slug === slug && p.kind !== "owner");
|
|
148
|
+
if (!participant) continue;
|
|
149
|
+
|
|
150
|
+
onSpeakerStart?.(slug);
|
|
151
|
+
const reply = await runAgent(slug, { reason, byOwner });
|
|
152
|
+
const replyText = typeof reply === "string" ? reply : "";
|
|
153
|
+
replies.push({ slug, text: replyText });
|
|
154
|
+
|
|
155
|
+
// A reply can pull anyone in, including someone who already spoke — that's
|
|
156
|
+
// how the ping-pong continues. Skip only if they're already waiting.
|
|
157
|
+
for (const mentioned of parseMentions(replyText, participants, slug)) {
|
|
158
|
+
if (queue.some((q) => q.slug === mentioned)) continue;
|
|
159
|
+
queue.push({ slug: mentioned, reason: slug, byOwner: false });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return replies;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export const __test__ = { norm, aliasesFor, MAX_TURNS_PER_MESSAGE };
|
package/src/core/agent/judge.js
CHANGED
|
@@ -1,17 +1,39 @@
|
|
|
1
1
|
// Goal-completion judge loop (OpenHands Critic / iterative-refinement
|
|
2
|
-
// pattern).
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
2
|
+
// pattern). An LLM judge scores how likely the ORIGINAL goal is actually met
|
|
3
|
+
// (0..1); below the threshold the agent gets a follow-up verification note and
|
|
4
|
+
// continues — bounded by max_iterations so a harsh judge can't spin forever.
|
|
5
|
+
//
|
|
6
|
+
// Two bounds, and only one of them is a count of rounds. `max_iterations` caps
|
|
7
|
+
// how many times we RE-ASK; the turn's tool budget caps how much the asking may
|
|
8
|
+
// cost, and the rounds share that budget with the run that came before them
|
|
9
|
+
// (applyJudgeLoop's `maxIters`). They used to be independent, which quietly made
|
|
10
|
+
// the real ceiling max_iterations × the budget — see constants.js.
|
|
11
|
+
//
|
|
12
|
+
// It serves two different failures, through the same loop:
|
|
13
|
+
//
|
|
14
|
+
// - Completion-contract turns (coding surfaces) declare "done" themselves,
|
|
15
|
+
// and the judge checks that claim. Opt-in: `judge.enabled`.
|
|
16
|
+
// - Conversational turns (Telegram, web chat) end whenever the model stops
|
|
17
|
+
// calling tools — which it also does when it merely ANNOUNCES the next step
|
|
18
|
+
// ("ahora genero el SRT en inglés") and writes no call. Nothing declared
|
|
19
|
+
// anything; the task just stopped halfway and waited to be poked. Here the
|
|
20
|
+
// judge IS the poke, and it is on by default (`judge.continue_unfinished`).
|
|
7
21
|
import { callEngine } from "../engines/index.js";
|
|
22
|
+
import { TURN_ENDING_TOOLS } from "./tools/names.js";
|
|
23
|
+
import { MIN_JUDGE_ROUND_ITERS } from "./constants.js";
|
|
8
24
|
|
|
9
25
|
export function judgeConfig(globalConfig) {
|
|
10
26
|
const raw = globalConfig?.super_agent?.judge || {};
|
|
11
27
|
const threshold = Number(raw.success_threshold);
|
|
12
28
|
const iters = parseInt(raw.max_iterations, 10);
|
|
13
29
|
return {
|
|
30
|
+
// Verify a contract turn's own "done". Opt-in — the coding surfaces pay a
|
|
31
|
+
// judge call per finish, and not every deployment wants that.
|
|
14
32
|
enabled: raw.enabled === true,
|
|
33
|
+
// Continue a conversational turn that stopped mid-task. On unless switched
|
|
34
|
+
// off: a turn that quits after announcing its next step reads as a bug, and
|
|
35
|
+
// the alternative is the user typing "seguí" to restart it by hand.
|
|
36
|
+
continue_unfinished: raw.continue_unfinished !== false,
|
|
15
37
|
success_threshold:
|
|
16
38
|
Number.isFinite(threshold) && threshold > 0 && threshold <= 1 ? threshold : 0.6,
|
|
17
39
|
max_iterations: Number.isFinite(iters) && iters > 0 ? Math.min(iters, 5) : 2,
|
|
@@ -91,10 +113,17 @@ export function parseVerdict(text) {
|
|
|
91
113
|
* Score a finished run against its goal. Returns {score, reasoning, missing}
|
|
92
114
|
* or null when the judge is unusable (engine down, unparseable reply) — the
|
|
93
115
|
* caller treats null as "accept the result", never as a failure.
|
|
116
|
+
*
|
|
117
|
+
* `fallbackModel` is the last resort for the model that does the scoring, and
|
|
118
|
+
* exists for project agents: they run on installs that never configured a
|
|
119
|
+
* super-agent, and resolving to "" there would switch the judge off silently —
|
|
120
|
+
* shipped, on by default, and doing nothing. The caller passes the model that
|
|
121
|
+
* ran the turn. The explicit knobs still win, in order: `judge.model`, then
|
|
122
|
+
* `super_agent.model`.
|
|
94
123
|
*/
|
|
95
|
-
export async function judgeCompletion({ goal, result, globalConfig, callEngineFn = callEngine }) {
|
|
124
|
+
export async function judgeCompletion({ goal, result, globalConfig, fallbackModel = "", callEngineFn = callEngine }) {
|
|
96
125
|
const cfg = judgeConfig(globalConfig);
|
|
97
|
-
const modelId = cfg.model || globalConfig?.super_agent?.model || "";
|
|
126
|
+
const modelId = cfg.model || globalConfig?.super_agent?.model || fallbackModel || "";
|
|
98
127
|
if (!modelId) return null;
|
|
99
128
|
try {
|
|
100
129
|
const r = await callEngineFn({
|
|
@@ -136,15 +165,89 @@ export function buildJudgeFollowup(verdict, iteration) {
|
|
|
136
165
|
.join("\n");
|
|
137
166
|
}
|
|
138
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Is this conversational turn one worth checking — and continuing if unfinished?
|
|
170
|
+
*
|
|
171
|
+
* Two exclusions, both about not spending a call to learn nothing:
|
|
172
|
+
* - a turn that ran no tools is chat, and chat has no half-done work; judging
|
|
173
|
+
* it would be one model call per "hola".
|
|
174
|
+
* - a turn that ended by ASKING the user is not unfinished, it is waiting. A
|
|
175
|
+
* verdict of "not complete" there would push the agent to answer its own
|
|
176
|
+
* question instead of letting the person answer it. That covers both ways a
|
|
177
|
+
* turn can ask: the ask_questions tool, and run-agent's reserved wrap-up
|
|
178
|
+
* step (`endedAwaitingUser`), whose whole job is to recap and ask "want me
|
|
179
|
+
* to keep going?" when the tool budget runs out.
|
|
180
|
+
*
|
|
181
|
+
* The wrap-up case is the one that bit us (2026-08-30, web chat): the budget
|
|
182
|
+
* ran out at 9 actions, the wrap-up asked whether to continue, the judge read
|
|
183
|
+
* "worked and then stopped" and re-ran the turn — which spent another 9 actions
|
|
184
|
+
* and hit the same wall, so the user got the same recap and the same question
|
|
185
|
+
* three times in a row, never once getting to answer it. Extending a budget the
|
|
186
|
+
* system itself set is what maxIters is for; the judge's job is to poke a turn
|
|
187
|
+
* that quit on its own.
|
|
188
|
+
*
|
|
189
|
+
* @param {{trace?: {tool?: string}[], endedAwaitingUser?: boolean}} result a runAgent result
|
|
190
|
+
*/
|
|
191
|
+
export function continuableTurn(result) {
|
|
192
|
+
const trace = Array.isArray(result?.trace) ? result.trace : [];
|
|
193
|
+
if (trace.length === 0) return false;
|
|
194
|
+
return !awaitingUser(result);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Did this turn close by putting a question to the user? Two ways it can:
|
|
199
|
+
* the ask_questions tool, or run-agent's reserved wrap-up step, which recaps
|
|
200
|
+
* and asks "want me to keep going?" when the tool budget runs out
|
|
201
|
+
* (`endedAwaitingUser`). Either way the next move belongs to a person.
|
|
202
|
+
*
|
|
203
|
+
* @param {{trace?: {tool?: string}[], endedAwaitingUser?: boolean}} result a runAgent result
|
|
204
|
+
*/
|
|
205
|
+
export function awaitingUser(result) {
|
|
206
|
+
if (result?.endedAwaitingUser) return true;
|
|
207
|
+
const trace = Array.isArray(result?.trace) ? result.trace : [];
|
|
208
|
+
return trace.some((t) => TURN_ENDING_TOOLS.has(String(t?.tool || "")));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Iterations of the tool budget a run consumed. runAgent reports it directly;
|
|
213
|
+
* an injected runner (tests, a surface with its own loop) may not, and for
|
|
214
|
+
* those we fall back to a LOWER BOUND — a tool result cannot exist without an
|
|
215
|
+
* iteration that produced it, and a round that ran at all cost at least one.
|
|
216
|
+
* Under-counting means one extra round in a synthetic case; not counting at all
|
|
217
|
+
* would mean no ceiling, which is the bug this whole file's budget arithmetic
|
|
218
|
+
* exists to close.
|
|
219
|
+
*
|
|
220
|
+
* @param {{iterations?: number, trace?: unknown[]}} result a runAgent result
|
|
221
|
+
*/
|
|
222
|
+
export function itersSpent(result) {
|
|
223
|
+
const n = Number(result?.iterations);
|
|
224
|
+
if (Number.isFinite(n) && n >= 0) return n;
|
|
225
|
+
const trace = Array.isArray(result?.trace) ? result.trace : [];
|
|
226
|
+
return Math.max(1, trace.length);
|
|
227
|
+
}
|
|
228
|
+
|
|
139
229
|
/**
|
|
140
230
|
* Refinement driver, dependency-injected so surfaces and tests supply their
|
|
141
231
|
* own judge/runner. `judgeFn(result)` → verdict|null; `runFollowup(followupPrompt,
|
|
142
|
-
* result)` → next run result. Merges usage
|
|
143
|
-
* attaches the verdict trail as `result.judge`.
|
|
232
|
+
* result, {maxIters})` → next run result. Merges usage, traces and iteration
|
|
233
|
+
* spend across rounds and attaches the verdict trail as `result.judge`.
|
|
234
|
+
*
|
|
235
|
+
* `maxIters` is the budget for the WHOLE TURN — the run that produced
|
|
236
|
+
* `initialResult` plus every round this loop adds — not a per-round allowance.
|
|
237
|
+
* Each round is handed what the rounds before it left, and once too little is
|
|
238
|
+
* left to be worth a round (MIN_JUDGE_ROUND_ITERS) the loop stops. See the
|
|
239
|
+
* "one turn, one budget" note in constants.js for why the total is shared
|
|
240
|
+
* rather than the rounds getting a budget of their own.
|
|
241
|
+
*
|
|
242
|
+
* Omit it (or pass 0) and there is no arithmetic to do: rounds run on whatever
|
|
243
|
+
* budget the runner picks, bounded only by cfg.max_iterations. That is the
|
|
244
|
+
* shape an injected runner without a tool loop wants.
|
|
144
245
|
*/
|
|
145
|
-
export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup, onEvent = null }) {
|
|
246
|
+
export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup, onEvent = null, maxIters = 0 }) {
|
|
146
247
|
let result = initialResult;
|
|
147
248
|
const trail = [];
|
|
249
|
+
const budget = Number.isFinite(Number(maxIters)) && Number(maxIters) > 0 ? Number(maxIters) : 0;
|
|
250
|
+
let spent = itersSpent(initialResult);
|
|
148
251
|
for (let i = 1; i <= cfg.max_iterations; i++) {
|
|
149
252
|
const verdict = await judgeFn(result);
|
|
150
253
|
if (verdict) {
|
|
@@ -160,7 +263,23 @@ export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup,
|
|
|
160
263
|
}
|
|
161
264
|
}
|
|
162
265
|
if (!verdict || verdict.score >= cfg.success_threshold) break;
|
|
163
|
-
|
|
266
|
+
// The verdict is worth recording even when we cannot act on it — it says
|
|
267
|
+
// the turn ended unverified, and why. Acting on it is what the budget
|
|
268
|
+
// decides. We judge first and check the budget here, rather than the other
|
|
269
|
+
// way round, because a completion-contract turn is judged FOR the verdict.
|
|
270
|
+
const remaining = budget ? budget - spent : 0;
|
|
271
|
+
if (budget && remaining < MIN_JUDGE_ROUND_ITERS) {
|
|
272
|
+
if (typeof onEvent === "function") {
|
|
273
|
+
await onEvent({ type: "judge_budget_exhausted", iteration: i, spent, budget });
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
const next = await runFollowup(
|
|
278
|
+
buildJudgeFollowup(verdict, i),
|
|
279
|
+
result,
|
|
280
|
+
budget ? { maxIters: remaining } : {},
|
|
281
|
+
);
|
|
282
|
+
spent += itersSpent(next);
|
|
164
283
|
result = {
|
|
165
284
|
...next,
|
|
166
285
|
usage: {
|
|
@@ -168,7 +287,15 @@ export async function applyJudgeLoop({ initialResult, cfg, judgeFn, runFollowup,
|
|
|
168
287
|
output_tokens: (result.usage?.output_tokens || 0) + (next.usage?.output_tokens || 0),
|
|
169
288
|
},
|
|
170
289
|
trace: [...(result.trace || []), ...(next.trace || [])],
|
|
290
|
+
// The turn's total, not this round's — same rule as usage and trace. A
|
|
291
|
+
// caller that logs "spent N of maxIters" must see one number for the turn.
|
|
292
|
+
iterations: spent,
|
|
171
293
|
};
|
|
294
|
+
// The round we just ran closed by asking the user something — it exhausted
|
|
295
|
+
// its budget and wrapped up, or it called ask_questions. Same rule as the
|
|
296
|
+
// gate that let us in here: another round would answer over their head and
|
|
297
|
+
// re-ask the identical question.
|
|
298
|
+
if (awaitingUser(result)) break;
|
|
172
299
|
}
|
|
173
300
|
return trail.length ? { ...result, judge: trail } : result;
|
|
174
301
|
}
|