@elizaos/agent 2.0.0-alpha.144 → 2.0.0-alpha.151
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/apps/app-lifeops/src/actions/inbox-digest.d.ts +2 -0
- package/apps/app-lifeops/src/actions/inbox-digest.d.ts.map +1 -0
- package/apps/app-lifeops/src/actions/inbox-digest.js +1 -0
- package/apps/app-lifeops/src/actions/inbox-respond.d.ts +2 -0
- package/apps/app-lifeops/src/actions/inbox-respond.d.ts.map +1 -0
- package/apps/app-lifeops/src/actions/inbox-respond.js +1 -0
- package/apps/app-lifeops/src/actions/inbox-triage.d.ts +2 -0
- package/apps/app-lifeops/src/actions/inbox-triage.d.ts.map +1 -0
- package/apps/app-lifeops/src/actions/inbox-triage.js +1 -0
- package/apps/app-lifeops/src/actions/inbox.d.ts +3 -0
- package/apps/app-lifeops/src/actions/inbox.d.ts.map +1 -0
- package/apps/app-lifeops/src/actions/inbox.js +856 -0
- package/apps/app-lifeops/src/actions/update-owner-profile.d.ts +3 -0
- package/apps/app-lifeops/src/actions/update-owner-profile.d.ts.map +1 -0
- package/apps/app-lifeops/src/actions/update-owner-profile.js +131 -0
- package/apps/app-lifeops/src/inbox/channel-deep-links.d.ts.map +1 -0
- package/apps/app-lifeops/src/inbox/config.d.ts.map +1 -0
- package/{packages/agent → apps/app-lifeops}/src/inbox/config.js +1 -1
- package/apps/app-lifeops/src/inbox/message-fetcher.d.ts.map +1 -0
- package/apps/app-lifeops/src/inbox/reflection.d.ts.map +1 -0
- package/apps/app-lifeops/src/inbox/repository.d.ts.map +1 -0
- package/apps/app-lifeops/src/inbox/triage-classifier.d.ts.map +1 -0
- package/apps/app-lifeops/src/inbox/types.d.ts.map +1 -0
- package/apps/app-lifeops/src/lifeops/index.d.ts +25 -0
- package/apps/app-lifeops/src/lifeops/index.d.ts.map +1 -0
- package/apps/app-lifeops/src/lifeops/index.js +24 -0
- package/apps/app-lifeops/src/lifeops/screen-context.d.ts +52 -0
- package/apps/app-lifeops/src/lifeops/screen-context.d.ts.map +1 -0
- package/apps/app-lifeops/src/lifeops/screen-context.js +332 -0
- package/apps/app-lifeops/src/plugin.d.ts +3 -0
- package/apps/app-lifeops/src/plugin.d.ts.map +1 -1
- package/apps/app-lifeops/src/plugin.js +16 -3
- package/apps/app-lifeops/src/providers/inbox-triage.d.ts +3 -0
- package/apps/app-lifeops/src/providers/inbox-triage.d.ts.map +1 -0
- package/apps/app-lifeops/src/providers/inbox-triage.js +89 -0
- package/package.json +6 -4
- package/packages/agent/src/actions/calendar.d.ts +1 -18
- package/packages/agent/src/actions/calendar.d.ts.map +1 -1
- package/packages/agent/src/actions/calendar.js +1 -3143
- package/packages/agent/src/actions/check-balance.d.ts +17 -0
- package/packages/agent/src/actions/check-balance.d.ts.map +1 -0
- package/packages/agent/src/actions/check-balance.js +167 -0
- package/packages/agent/src/actions/connector-resolver.d.ts +75 -0
- package/packages/agent/src/actions/connector-resolver.d.ts.map +1 -0
- package/packages/agent/src/actions/connector-resolver.js +245 -0
- package/packages/agent/src/actions/context-signal-lexicon.d.ts +1 -1
- package/packages/agent/src/actions/context-signal-lexicon.d.ts.map +1 -1
- package/packages/agent/src/actions/context-signal-lexicon.js +6 -0
- package/packages/agent/src/actions/eject-plugin.d.ts +3 -0
- package/packages/agent/src/actions/eject-plugin.d.ts.map +1 -0
- package/packages/agent/src/actions/eject-plugin.js +48 -0
- package/packages/agent/src/actions/execute-trade.d.ts +17 -0
- package/packages/agent/src/actions/execute-trade.d.ts.map +1 -0
- package/packages/agent/src/actions/execute-trade.js +299 -0
- package/packages/agent/src/actions/get-self-status.d.ts +13 -0
- package/packages/agent/src/actions/get-self-status.d.ts.map +1 -0
- package/packages/agent/src/actions/get-self-status.js +66 -0
- package/packages/agent/src/actions/gmail.d.ts +1 -32
- package/packages/agent/src/actions/gmail.d.ts.map +1 -1
- package/packages/agent/src/actions/gmail.js +1 -1734
- package/packages/agent/src/actions/inbox-digest.d.ts +1 -1
- package/packages/agent/src/actions/inbox-digest.d.ts.map +1 -1
- package/packages/agent/src/actions/inbox-digest.js +1 -1
- package/packages/agent/src/actions/inbox-respond.d.ts +1 -1
- package/packages/agent/src/actions/inbox-respond.d.ts.map +1 -1
- package/packages/agent/src/actions/inbox-respond.js +1 -1
- package/packages/agent/src/actions/inbox-triage.d.ts +1 -1
- package/packages/agent/src/actions/inbox-triage.d.ts.map +1 -1
- package/packages/agent/src/actions/inbox-triage.js +1 -1
- package/packages/agent/src/actions/inbox.d.ts +1 -2
- package/packages/agent/src/actions/inbox.d.ts.map +1 -1
- package/packages/agent/src/actions/inbox.js +1 -856
- package/packages/agent/src/actions/index.d.ts +13 -0
- package/packages/agent/src/actions/index.d.ts.map +1 -1
- package/packages/agent/src/actions/index.js +13 -0
- package/packages/agent/src/actions/install-plugin.d.ts +3 -0
- package/packages/agent/src/actions/install-plugin.d.ts.map +1 -0
- package/packages/agent/src/actions/install-plugin.js +65 -0
- package/packages/agent/src/actions/life-goal-extractor.d.ts +1 -68
- package/packages/agent/src/actions/life-goal-extractor.d.ts.map +1 -1
- package/packages/agent/src/actions/life-goal-extractor.js +1 -354
- package/packages/agent/src/actions/life-param-extractor.d.ts +1 -77
- package/packages/agent/src/actions/life-param-extractor.d.ts.map +1 -1
- package/packages/agent/src/actions/life-param-extractor.js +1 -423
- package/packages/agent/src/actions/life-recent-context.d.ts +1 -8
- package/packages/agent/src/actions/life-recent-context.d.ts.map +1 -1
- package/packages/agent/src/actions/life-recent-context.js +1 -84
- package/packages/agent/src/actions/life-update-extractor.d.ts +1 -26
- package/packages/agent/src/actions/life-update-extractor.d.ts.map +1 -1
- package/packages/agent/src/actions/life-update-extractor.js +1 -195
- package/packages/agent/src/actions/life.d.ts +1 -8
- package/packages/agent/src/actions/life.d.ts.map +1 -1
- package/packages/agent/src/actions/life.extractor.d.ts +1 -17
- package/packages/agent/src/actions/life.extractor.d.ts.map +1 -1
- package/packages/agent/src/actions/life.extractor.js +1 -264
- package/packages/agent/src/actions/life.js +1 -3379
- package/packages/agent/src/actions/lifeops-extraction-config.d.ts +1 -15
- package/packages/agent/src/actions/lifeops-extraction-config.d.ts.map +1 -1
- package/packages/agent/src/actions/lifeops-extraction-config.js +1 -25
- package/packages/agent/src/actions/lifeops-google-helpers.d.ts +1 -61
- package/packages/agent/src/actions/lifeops-google-helpers.d.ts.map +1 -1
- package/packages/agent/src/actions/lifeops-google-helpers.js +1 -607
- package/packages/agent/src/actions/list-ejected.d.ts +3 -0
- package/packages/agent/src/actions/list-ejected.d.ts.map +1 -0
- package/packages/agent/src/actions/list-ejected.js +35 -0
- package/packages/agent/src/actions/log-level.d.ts +3 -0
- package/packages/agent/src/actions/log-level.d.ts.map +1 -0
- package/packages/agent/src/actions/log-level.js +125 -0
- package/packages/agent/src/actions/manage-tasks.d.ts.map +1 -1
- package/packages/agent/src/actions/manage-tasks.js +51 -15
- package/packages/agent/src/actions/media.d.ts +21 -0
- package/packages/agent/src/actions/media.d.ts.map +1 -0
- package/packages/agent/src/actions/media.js +384 -0
- package/packages/agent/src/actions/read-messages.d.ts +14 -0
- package/packages/agent/src/actions/read-messages.d.ts.map +1 -0
- package/packages/agent/src/actions/read-messages.js +228 -0
- package/packages/agent/src/actions/reinject-plugin.d.ts +3 -0
- package/packages/agent/src/actions/reinject-plugin.d.ts.map +1 -0
- package/packages/agent/src/actions/reinject-plugin.js +47 -0
- package/packages/agent/src/actions/send-message.d.ts +0 -7
- package/packages/agent/src/actions/send-message.d.ts.map +1 -1
- package/packages/agent/src/actions/send-message.js +170 -49
- package/packages/agent/src/actions/sync-plugin.d.ts +3 -0
- package/packages/agent/src/actions/sync-plugin.d.ts.map +1 -0
- package/packages/agent/src/actions/sync-plugin.js +47 -0
- package/packages/agent/src/actions/timezone-normalization.d.ts +1 -2
- package/packages/agent/src/actions/timezone-normalization.d.ts.map +1 -1
- package/packages/agent/src/actions/timezone-normalization.js +1 -107
- package/packages/agent/src/actions/transfer-token.d.ts +17 -0
- package/packages/agent/src/actions/transfer-token.d.ts.map +1 -0
- package/packages/agent/src/actions/transfer-token.js +470 -0
- package/packages/agent/src/actions/update-owner-profile.d.ts +1 -2
- package/packages/agent/src/actions/update-owner-profile.d.ts.map +1 -1
- package/packages/agent/src/actions/update-owner-profile.js +1 -131
- package/packages/agent/src/actions/wallet-action-shared.d.ts +15 -0
- package/packages/agent/src/actions/wallet-action-shared.d.ts.map +1 -0
- package/packages/agent/src/actions/wallet-action-shared.js +24 -0
- package/packages/agent/src/api/agent-admin-routes.d.ts.map +1 -1
- package/packages/agent/src/api/agent-admin-routes.js +1 -1
- package/packages/agent/src/api/binance-skill-helpers.d.ts.map +1 -1
- package/packages/agent/src/api/binance-skill-helpers.js +8 -3
- package/packages/agent/src/api/chat-routes.d.ts.map +1 -1
- package/packages/agent/src/api/chat-routes.js +20 -5
- package/packages/agent/src/api/coding-agents-auth-sanitize.d.ts +1 -22
- package/packages/agent/src/api/coding-agents-auth-sanitize.d.ts.map +1 -1
- package/packages/agent/src/api/coding-agents-auth-sanitize.js +1 -39
- package/packages/agent/src/api/coding-agents-preflight-normalize.d.ts +1 -28
- package/packages/agent/src/api/coding-agents-preflight-normalize.d.ts.map +1 -1
- package/packages/agent/src/api/coding-agents-preflight-normalize.js +1 -45
- package/packages/agent/src/api/coordinator-types.d.ts +1 -46
- package/packages/agent/src/api/coordinator-types.d.ts.map +1 -1
- package/packages/agent/src/api/coordinator-types.js +1 -1
- package/packages/agent/src/api/coordinator-wiring.d.ts +1 -45
- package/packages/agent/src/api/coordinator-wiring.d.ts.map +1 -1
- package/packages/agent/src/api/coordinator-wiring.js +1 -108
- package/packages/agent/src/api/index.d.ts +1 -1
- package/packages/agent/src/api/index.d.ts.map +1 -1
- package/packages/agent/src/api/index.js +1 -1
- package/packages/agent/src/api/lifeops-browser-packaging.d.ts +1 -15
- package/packages/agent/src/api/lifeops-browser-packaging.d.ts.map +1 -1
- package/packages/agent/src/api/lifeops-browser-packaging.js +1 -305
- package/packages/agent/src/api/lifeops-routes.d.ts +1 -19
- package/packages/agent/src/api/lifeops-routes.d.ts.map +1 -1
- package/packages/agent/src/api/lifeops-routes.js +1 -1173
- package/packages/agent/src/api/server.d.ts.map +1 -1
- package/packages/agent/src/api/server.js +6 -6
- package/packages/agent/src/api/task-agent-message-routing.d.ts +1 -9
- package/packages/agent/src/api/task-agent-message-routing.d.ts.map +1 -1
- package/packages/agent/src/api/task-agent-message-routing.js +1 -62
- package/packages/agent/src/api/website-blocker-routes.d.ts +1 -6
- package/packages/agent/src/api/website-blocker-routes.d.ts.map +1 -1
- package/packages/agent/src/api/website-blocker-routes.js +1 -174
- package/packages/agent/src/config/types.agent-defaults.d.ts +1 -1
- package/packages/agent/src/config/types.agent-defaults.d.ts.map +1 -1
- package/packages/agent/src/evals/coordinator-eval-client.d.ts +1 -38
- package/packages/agent/src/evals/coordinator-eval-client.d.ts.map +1 -1
- package/packages/agent/src/evals/coordinator-eval-client.js +1 -138
- package/packages/agent/src/evals/coordinator-live-runner.d.ts +1 -56
- package/packages/agent/src/evals/coordinator-live-runner.d.ts.map +1 -1
- package/packages/agent/src/evals/coordinator-live-runner.js +1 -546
- package/packages/agent/src/evals/coordinator-preflight.d.ts +1 -31
- package/packages/agent/src/evals/coordinator-preflight.d.ts.map +1 -1
- package/packages/agent/src/evals/coordinator-preflight.js +1 -296
- package/packages/agent/src/evals/coordinator-scenarios.d.ts +1 -23
- package/packages/agent/src/evals/coordinator-scenarios.d.ts.map +1 -1
- package/packages/agent/src/evals/coordinator-scenarios.js +1 -1141
- package/packages/agent/src/lifeops/app-state.d.ts +1 -10
- package/packages/agent/src/lifeops/app-state.d.ts.map +1 -1
- package/packages/agent/src/lifeops/app-state.js +1 -32
- package/packages/agent/src/lifeops/apple-reminders.d.ts +1 -57
- package/packages/agent/src/lifeops/apple-reminders.d.ts.map +1 -1
- package/packages/agent/src/lifeops/apple-reminders.js +1 -325
- package/packages/agent/src/lifeops/defaults.d.ts +1 -23
- package/packages/agent/src/lifeops/defaults.d.ts.map +1 -1
- package/packages/agent/src/lifeops/defaults.js +1 -205
- package/packages/agent/src/lifeops/engine.d.ts +1 -7
- package/packages/agent/src/lifeops/engine.d.ts.map +1 -1
- package/packages/agent/src/lifeops/engine.js +1 -389
- package/packages/agent/src/lifeops/goal-grounding.d.ts +1 -53
- package/packages/agent/src/lifeops/goal-grounding.d.ts.map +1 -1
- package/packages/agent/src/lifeops/goal-grounding.js +1 -147
- package/packages/agent/src/lifeops/goal-semantic-evaluator.d.ts +1 -11
- package/packages/agent/src/lifeops/goal-semantic-evaluator.d.ts.map +1 -1
- package/packages/agent/src/lifeops/goal-semantic-evaluator.js +1 -154
- package/packages/agent/src/lifeops/google-api-error.d.ts +1 -6
- package/packages/agent/src/lifeops/google-api-error.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-api-error.js +1 -35
- package/packages/agent/src/lifeops/google-calendar.d.ts +1 -52
- package/packages/agent/src/lifeops/google-calendar.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-calendar.js +1 -268
- package/packages/agent/src/lifeops/google-connector-gateway.d.ts +1 -18
- package/packages/agent/src/lifeops/google-connector-gateway.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-connector-gateway.js +1 -65
- package/packages/agent/src/lifeops/google-fetch.d.ts +1 -10
- package/packages/agent/src/lifeops/google-fetch.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-fetch.js +1 -85
- package/packages/agent/src/lifeops/google-gmail.d.ts +1 -53
- package/packages/agent/src/lifeops/google-gmail.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-gmail.js +1 -471
- package/packages/agent/src/lifeops/google-managed-client.d.ts +1 -126
- package/packages/agent/src/lifeops/google-managed-client.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-managed-client.js +1 -294
- package/packages/agent/src/lifeops/google-oauth.d.ts +1 -60
- package/packages/agent/src/lifeops/google-oauth.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-oauth.js +1 -494
- package/packages/agent/src/lifeops/google-scopes.d.ts +1 -12
- package/packages/agent/src/lifeops/google-scopes.d.ts.map +1 -1
- package/packages/agent/src/lifeops/google-scopes.js +1 -96
- package/packages/agent/src/lifeops/index.d.ts +1 -2
- package/packages/agent/src/lifeops/index.d.ts.map +1 -1
- package/packages/agent/src/lifeops/index.js +1 -2
- package/packages/agent/src/lifeops/owner-profile.d.ts +1 -14
- package/packages/agent/src/lifeops/owner-profile.d.ts.map +1 -1
- package/packages/agent/src/lifeops/owner-profile.js +1 -194
- package/packages/agent/src/lifeops/repository.d.ts +1 -208
- package/packages/agent/src/lifeops/repository.d.ts.map +1 -1
- package/packages/agent/src/lifeops/repository.js +1 -3187
- package/packages/agent/src/lifeops/runtime.d.ts +1 -13
- package/packages/agent/src/lifeops/runtime.d.ts.map +1 -1
- package/packages/agent/src/lifeops/runtime.js +1 -120
- package/packages/agent/src/lifeops/screen-context.d.ts +1 -51
- package/packages/agent/src/lifeops/screen-context.d.ts.map +1 -1
- package/packages/agent/src/lifeops/screen-context.js +1 -332
- package/packages/agent/src/lifeops/seed-routines.d.ts +1 -19
- package/packages/agent/src/lifeops/seed-routines.d.ts.map +1 -1
- package/packages/agent/src/lifeops/seed-routines.js +1 -111
- package/packages/agent/src/lifeops/service.d.ts +1 -274
- package/packages/agent/src/lifeops/service.d.ts.map +1 -1
- package/packages/agent/src/lifeops/service.js +1 -9260
- package/packages/agent/src/lifeops/sql.d.ts +1 -30
- package/packages/agent/src/lifeops/sql.d.ts.map +1 -1
- package/packages/agent/src/lifeops/sql.js +1 -247
- package/packages/agent/src/lifeops/time.d.ts +1 -16
- package/packages/agent/src/lifeops/time.d.ts.map +1 -1
- package/packages/agent/src/lifeops/time.js +1 -132
- package/packages/agent/src/lifeops/twilio.d.ts +1 -24
- package/packages/agent/src/lifeops/twilio.d.ts.map +1 -1
- package/packages/agent/src/lifeops/twilio.js +1 -157
- package/packages/agent/src/lifeops/x-poster.d.ts +1 -18
- package/packages/agent/src/lifeops/x-poster.d.ts.map +1 -1
- package/packages/agent/src/lifeops/x-poster.js +1 -148
- package/packages/agent/src/providers/inbox-triage.d.ts +1 -2
- package/packages/agent/src/providers/inbox-triage.d.ts.map +1 -1
- package/packages/agent/src/providers/inbox-triage.js +1 -89
- package/packages/agent/src/providers/index.d.ts +4 -1
- package/packages/agent/src/providers/index.d.ts.map +1 -1
- package/packages/agent/src/providers/index.js +4 -1
- package/packages/agent/src/providers/lifeops.d.ts +1 -2
- package/packages/agent/src/providers/lifeops.d.ts.map +1 -1
- package/packages/agent/src/providers/lifeops.js +1 -157
- package/packages/agent/src/providers/local-models.d.ts +118 -0
- package/packages/agent/src/providers/local-models.d.ts.map +1 -0
- package/packages/agent/src/providers/local-models.js +427 -0
- package/packages/agent/src/providers/media-provider.d.ts +192 -0
- package/packages/agent/src/providers/media-provider.d.ts.map +1 -0
- package/packages/agent/src/providers/media-provider.js +1088 -0
- package/packages/agent/src/providers/self-status.d.ts +4 -0
- package/packages/agent/src/providers/self-status.d.ts.map +1 -0
- package/packages/agent/src/providers/self-status.js +12 -0
- package/packages/agent/src/providers/tasks.d.ts.map +1 -1
- package/packages/agent/src/providers/tasks.js +7 -7
- package/packages/agent/src/runtime/core-plugins.js +1 -1
- package/packages/agent/src/runtime/eliza-plugin.d.ts.map +1 -1
- package/packages/agent/src/runtime/eliza-plugin.js +1 -7
- package/packages/agent/src/runtime/eliza.js +2 -2
- package/packages/agent/src/runtime/plugin-collector.js +3 -3
- package/packages/agent/src/runtime/plugin-lifecycle.d.ts.map +1 -1
- package/packages/agent/src/runtime/plugin-lifecycle.js +3 -13
- package/packages/agent/src/runtime/trajectory-internals.d.ts.map +1 -1
- package/packages/agent/src/runtime/trajectory-internals.js +1 -3
- package/packages/agent/src/services/built-in-app-routes/hyperscape.d.ts.map +1 -1
- package/packages/agent/src/services/coding-task-executor.d.ts +3 -3
- package/packages/agent/src/services/coding-task-executor.js +3 -3
- package/packages/shared/src/awareness/index.d.ts +2 -0
- package/packages/shared/src/awareness/index.d.ts.map +1 -0
- package/packages/shared/src/awareness/index.js +1 -0
- package/packages/shared/src/awareness/registry.d.ts +27 -0
- package/packages/shared/src/awareness/registry.d.ts.map +1 -0
- package/packages/shared/src/awareness/registry.js +161 -0
- package/packages/shared/src/i18n/generated/validation-keyword-data.d.ts +24 -0
- package/packages/shared/src/i18n/generated/validation-keyword-data.d.ts.map +1 -1
- package/packages/shared/src/i18n/generated/validation-keyword-data.js +24 -0
- package/packages/shared/src/runtime-env.d.ts.map +1 -1
- package/packages/shared/src/runtime-env.js +5 -1
- package/packages/typescript/src/generated/action-docs.d.ts +135 -0
- package/packages/typescript/src/generated/action-docs.d.ts.map +1 -1
- package/packages/typescript/src/generated/action-docs.js +237 -0
- package/packages/typescript/src/i18n/generated/validation-keyword-data.d.ts +24 -0
- package/packages/typescript/src/i18n/generated/validation-keyword-data.d.ts.map +1 -1
- package/packages/typescript/src/i18n/generated/validation-keyword-data.js +24 -0
- package/packages/typescript/src/index.node.d.ts +2 -2
- package/packages/typescript/src/index.node.d.ts.map +1 -1
- package/packages/typescript/src/index.node.js +4 -3
- package/packages/typescript/src/plugin-lifecycle.d.ts.map +1 -1
- package/packages/typescript/src/plugin-lifecycle.js +42 -3
- package/packages/typescript/src/services/message.d.ts.map +1 -1
- package/packages/typescript/src/services/message.js +32 -0
- package/apps/app-training/src/core/cli.d.ts +0 -11
- package/apps/app-training/src/core/cli.d.ts.map +0 -1
- package/apps/app-training/src/core/cli.js +0 -302
- package/apps/app-training/src/core/context-audit.d.ts +0 -51
- package/apps/app-training/src/core/context-audit.d.ts.map +0 -1
- package/apps/app-training/src/core/context-audit.js +0 -141
- package/apps/app-training/src/core/context-catalog.d.ts +0 -47
- package/apps/app-training/src/core/context-catalog.d.ts.map +0 -1
- package/apps/app-training/src/core/context-catalog.js +0 -259
- package/apps/app-training/src/core/context-types.d.ts +0 -3
- package/apps/app-training/src/core/context-types.d.ts.map +0 -1
- package/apps/app-training/src/core/context-types.js +0 -11
- package/apps/app-training/src/core/dataset-generator.d.ts +0 -135
- package/apps/app-training/src/core/dataset-generator.d.ts.map +0 -1
- package/apps/app-training/src/core/dataset-generator.js +0 -703
- package/apps/app-training/src/core/replay-validator.d.ts +0 -96
- package/apps/app-training/src/core/replay-validator.d.ts.map +0 -1
- package/apps/app-training/src/core/replay-validator.js +0 -265
- package/apps/app-training/src/core/roleplay-executor.d.ts +0 -123
- package/apps/app-training/src/core/roleplay-executor.d.ts.map +0 -1
- package/apps/app-training/src/core/roleplay-executor.js +0 -645
- package/apps/app-training/src/core/roleplay-trajectories.d.ts +0 -54
- package/apps/app-training/src/core/roleplay-trajectories.d.ts.map +0 -1
- package/apps/app-training/src/core/roleplay-trajectories.js +0 -73
- package/apps/app-training/src/core/scenario-blueprints.d.ts +0 -62
- package/apps/app-training/src/core/scenario-blueprints.d.ts.map +0 -1
- package/apps/app-training/src/core/scenario-blueprints.js +0 -790
- package/apps/app-training/src/core/trajectory-task-datasets.d.ts +0 -38
- package/apps/app-training/src/core/trajectory-task-datasets.d.ts.map +0 -1
- package/apps/app-training/src/core/trajectory-task-datasets.js +0 -281
- package/apps/app-training/src/core/vertex-tuning.d.ts +0 -139
- package/apps/app-training/src/core/vertex-tuning.d.ts.map +0 -1
- package/apps/app-training/src/core/vertex-tuning.js +0 -234
- package/packages/agent/src/inbox/channel-deep-links.d.ts.map +0 -1
- package/packages/agent/src/inbox/config.d.ts.map +0 -1
- package/packages/agent/src/inbox/message-fetcher.d.ts.map +0 -1
- package/packages/agent/src/inbox/reflection.d.ts.map +0 -1
- package/packages/agent/src/inbox/repository.d.ts.map +0 -1
- package/packages/agent/src/inbox/triage-classifier.d.ts.map +0 -1
- package/packages/agent/src/inbox/types.d.ts.map +0 -1
- package/packages/agent/src/training/cli.d.ts +0 -2
- package/packages/agent/src/training/cli.d.ts.map +0 -1
- package/packages/agent/src/training/cli.js +0 -2
- package/packages/agent/src/training/context-audit.d.ts +0 -2
- package/packages/agent/src/training/context-audit.d.ts.map +0 -1
- package/packages/agent/src/training/context-audit.js +0 -2
- package/packages/agent/src/training/context-catalog.d.ts +0 -2
- package/packages/agent/src/training/context-catalog.d.ts.map +0 -1
- package/packages/agent/src/training/context-catalog.js +0 -2
- package/packages/agent/src/training/context-types.d.ts +0 -2
- package/packages/agent/src/training/context-types.d.ts.map +0 -1
- package/packages/agent/src/training/context-types.js +0 -2
- package/packages/agent/src/training/dataset-generator.d.ts +0 -2
- package/packages/agent/src/training/dataset-generator.d.ts.map +0 -1
- package/packages/agent/src/training/dataset-generator.js +0 -2
- package/packages/agent/src/training/replay-validator.d.ts +0 -2
- package/packages/agent/src/training/replay-validator.d.ts.map +0 -1
- package/packages/agent/src/training/replay-validator.js +0 -2
- package/packages/agent/src/training/roleplay-executor.d.ts +0 -2
- package/packages/agent/src/training/roleplay-executor.d.ts.map +0 -1
- package/packages/agent/src/training/roleplay-executor.js +0 -2
- package/packages/agent/src/training/roleplay-trajectories.d.ts +0 -2
- package/packages/agent/src/training/roleplay-trajectories.d.ts.map +0 -1
- package/packages/agent/src/training/roleplay-trajectories.js +0 -2
- package/packages/agent/src/training/scenario-blueprints.d.ts +0 -2
- package/packages/agent/src/training/scenario-blueprints.d.ts.map +0 -1
- package/packages/agent/src/training/scenario-blueprints.js +0 -2
- package/packages/agent/src/training/trajectory-task-datasets.d.ts +0 -2
- package/packages/agent/src/training/trajectory-task-datasets.d.ts.map +0 -1
- package/packages/agent/src/training/trajectory-task-datasets.js +0 -2
- package/packages/agent/src/training/vertex-tuning.d.ts +0 -2
- package/packages/agent/src/training/vertex-tuning.d.ts.map +0 -1
- package/packages/agent/src/training/vertex-tuning.js +0 -2
- package/packages/typescript/src/features/orchestrator/actions/coding-task-handlers.d.ts +0 -41
- package/packages/typescript/src/features/orchestrator/actions/coding-task-handlers.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/coding-task-handlers.js +0 -443
- package/packages/typescript/src/features/orchestrator/actions/coding-task-helpers.d.ts +0 -34
- package/packages/typescript/src/features/orchestrator/actions/coding-task-helpers.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/coding-task-helpers.js +0 -171
- package/packages/typescript/src/features/orchestrator/actions/eval-metadata.d.ts +0 -11
- package/packages/typescript/src/features/orchestrator/actions/eval-metadata.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/eval-metadata.js +0 -55
- package/packages/typescript/src/features/orchestrator/actions/finalize-workspace.d.ts +0 -11
- package/packages/typescript/src/features/orchestrator/actions/finalize-workspace.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/finalize-workspace.js +0 -214
- package/packages/typescript/src/features/orchestrator/actions/list-agents.d.ts +0 -13
- package/packages/typescript/src/features/orchestrator/actions/list-agents.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/list-agents.js +0 -174
- package/packages/typescript/src/features/orchestrator/actions/manage-issues.d.ts +0 -11
- package/packages/typescript/src/features/orchestrator/actions/manage-issues.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/manage-issues.js +0 -428
- package/packages/typescript/src/features/orchestrator/actions/provision-workspace.d.ts +0 -11
- package/packages/typescript/src/features/orchestrator/actions/provision-workspace.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/provision-workspace.js +0 -189
- package/packages/typescript/src/features/orchestrator/actions/send-to-agent.d.ts +0 -12
- package/packages/typescript/src/features/orchestrator/actions/send-to-agent.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/send-to-agent.js +0 -265
- package/packages/typescript/src/features/orchestrator/actions/spawn-agent.d.ts +0 -12
- package/packages/typescript/src/features/orchestrator/actions/spawn-agent.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/spawn-agent.js +0 -356
- package/packages/typescript/src/features/orchestrator/actions/start-coding-task.d.ts +0 -22
- package/packages/typescript/src/features/orchestrator/actions/start-coding-task.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/start-coding-task.js +0 -270
- package/packages/typescript/src/features/orchestrator/actions/stop-agent.d.ts +0 -12
- package/packages/typescript/src/features/orchestrator/actions/stop-agent.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/stop-agent.js +0 -192
- package/packages/typescript/src/features/orchestrator/actions/task-control.d.ts +0 -3
- package/packages/typescript/src/features/orchestrator/actions/task-control.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/task-control.js +0 -217
- package/packages/typescript/src/features/orchestrator/actions/task-history.d.ts +0 -3
- package/packages/typescript/src/features/orchestrator/actions/task-history.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/task-history.js +0 -323
- package/packages/typescript/src/features/orchestrator/actions/task-share.d.ts +0 -3
- package/packages/typescript/src/features/orchestrator/actions/task-share.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/task-share.js +0 -168
- package/packages/typescript/src/features/orchestrator/actions/task-thread-target.d.ts +0 -11
- package/packages/typescript/src/features/orchestrator/actions/task-thread-target.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/actions/task-thread-target.js +0 -68
- package/packages/typescript/src/features/orchestrator/api/agent-routes.d.ts +0 -18
- package/packages/typescript/src/features/orchestrator/api/agent-routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/agent-routes.js +0 -654
- package/packages/typescript/src/features/orchestrator/api/coordinator-routes.d.ts +0 -22
- package/packages/typescript/src/features/orchestrator/api/coordinator-routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/coordinator-routes.js +0 -403
- package/packages/typescript/src/features/orchestrator/api/hook-routes.d.ts +0 -18
- package/packages/typescript/src/features/orchestrator/api/hook-routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/hook-routes.js +0 -164
- package/packages/typescript/src/features/orchestrator/api/issue-routes.d.ts +0 -17
- package/packages/typescript/src/features/orchestrator/api/issue-routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/issue-routes.js +0 -132
- package/packages/typescript/src/features/orchestrator/api/routes.d.ts +0 -37
- package/packages/typescript/src/features/orchestrator/api/routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/routes.js +0 -96
- package/packages/typescript/src/features/orchestrator/api/workspace-routes.d.ts +0 -17
- package/packages/typescript/src/features/orchestrator/api/workspace-routes.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/api/workspace-routes.js +0 -149
- package/packages/typescript/src/features/orchestrator/base-plugin.d.ts +0 -19
- package/packages/typescript/src/features/orchestrator/base-plugin.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/base-plugin.js +0 -75
- package/packages/typescript/src/features/orchestrator/claude-jsonl-completion-watcher.d.ts +0 -101
- package/packages/typescript/src/features/orchestrator/claude-jsonl-completion-watcher.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/claude-jsonl-completion-watcher.js +0 -310
- package/packages/typescript/src/features/orchestrator/index.d.ts +0 -33
- package/packages/typescript/src/features/orchestrator/index.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/index.js +0 -30
- package/packages/typescript/src/features/orchestrator/patch-agent-orchestrator-plugin.d.ts +0 -15
- package/packages/typescript/src/features/orchestrator/patch-agent-orchestrator-plugin.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/patch-agent-orchestrator-plugin.js +0 -1449
- package/packages/typescript/src/features/orchestrator/providers/action-examples.d.ts +0 -14
- package/packages/typescript/src/features/orchestrator/providers/action-examples.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/providers/action-examples.js +0 -151
- package/packages/typescript/src/features/orchestrator/providers/active-workspace-context.d.ts +0 -13
- package/packages/typescript/src/features/orchestrator/providers/active-workspace-context.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/providers/active-workspace-context.js +0 -142
- package/packages/typescript/src/features/orchestrator/services/agent-credentials.d.ts +0 -6
- package/packages/typescript/src/features/orchestrator/services/agent-credentials.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/agent-credentials.js +0 -91
- package/packages/typescript/src/features/orchestrator/services/agent-metrics.d.ts +0 -30
- package/packages/typescript/src/features/orchestrator/services/agent-metrics.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/agent-metrics.js +0 -54
- package/packages/typescript/src/features/orchestrator/services/agent-selection.d.ts +0 -53
- package/packages/typescript/src/features/orchestrator/services/agent-selection.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/agent-selection.js +0 -70
- package/packages/typescript/src/features/orchestrator/services/ansi-utils.d.ts +0 -61
- package/packages/typescript/src/features/orchestrator/services/ansi-utils.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/ansi-utils.js +0 -252
- package/packages/typescript/src/features/orchestrator/services/config-env.d.ts +0 -13
- package/packages/typescript/src/features/orchestrator/services/config-env.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/config-env.js +0 -37
- package/packages/typescript/src/features/orchestrator/services/coordinator-event-normalizer.d.ts +0 -50
- package/packages/typescript/src/features/orchestrator/services/coordinator-event-normalizer.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/coordinator-event-normalizer.js +0 -184
- package/packages/typescript/src/features/orchestrator/services/debug-capture.d.ts +0 -38
- package/packages/typescript/src/features/orchestrator/services/debug-capture.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/debug-capture.js +0 -113
- package/packages/typescript/src/features/orchestrator/services/pty-auto-response.d.ts +0 -30
- package/packages/typescript/src/features/orchestrator/services/pty-auto-response.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-auto-response.js +0 -146
- package/packages/typescript/src/features/orchestrator/services/pty-init.d.ts +0 -54
- package/packages/typescript/src/features/orchestrator/services/pty-init.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-init.js +0 -315
- package/packages/typescript/src/features/orchestrator/services/pty-service.d.ts +0 -175
- package/packages/typescript/src/features/orchestrator/services/pty-service.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-service.js +0 -1469
- package/packages/typescript/src/features/orchestrator/services/pty-session-io.d.ts +0 -49
- package/packages/typescript/src/features/orchestrator/services/pty-session-io.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-session-io.js +0 -180
- package/packages/typescript/src/features/orchestrator/services/pty-spawn.d.ts +0 -53
- package/packages/typescript/src/features/orchestrator/services/pty-spawn.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-spawn.js +0 -280
- package/packages/typescript/src/features/orchestrator/services/pty-types.d.ts +0 -80
- package/packages/typescript/src/features/orchestrator/services/pty-types.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/pty-types.js +0 -51
- package/packages/typescript/src/features/orchestrator/services/repo-input.d.ts +0 -16
- package/packages/typescript/src/features/orchestrator/services/repo-input.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/repo-input.js +0 -88
- package/packages/typescript/src/features/orchestrator/services/stall-classifier.d.ts +0 -69
- package/packages/typescript/src/features/orchestrator/services/stall-classifier.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/stall-classifier.js +0 -446
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator-prompts.d.ts +0 -97
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator-prompts.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator-prompts.js +0 -342
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator.d.ts +0 -421
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-coordinator.js +0 -2356
- package/packages/typescript/src/features/orchestrator/services/swarm-decision-loop.d.ts +0 -52
- package/packages/typescript/src/features/orchestrator/services/swarm-decision-loop.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-decision-loop.js +0 -1538
- package/packages/typescript/src/features/orchestrator/services/swarm-event-triage.d.ts +0 -49
- package/packages/typescript/src/features/orchestrator/services/swarm-event-triage.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-event-triage.js +0 -171
- package/packages/typescript/src/features/orchestrator/services/swarm-history.d.ts +0 -27
- package/packages/typescript/src/features/orchestrator/services/swarm-history.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-history.js +0 -148
- package/packages/typescript/src/features/orchestrator/services/swarm-idle-watchdog.d.ts +0 -22
- package/packages/typescript/src/features/orchestrator/services/swarm-idle-watchdog.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/swarm-idle-watchdog.js +0 -265
- package/packages/typescript/src/features/orchestrator/services/task-acceptance.d.ts +0 -8
- package/packages/typescript/src/features/orchestrator/services/task-acceptance.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-acceptance.js +0 -114
- package/packages/typescript/src/features/orchestrator/services/task-agent-auth.d.ts +0 -68
- package/packages/typescript/src/features/orchestrator/services/task-agent-auth.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-agent-auth.js +0 -559
- package/packages/typescript/src/features/orchestrator/services/task-agent-frameworks.d.ts +0 -82
- package/packages/typescript/src/features/orchestrator/services/task-agent-frameworks.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-agent-frameworks.js +0 -738
- package/packages/typescript/src/features/orchestrator/services/task-kind.d.ts +0 -3
- package/packages/typescript/src/features/orchestrator/services/task-kind.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-kind.js +0 -40
- package/packages/typescript/src/features/orchestrator/services/task-policy.d.ts +0 -17
- package/packages/typescript/src/features/orchestrator/services/task-policy.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-policy.js +0 -226
- package/packages/typescript/src/features/orchestrator/services/task-registry.d.ts +0 -550
- package/packages/typescript/src/features/orchestrator/services/task-registry.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-registry.js +0 -2182
- package/packages/typescript/src/features/orchestrator/services/task-share.d.ts +0 -18
- package/packages/typescript/src/features/orchestrator/services/task-share.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-share.js +0 -159
- package/packages/typescript/src/features/orchestrator/services/task-validation.d.ts +0 -69
- package/packages/typescript/src/features/orchestrator/services/task-validation.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-validation.js +0 -587
- package/packages/typescript/src/features/orchestrator/services/task-verifier-runner.d.ts +0 -5
- package/packages/typescript/src/features/orchestrator/services/task-verifier-runner.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/task-verifier-runner.js +0 -372
- package/packages/typescript/src/features/orchestrator/services/trajectory-context.d.ts +0 -73
- package/packages/typescript/src/features/orchestrator/services/trajectory-context.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/trajectory-context.js +0 -64
- package/packages/typescript/src/features/orchestrator/services/trajectory-feedback.d.ts +0 -53
- package/packages/typescript/src/features/orchestrator/services/trajectory-feedback.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/trajectory-feedback.js +0 -260
- package/packages/typescript/src/features/orchestrator/services/workspace-git-ops.d.ts +0 -28
- package/packages/typescript/src/features/orchestrator/services/workspace-git-ops.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/workspace-git-ops.js +0 -105
- package/packages/typescript/src/features/orchestrator/services/workspace-github.d.ts +0 -58
- package/packages/typescript/src/features/orchestrator/services/workspace-github.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/workspace-github.js +0 -139
- package/packages/typescript/src/features/orchestrator/services/workspace-lifecycle.d.ts +0 -18
- package/packages/typescript/src/features/orchestrator/services/workspace-lifecycle.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/workspace-lifecycle.js +0 -86
- package/packages/typescript/src/features/orchestrator/services/workspace-service.d.ts +0 -118
- package/packages/typescript/src/features/orchestrator/services/workspace-service.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/workspace-service.js +0 -533
- package/packages/typescript/src/features/orchestrator/services/workspace-types.d.ts +0 -81
- package/packages/typescript/src/features/orchestrator/services/workspace-types.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/services/workspace-types.js +0 -8
- package/packages/typescript/src/features/orchestrator/task-progress-streamer.d.ts +0 -38
- package/packages/typescript/src/features/orchestrator/task-progress-streamer.d.ts.map +0 -1
- package/packages/typescript/src/features/orchestrator/task-progress-streamer.js +0 -293
- /package/{packages/agent → apps/app-lifeops}/src/inbox/channel-deep-links.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/channel-deep-links.js +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/config.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/message-fetcher.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/message-fetcher.js +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/reflection.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/reflection.js +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/repository.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/repository.js +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/triage-classifier.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/triage-classifier.js +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/types.d.ts +0 -0
- /package/{packages/agent → apps/app-lifeops}/src/inbox/types.js +0 -0
|
@@ -1,1538 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Swarm Coordinator — Decision Loop & Blocked/Turn-Complete Handlers
|
|
3
|
-
*
|
|
4
|
-
* Extracted from swarm-coordinator.ts for modularity.
|
|
5
|
-
* All functions are pure async helpers that receive a SwarmCoordinatorContext
|
|
6
|
-
* to access shared state and services.
|
|
7
|
-
*
|
|
8
|
-
* @module services/swarm-decision-loop
|
|
9
|
-
*/
|
|
10
|
-
import * as path from "node:path";
|
|
11
|
-
import { ModelType } from "@elizaos/core";
|
|
12
|
-
import { cleanForChat, extractCompletionSummary } from "./ansi-utils.js";
|
|
13
|
-
import { buildBlockedEventMessage, buildCoordinationPrompt, buildTurnCompletePrompt, parseCoordinationResponse, } from "./swarm-coordinator-prompts.js";
|
|
14
|
-
import { classifyEventTier } from "./swarm-event-triage.js";
|
|
15
|
-
import { validateTaskCompletion } from "./task-validation.js";
|
|
16
|
-
import { runReadyTaskVerifiers } from "./task-verifier-runner.js";
|
|
17
|
-
import { withTrajectoryContext } from "./trajectory-context.js";
|
|
18
|
-
// ─── Constants ───
|
|
19
|
-
/** Timeout for agent decision pipeline callback (ms). */
|
|
20
|
-
const DECISION_CB_TIMEOUT_MS = 30_000;
|
|
21
|
-
const LOGIN_REQUIRED_PROMPT_RE = /\b(?:requires authentication|needs (?:a )?provider login|run\s+"?claude login"?|claude code requires authentication|login required|authenticate|sign in)\b/i;
|
|
22
|
-
/** Wrap a promise with a timeout. Rejects with an error if not resolved in time. */
|
|
23
|
-
function withTimeout(promise, ms, label) {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
const timer = setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms);
|
|
26
|
-
promise.then((val) => {
|
|
27
|
-
clearTimeout(timer);
|
|
28
|
-
resolve(val);
|
|
29
|
-
}, (err) => {
|
|
30
|
-
clearTimeout(timer);
|
|
31
|
-
reject(err);
|
|
32
|
-
});
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
/** Maximum consecutive auto-responses before escalating to a human. */
|
|
36
|
-
const MAX_AUTO_RESPONSES = 10;
|
|
37
|
-
/**
|
|
38
|
-
* Grace period after the coordinator sends input to an agent (ms).
|
|
39
|
-
* During this window, stall and turn-complete events are suppressed
|
|
40
|
-
* to give the agent time to process the input before re-assessment.
|
|
41
|
-
*/
|
|
42
|
-
export const POST_SEND_COOLDOWN_MS = 15_000;
|
|
43
|
-
const deferredTurnCompleteTimers = new Map();
|
|
44
|
-
/** Clear all deferred turn-complete timers (used during coordinator shutdown). */
|
|
45
|
-
export function clearDeferredTurnCompleteTimers() {
|
|
46
|
-
for (const timer of deferredTurnCompleteTimers.values()) {
|
|
47
|
-
clearTimeout(timer);
|
|
48
|
-
}
|
|
49
|
-
deferredTurnCompleteTimers.clear();
|
|
50
|
-
}
|
|
51
|
-
// ─── Helpers ───
|
|
52
|
-
/** Build a TaskContextSummary from a TaskContext. */
|
|
53
|
-
function toContextSummary(taskCtx) {
|
|
54
|
-
return {
|
|
55
|
-
sessionId: taskCtx.sessionId,
|
|
56
|
-
agentType: taskCtx.agentType,
|
|
57
|
-
label: taskCtx.label,
|
|
58
|
-
originalTask: taskCtx.originalTask,
|
|
59
|
-
workdir: taskCtx.workdir,
|
|
60
|
-
repo: taskCtx.repo,
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
/** Extract recent non-auto-resolved decisions as history entries. */
|
|
64
|
-
function toDecisionHistory(taskCtx) {
|
|
65
|
-
return taskCtx.decisions
|
|
66
|
-
.filter((d) => d.decision !== "auto_resolved")
|
|
67
|
-
.slice(-5)
|
|
68
|
-
.map((d) => ({
|
|
69
|
-
event: d.event,
|
|
70
|
-
promptText: d.promptText,
|
|
71
|
-
action: d.decision,
|
|
72
|
-
response: d.response,
|
|
73
|
-
reasoning: d.reasoning,
|
|
74
|
-
}));
|
|
75
|
-
}
|
|
76
|
-
/** Collect sibling task summaries for cross-task context (excludes the current session). */
|
|
77
|
-
function collectSiblings(ctx, currentSessionId) {
|
|
78
|
-
const siblings = [];
|
|
79
|
-
for (const [sid, task] of ctx.tasks) {
|
|
80
|
-
if (sid === currentSessionId)
|
|
81
|
-
continue;
|
|
82
|
-
// Find the most recent keyDecision from this sibling's decisions
|
|
83
|
-
let lastKeyDecision;
|
|
84
|
-
for (let i = task.decisions.length - 1; i >= 0; i--) {
|
|
85
|
-
const d = task.decisions[i];
|
|
86
|
-
if (d.reasoning && d.decision !== "auto_resolved") {
|
|
87
|
-
lastKeyDecision = d.reasoning;
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// Also check shared decisions for this sibling's key decisions
|
|
92
|
-
for (let i = ctx.sharedDecisions.length - 1; i >= 0; i--) {
|
|
93
|
-
const sd = ctx.sharedDecisions[i];
|
|
94
|
-
if (sd.agentLabel === task.label) {
|
|
95
|
-
lastKeyDecision = sd.summary;
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
siblings.push({
|
|
100
|
-
label: task.label,
|
|
101
|
-
agentType: task.agentType,
|
|
102
|
-
originalTask: task.originalTask,
|
|
103
|
-
status: task.status,
|
|
104
|
-
lastKeyDecision,
|
|
105
|
-
completionSummary: task.completionSummary,
|
|
106
|
-
});
|
|
107
|
-
}
|
|
108
|
-
return siblings;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Enrich a text response with any shared decisions the agent hasn't seen yet.
|
|
112
|
-
* Returns the enriched response and the snapshot index to commit after send.
|
|
113
|
-
* Short responses (like "y", "n", single-word approvals) are left untouched
|
|
114
|
-
* to avoid confusing TUI prompts.
|
|
115
|
-
*/
|
|
116
|
-
function enrichWithSharedDecisions(ctx, sessionId, response) {
|
|
117
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
118
|
-
if (!taskCtx)
|
|
119
|
-
return { response };
|
|
120
|
-
const allDecisions = ctx.sharedDecisions;
|
|
121
|
-
const lastSeen = taskCtx.lastSeenDecisionIndex;
|
|
122
|
-
// Snapshot the current length so we don't skip decisions appended during send.
|
|
123
|
-
const snapshotEnd = allDecisions.length;
|
|
124
|
-
if (lastSeen >= snapshotEnd)
|
|
125
|
-
return { response };
|
|
126
|
-
// Don't inject context into short responses (approvals, single words)
|
|
127
|
-
if (response.length < 20) {
|
|
128
|
-
return { response };
|
|
129
|
-
}
|
|
130
|
-
const unseen = allDecisions.slice(lastSeen, snapshotEnd);
|
|
131
|
-
const contextBlock = unseen
|
|
132
|
-
.map((d) => `[${d.agentLabel}] ${d.summary}`)
|
|
133
|
-
.join("; ");
|
|
134
|
-
return {
|
|
135
|
-
response: `${response}\n\n(Context from other agents: ${contextBlock})`,
|
|
136
|
-
snapshotIndex: snapshotEnd,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
/** Advance the shared-decisions high-water mark for a session after a successful send. */
|
|
140
|
-
function commitSharedDecisionIndex(ctx, sessionId, snapshotIndex) {
|
|
141
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
142
|
-
if (taskCtx) {
|
|
143
|
-
taskCtx.lastSeenDecisionIndex = snapshotIndex;
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
/** Record a key decision from an LLM response into the shared decisions list. */
|
|
147
|
-
function recordKeyDecision(ctx, agentLabel, decision) {
|
|
148
|
-
if (!decision.keyDecision)
|
|
149
|
-
return;
|
|
150
|
-
ctx.sharedDecisions.push({
|
|
151
|
-
agentLabel,
|
|
152
|
-
summary: decision.keyDecision,
|
|
153
|
-
timestamp: Date.now(),
|
|
154
|
-
});
|
|
155
|
-
ctx.log(`Shared decision from "${agentLabel}": ${decision.keyDecision}`);
|
|
156
|
-
}
|
|
157
|
-
/**
|
|
158
|
-
* Drain a buffered task_complete event for a session after an in-flight
|
|
159
|
-
* decision finishes. Prevents task_complete from being silently dropped
|
|
160
|
-
* when it arrives during a slow handleBlocked/handleAutonomous LLM call.
|
|
161
|
-
*/
|
|
162
|
-
async function drainPendingTurnComplete(ctx, sessionId) {
|
|
163
|
-
if (!ctx.pendingTurnComplete.has(sessionId))
|
|
164
|
-
return;
|
|
165
|
-
const pendingData = ctx.pendingTurnComplete.get(sessionId);
|
|
166
|
-
ctx.pendingTurnComplete.delete(sessionId);
|
|
167
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
168
|
-
if (!taskCtx ||
|
|
169
|
-
(taskCtx.status !== "active" && taskCtx.status !== "tool_running")) {
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
ctx.log(`Draining buffered turn-complete for "${taskCtx.label}"`);
|
|
173
|
-
await handleTurnComplete(ctx, sessionId, taskCtx, pendingData);
|
|
174
|
-
}
|
|
175
|
-
/**
|
|
176
|
-
* Drain a buffered blocked event for a session after an in-flight
|
|
177
|
-
* decision finishes. Prevents a distinct blocked prompt from being
|
|
178
|
-
* silently dropped when it arrives during a slow LLM call.
|
|
179
|
-
*/
|
|
180
|
-
async function drainPendingBlocked(ctx, sessionId) {
|
|
181
|
-
if (!ctx.pendingBlocked.has(sessionId))
|
|
182
|
-
return;
|
|
183
|
-
const pendingData = ctx.pendingBlocked.get(sessionId);
|
|
184
|
-
ctx.pendingBlocked.delete(sessionId);
|
|
185
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
186
|
-
// Mirror drainPendingTurnComplete: a buffered blocked event should still
|
|
187
|
-
// drain if the task is in tool_running state (subagents using tools sit
|
|
188
|
-
// there continuously). Without this, a blocked prompt that arrived during
|
|
189
|
-
// an in-flight decision gets dropped silently when the lock releases.
|
|
190
|
-
if (!taskCtx ||
|
|
191
|
-
(taskCtx.status !== "active" && taskCtx.status !== "tool_running")) {
|
|
192
|
-
return;
|
|
193
|
-
}
|
|
194
|
-
ctx.log(`Draining buffered blocked event for "${taskCtx.label}"`);
|
|
195
|
-
await handleBlocked(ctx, sessionId, taskCtx, pendingData);
|
|
196
|
-
}
|
|
197
|
-
/** Format a decision's response for recording. */
|
|
198
|
-
function formatDecisionResponse(decision) {
|
|
199
|
-
if (decision.action !== "respond")
|
|
200
|
-
return undefined;
|
|
201
|
-
return decision.useKeys
|
|
202
|
-
? `keys:${decision.keys?.join(",")}`
|
|
203
|
-
: decision.response;
|
|
204
|
-
}
|
|
205
|
-
function truncateForUser(text, max = 140) {
|
|
206
|
-
const trimmed = text.trim();
|
|
207
|
-
if (trimmed.length <= max) {
|
|
208
|
-
return trimmed;
|
|
209
|
-
}
|
|
210
|
-
return `${trimmed.slice(0, max)}...`;
|
|
211
|
-
}
|
|
212
|
-
function extractLoginInstructions(eventData) {
|
|
213
|
-
const instructions = typeof eventData.promptInfo?.instructions === "string"
|
|
214
|
-
? eventData.promptInfo.instructions.trim()
|
|
215
|
-
: "";
|
|
216
|
-
if (instructions) {
|
|
217
|
-
return instructions;
|
|
218
|
-
}
|
|
219
|
-
return typeof eventData.promptInfo?.prompt === "string"
|
|
220
|
-
? eventData.promptInfo.prompt.trim()
|
|
221
|
-
: "";
|
|
222
|
-
}
|
|
223
|
-
function isLoginRequiredPrompt(promptText, promptType) {
|
|
224
|
-
if (promptType === "login") {
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
227
|
-
return LOGIN_REQUIRED_PROMPT_RE.test(promptText);
|
|
228
|
-
}
|
|
229
|
-
function formatSuggestedAction(decision) {
|
|
230
|
-
if (!decision) {
|
|
231
|
-
return "Needs human review with no automatic suggestion.";
|
|
232
|
-
}
|
|
233
|
-
if (decision.action === "respond") {
|
|
234
|
-
if (decision.useKeys && decision.keys?.length) {
|
|
235
|
-
return `Suggested action: send keys ${decision.keys.join(", ")}.`;
|
|
236
|
-
}
|
|
237
|
-
if (decision.response?.trim()) {
|
|
238
|
-
return `Suggested action: reply "${truncateForUser(decision.response, 80)}".`;
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return `Suggested action: ${decision.action}.`;
|
|
242
|
-
}
|
|
243
|
-
function decisionFromSuggestedResponse(suggestedResponse, reasoning = "Used adapter-provided auto-response for a routine blocking prompt.") {
|
|
244
|
-
if (suggestedResponse.startsWith("keys:")) {
|
|
245
|
-
return {
|
|
246
|
-
action: "respond",
|
|
247
|
-
useKeys: true,
|
|
248
|
-
keys: suggestedResponse
|
|
249
|
-
.slice("keys:".length)
|
|
250
|
-
.split(",")
|
|
251
|
-
.map((part) => part.trim())
|
|
252
|
-
.filter(Boolean),
|
|
253
|
-
reasoning,
|
|
254
|
-
};
|
|
255
|
-
}
|
|
256
|
-
return {
|
|
257
|
-
action: "respond",
|
|
258
|
-
response: suggestedResponse,
|
|
259
|
-
reasoning,
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
function inferRoutinePromptResponse(promptText, promptType) {
|
|
263
|
-
if (promptType === "project_select" &&
|
|
264
|
-
/project|workspace/i.test(promptText)) {
|
|
265
|
-
return {
|
|
266
|
-
suggestedResponse: "keys:enter",
|
|
267
|
-
reasoning: "Accepted the current workspace so a routine project-selection prompt does not stall the task.",
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
if (promptType === "config" &&
|
|
271
|
-
/claude (?:dialog awaiting navigation|menu navigation required)/i.test(promptText)) {
|
|
272
|
-
return {
|
|
273
|
-
suggestedResponse: "keys:enter",
|
|
274
|
-
reasoning: "Accepted Claude's default dialog action so the replacement session can continue without exiting the CLI.",
|
|
275
|
-
};
|
|
276
|
-
}
|
|
277
|
-
if (promptType && promptType !== "unknown") {
|
|
278
|
-
return null;
|
|
279
|
-
}
|
|
280
|
-
if (/should i open (?:the )?(?:page|link|url).*(?:new tab|browser tab).*instead\??/i.test(promptText)) {
|
|
281
|
-
return {
|
|
282
|
-
suggestedResponse: "yes",
|
|
283
|
-
reasoning: "Accepted routine browser follow-up so the agent can keep using its web tool without human intervention.",
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
if (/cheaper,\s*faster,\s*but less capable/i.test(promptText) &&
|
|
287
|
-
/keep current model/i.test(promptText)) {
|
|
288
|
-
return {
|
|
289
|
-
suggestedResponse: "2",
|
|
290
|
-
reasoning: "Kept the current Codex model so a routine model-selection prompt does not stall the task.",
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
return null;
|
|
294
|
-
}
|
|
295
|
-
/** Check if a permission prompt references paths outside the workspace. */
|
|
296
|
-
export function isOutOfScopeAccess(promptText, workdir) {
|
|
297
|
-
// Strip URLs so we don't false-positive on https://example.com/foo/bar
|
|
298
|
-
const stripped = promptText.replace(/https?:\/\/\S+/g, "");
|
|
299
|
-
// Match absolute paths: multi-segment (/dir/file) or well-known single-segment
|
|
300
|
-
// roots that agents should never touch (/etc, /tmp, /var, /usr, /opt, /sys, /proc).
|
|
301
|
-
const multiSegment = /\/[\w.-]+(?:\/[\w.-]+)+/g;
|
|
302
|
-
const sensitiveRoots = /\b\/(etc|tmp|var|usr|opt|sys|proc|root)\b/g;
|
|
303
|
-
const homeTilde = /~\/[\w.-]+/g;
|
|
304
|
-
const matches = [
|
|
305
|
-
...(stripped.match(multiSegment) ?? []),
|
|
306
|
-
...(stripped.match(sensitiveRoots) ?? []).map((m) => m.trimStart()),
|
|
307
|
-
...(stripped.match(homeTilde) ?? []).map((m) => m.replace("~", process.env.HOME ?? "/home/user")),
|
|
308
|
-
];
|
|
309
|
-
if (matches.length === 0)
|
|
310
|
-
return false;
|
|
311
|
-
const resolvedWorkdir = path.resolve(workdir);
|
|
312
|
-
return matches.some((p) => {
|
|
313
|
-
const resolved = path.resolve(p);
|
|
314
|
-
return (!resolved.startsWith(resolvedWorkdir + path.sep) &&
|
|
315
|
-
resolved !== resolvedWorkdir);
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
/**
|
|
319
|
-
* Check if all registered tasks have reached a terminal state.
|
|
320
|
-
* If so, send a swarm-wide summary message to the chat.
|
|
321
|
-
*/
|
|
322
|
-
export function checkAllTasksComplete(ctx) {
|
|
323
|
-
void checkAllTasksCompleteAsync(ctx);
|
|
324
|
-
}
|
|
325
|
-
async function checkAllTasksCompleteAsync(ctx) {
|
|
326
|
-
const tasks = Array.from(ctx.tasks.values());
|
|
327
|
-
if (tasks.length === 0)
|
|
328
|
-
return;
|
|
329
|
-
const terminalStates = new Set(["completed", "stopped", "error"]);
|
|
330
|
-
const allDone = tasks.every((t) => terminalStates.has(t.status));
|
|
331
|
-
if (!allDone) {
|
|
332
|
-
const statuses = tasks.map((t) => `${t.label}=${t.status}`).join(", ");
|
|
333
|
-
ctx.log(`checkAllTasksComplete: not all done yet — ${statuses}`);
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
const threadIds = [...new Set(tasks.map((task) => task.threadId))];
|
|
337
|
-
const failingThreads = [];
|
|
338
|
-
for (const threadId of threadIds) {
|
|
339
|
-
await runReadyTaskVerifiers(ctx.runtime, ctx.taskRegistry, threadId);
|
|
340
|
-
const thread = await ctx.taskRegistry.getThread(threadId);
|
|
341
|
-
if (!thread || thread.nodes.length === 0) {
|
|
342
|
-
continue;
|
|
343
|
-
}
|
|
344
|
-
const goalNodes = thread.nodes.filter((node) => node.kind === "goal");
|
|
345
|
-
const failedGoals = goalNodes
|
|
346
|
-
.filter((node) => node.status === "failed" ||
|
|
347
|
-
node.status === "canceled" ||
|
|
348
|
-
node.status === "interrupted")
|
|
349
|
-
.map((node) => `${node.title}=${node.status}`);
|
|
350
|
-
const incompleteGoals = goalNodes
|
|
351
|
-
.filter((node) => node.status !== "completed" &&
|
|
352
|
-
node.status !== "failed" &&
|
|
353
|
-
node.status !== "canceled" &&
|
|
354
|
-
node.status !== "interrupted")
|
|
355
|
-
.map((node) => `${node.title}=${node.status}`);
|
|
356
|
-
if (incompleteGoals.length > 0) {
|
|
357
|
-
const pendingGoals = goalNodes
|
|
358
|
-
.filter((node) => node.status !== "completed")
|
|
359
|
-
.map((node) => `${node.title}=${node.status}`)
|
|
360
|
-
.join(", ");
|
|
361
|
-
ctx.log(`checkAllTasksComplete: thread ${threadId} still has non-terminal goal nodes — ${pendingGoals}`);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
const runningVerifiers = thread.verifierJobs.filter((job) => job.status === "running");
|
|
365
|
-
if (runningVerifiers.length > 0) {
|
|
366
|
-
ctx.log(`checkAllTasksComplete: thread ${threadId} still has running verifier jobs`);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
const pendingVerifiers = thread.verifierJobs.filter((job) => job.status === "pending");
|
|
370
|
-
if (pendingVerifiers.length > 0) {
|
|
371
|
-
ctx.log(`checkAllTasksComplete: thread ${threadId} still has pending verifier jobs`);
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const failedVerifiers = thread.verifierJobs
|
|
375
|
-
.filter((job) => job.status === "failed")
|
|
376
|
-
.map((job) => `${job.title}=failed`);
|
|
377
|
-
if (failedGoals.length > 0 || failedVerifiers.length > 0) {
|
|
378
|
-
failingThreads.push({
|
|
379
|
-
threadId,
|
|
380
|
-
failedGoals,
|
|
381
|
-
failedVerifiers,
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
if (failingThreads.length > 0) {
|
|
386
|
-
if (ctx.swarmCompleteNotified) {
|
|
387
|
-
ctx.log("checkAllTasksComplete: failure notification already sent — skipping");
|
|
388
|
-
return;
|
|
389
|
-
}
|
|
390
|
-
ctx.swarmCompleteNotified = true;
|
|
391
|
-
const summary = failingThreads
|
|
392
|
-
.map((thread) => [
|
|
393
|
-
`thread ${thread.threadId}`,
|
|
394
|
-
thread.failedGoals.length > 0
|
|
395
|
-
? `failed goals: ${thread.failedGoals.join(", ")}`
|
|
396
|
-
: "",
|
|
397
|
-
thread.failedVerifiers.length > 0
|
|
398
|
-
? `failed verifiers: ${thread.failedVerifiers.join(", ")}`
|
|
399
|
-
: "",
|
|
400
|
-
]
|
|
401
|
-
.filter(Boolean)
|
|
402
|
-
.join(" | "))
|
|
403
|
-
.join("; ");
|
|
404
|
-
ctx.log(`checkAllTasksComplete: sessions are terminal but acceptance failed — ${summary}`);
|
|
405
|
-
ctx.broadcast({
|
|
406
|
-
type: "swarm_attention_required",
|
|
407
|
-
sessionId: "",
|
|
408
|
-
timestamp: Date.now(),
|
|
409
|
-
data: {
|
|
410
|
-
summary,
|
|
411
|
-
threads: failingThreads,
|
|
412
|
-
},
|
|
413
|
-
});
|
|
414
|
-
ctx.sendChatMessage(`Task agents finished running, but the coordinator could not prove completion. ${summary}`, "task-agent");
|
|
415
|
-
return;
|
|
416
|
-
}
|
|
417
|
-
// Guard: only fire once per swarm (reset by coordinator on stop/new swarm)
|
|
418
|
-
if (ctx.swarmCompleteNotified) {
|
|
419
|
-
ctx.log("checkAllTasksComplete: already notified — skipping");
|
|
420
|
-
return;
|
|
421
|
-
}
|
|
422
|
-
ctx.swarmCompleteNotified = true;
|
|
423
|
-
const completed = tasks.filter((t) => t.status === "completed");
|
|
424
|
-
const stopped = tasks.filter((t) => t.status === "stopped");
|
|
425
|
-
const errored = tasks.filter((t) => t.status === "error");
|
|
426
|
-
const parts = [];
|
|
427
|
-
if (completed.length > 0) {
|
|
428
|
-
parts.push(`${completed.length} completed`);
|
|
429
|
-
}
|
|
430
|
-
if (stopped.length > 0) {
|
|
431
|
-
parts.push(`${stopped.length} stopped`);
|
|
432
|
-
}
|
|
433
|
-
if (errored.length > 0) {
|
|
434
|
-
parts.push(`${errored.length} errored`);
|
|
435
|
-
}
|
|
436
|
-
ctx.log(`checkAllTasksComplete: all ${tasks.length} tasks terminal (${parts.join(", ")}) — firing swarm_complete`);
|
|
437
|
-
ctx.broadcast({
|
|
438
|
-
type: "swarm_complete",
|
|
439
|
-
sessionId: "",
|
|
440
|
-
timestamp: Date.now(),
|
|
441
|
-
data: {
|
|
442
|
-
total: tasks.length,
|
|
443
|
-
completed: completed.length,
|
|
444
|
-
stopped: stopped.length,
|
|
445
|
-
errored: errored.length,
|
|
446
|
-
},
|
|
447
|
-
});
|
|
448
|
-
// Fire swarm complete callback for synthesis — if wired, the host
|
|
449
|
-
// (milaidy) will use this to generate a synthesized overview.
|
|
450
|
-
const swarmCompleteCb = ctx.getSwarmCompleteCallback();
|
|
451
|
-
const sendFallbackSummary = () => {
|
|
452
|
-
ctx.sendChatMessage(`All ${tasks.length} task agents finished (${parts.join(", ")}). Review their work when you're ready.`, "task-agent");
|
|
453
|
-
};
|
|
454
|
-
if (swarmCompleteCb) {
|
|
455
|
-
ctx.log("checkAllTasksComplete: swarm complete callback is wired — calling synthesis");
|
|
456
|
-
const taskSummaries = tasks.map((t) => {
|
|
457
|
-
// Fold in shared decisions relevant to this task so the synthesis
|
|
458
|
-
// prompt includes the agent's actual findings, not just PR URLs.
|
|
459
|
-
const decisions = ctx.sharedDecisions
|
|
460
|
-
.filter((sd) => sd.agentLabel === t.label)
|
|
461
|
-
.map((sd) => sd.summary);
|
|
462
|
-
const summaryParts = [];
|
|
463
|
-
if (decisions.length > 0)
|
|
464
|
-
summaryParts.push(decisions.join("; "));
|
|
465
|
-
if (t.completionSummary)
|
|
466
|
-
summaryParts.push(t.completionSummary);
|
|
467
|
-
return {
|
|
468
|
-
sessionId: t.sessionId,
|
|
469
|
-
label: t.label,
|
|
470
|
-
agentType: t.agentType,
|
|
471
|
-
originalTask: t.originalTask,
|
|
472
|
-
status: t.status,
|
|
473
|
-
completionSummary: summaryParts.join("\n") || "",
|
|
474
|
-
};
|
|
475
|
-
});
|
|
476
|
-
// Wrap in Promise.resolve().then() to catch sync throws, and race against
|
|
477
|
-
// a timeout to guard against callbacks that never settle.
|
|
478
|
-
void withTimeout(Promise.resolve().then(() => swarmCompleteCb({
|
|
479
|
-
tasks: taskSummaries,
|
|
480
|
-
total: tasks.length,
|
|
481
|
-
completed: completed.length,
|
|
482
|
-
stopped: stopped.length,
|
|
483
|
-
errored: errored.length,
|
|
484
|
-
})), DECISION_CB_TIMEOUT_MS, "swarmCompleteCb").catch((err) => {
|
|
485
|
-
ctx.log(`Swarm complete callback failed: ${err} — falling back to generic summary`);
|
|
486
|
-
sendFallbackSummary();
|
|
487
|
-
});
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
ctx.log("checkAllTasksComplete: no synthesis callback — sending generic message");
|
|
491
|
-
sendFallbackSummary();
|
|
492
|
-
}
|
|
493
|
-
}
|
|
494
|
-
/** Fetch recent PTY output, returning empty string on failure. */
|
|
495
|
-
async function fetchRecentOutput(ctx, sessionId, lines = 50) {
|
|
496
|
-
if (!ctx.ptyService)
|
|
497
|
-
return "";
|
|
498
|
-
try {
|
|
499
|
-
return await ctx.ptyService.getSessionOutput(sessionId, lines);
|
|
500
|
-
}
|
|
501
|
-
catch {
|
|
502
|
-
return "";
|
|
503
|
-
}
|
|
504
|
-
}
|
|
505
|
-
// ─── LLM Decision ───
|
|
506
|
-
/**
|
|
507
|
-
* Ask the LLM to make a coordination decision about a blocked agent.
|
|
508
|
-
*/
|
|
509
|
-
export async function makeCoordinationDecision(ctx, taskCtx, promptText, recentOutput) {
|
|
510
|
-
const prompt = buildCoordinationPrompt(toContextSummary(taskCtx), promptText, recentOutput, toDecisionHistory(taskCtx), collectSiblings(ctx, taskCtx.sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
511
|
-
try {
|
|
512
|
-
const result = await withTrajectoryContext(ctx.runtime, {
|
|
513
|
-
source: "orchestrator",
|
|
514
|
-
decisionType: "coordination",
|
|
515
|
-
sessionId: taskCtx.sessionId,
|
|
516
|
-
taskLabel: taskCtx.label,
|
|
517
|
-
repo: taskCtx.repo,
|
|
518
|
-
workdir: taskCtx.workdir,
|
|
519
|
-
originalTask: taskCtx.originalTask,
|
|
520
|
-
}, () => ctx.runtime.useModel(ModelType.TEXT_SMALL, { prompt }));
|
|
521
|
-
return parseCoordinationResponse(result);
|
|
522
|
-
}
|
|
523
|
-
catch (err) {
|
|
524
|
-
ctx.log(`LLM coordination call failed: ${err}`);
|
|
525
|
-
return null;
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
/**
|
|
529
|
-
* Execute a coordination decision — send response, complete session, escalate, or ignore.
|
|
530
|
-
*/
|
|
531
|
-
export async function executeDecision(ctx, sessionId, decision) {
|
|
532
|
-
if (!ctx.ptyService)
|
|
533
|
-
return;
|
|
534
|
-
switch (decision.action) {
|
|
535
|
-
case "respond": {
|
|
536
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
537
|
-
if (taskCtx) {
|
|
538
|
-
taskCtx.status = "active";
|
|
539
|
-
}
|
|
540
|
-
if (decision.useKeys && decision.keys) {
|
|
541
|
-
await ctx.ptyService.sendKeysToSession(sessionId, decision.keys);
|
|
542
|
-
}
|
|
543
|
-
else if (decision.response !== undefined) {
|
|
544
|
-
// Proactive injection: append unseen shared decisions to text responses
|
|
545
|
-
const { response: enriched, snapshotIndex } = enrichWithSharedDecisions(ctx, sessionId, decision.response);
|
|
546
|
-
await ctx.ptyService.sendToSession(sessionId, enriched);
|
|
547
|
-
// Only advance the high-water mark after send succeeds — if the send
|
|
548
|
-
// fails, the decisions will be retried on the next enrichment.
|
|
549
|
-
if (snapshotIndex !== undefined) {
|
|
550
|
-
commitSharedDecisionIndex(ctx, sessionId, snapshotIndex);
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
// Mark the send time so stall/turn-complete events are suppressed
|
|
554
|
-
// during the grace period while the agent processes this input.
|
|
555
|
-
if (taskCtx) {
|
|
556
|
-
taskCtx.lastInputSentAt = Date.now();
|
|
557
|
-
await ctx.syncTaskContext(taskCtx);
|
|
558
|
-
}
|
|
559
|
-
break;
|
|
560
|
-
}
|
|
561
|
-
case "complete": {
|
|
562
|
-
const taskCtx = ctx.tasks.get(sessionId);
|
|
563
|
-
// Extract meaningful artifacts (PR URLs, commits) instead of
|
|
564
|
-
// dumping raw terminal output which is full of TUI noise.
|
|
565
|
-
let summary = "";
|
|
566
|
-
try {
|
|
567
|
-
const rawOutput = await ctx.ptyService.getSessionOutput(sessionId, 50);
|
|
568
|
-
summary = extractCompletionSummary(rawOutput);
|
|
569
|
-
}
|
|
570
|
-
catch {
|
|
571
|
-
/* ignore */
|
|
572
|
-
}
|
|
573
|
-
if (!taskCtx) {
|
|
574
|
-
ctx.broadcast({
|
|
575
|
-
type: "task_complete",
|
|
576
|
-
sessionId,
|
|
577
|
-
timestamp: Date.now(),
|
|
578
|
-
data: { reasoning: decision.reasoning },
|
|
579
|
-
});
|
|
580
|
-
ctx.ptyService.stopSession(sessionId, /* force */ true).catch((err) => {
|
|
581
|
-
ctx.log(`Failed to stop session after LLM-detected completion: ${err}`);
|
|
582
|
-
});
|
|
583
|
-
break;
|
|
584
|
-
}
|
|
585
|
-
taskCtx.completionSummary = summary || decision.reasoning || "";
|
|
586
|
-
taskCtx.status = "tool_running";
|
|
587
|
-
await Promise.all([
|
|
588
|
-
ctx.syncTaskContext(taskCtx),
|
|
589
|
-
ctx.taskRegistry.appendEvent({
|
|
590
|
-
threadId: taskCtx.threadId,
|
|
591
|
-
sessionId,
|
|
592
|
-
eventType: "validation_started",
|
|
593
|
-
summary: `Validation started for "${taskCtx.label}"`,
|
|
594
|
-
data: {
|
|
595
|
-
completionReasoning: decision.reasoning,
|
|
596
|
-
completionSummary: taskCtx.completionSummary,
|
|
597
|
-
},
|
|
598
|
-
}),
|
|
599
|
-
]);
|
|
600
|
-
ctx.broadcast({
|
|
601
|
-
type: "tool_running",
|
|
602
|
-
sessionId,
|
|
603
|
-
timestamp: Date.now(),
|
|
604
|
-
data: {
|
|
605
|
-
description: "validation",
|
|
606
|
-
},
|
|
607
|
-
});
|
|
608
|
-
const verifierJob = taskCtx.taskNodeId
|
|
609
|
-
? await ctx.taskRegistry.createTaskVerifierJob({
|
|
610
|
-
threadId: taskCtx.threadId,
|
|
611
|
-
nodeId: taskCtx.taskNodeId,
|
|
612
|
-
status: "running",
|
|
613
|
-
verifierType: "task_completion",
|
|
614
|
-
title: `Validate ${taskCtx.label}`,
|
|
615
|
-
instructions: [
|
|
616
|
-
`Task: ${taskCtx.originalTask}`,
|
|
617
|
-
taskCtx.completionSummary
|
|
618
|
-
? `Completion summary: ${taskCtx.completionSummary}`
|
|
619
|
-
: "",
|
|
620
|
-
decision.reasoning ? `Reasoning: ${decision.reasoning}` : "",
|
|
621
|
-
]
|
|
622
|
-
.filter(Boolean)
|
|
623
|
-
.join("\n"),
|
|
624
|
-
config: {
|
|
625
|
-
sessionId,
|
|
626
|
-
agentType: taskCtx.agentType,
|
|
627
|
-
},
|
|
628
|
-
metadata: {
|
|
629
|
-
source: "swarm-decision-loop",
|
|
630
|
-
},
|
|
631
|
-
startedAt: new Date().toISOString(),
|
|
632
|
-
})
|
|
633
|
-
: null;
|
|
634
|
-
const validation = await validateTaskCompletion(ctx, {
|
|
635
|
-
sessionId,
|
|
636
|
-
taskCtx,
|
|
637
|
-
completionReasoning: decision.reasoning,
|
|
638
|
-
completionSummary: taskCtx.completionSummary,
|
|
639
|
-
turnOutput: taskCtx.completionSummary,
|
|
640
|
-
}).catch((err) => ({
|
|
641
|
-
verdict: "escalate",
|
|
642
|
-
summary: err instanceof Error
|
|
643
|
-
? `Validation failed: ${err.message}`
|
|
644
|
-
: `Validation failed: ${String(err)}`,
|
|
645
|
-
followUpPrompt: undefined,
|
|
646
|
-
reportPath: "",
|
|
647
|
-
artifacts: [],
|
|
648
|
-
}));
|
|
649
|
-
for (const artifact of validation.artifacts) {
|
|
650
|
-
await ctx.taskRegistry.recordArtifact({
|
|
651
|
-
threadId: taskCtx.threadId,
|
|
652
|
-
sessionId,
|
|
653
|
-
artifactType: artifact.artifactType,
|
|
654
|
-
title: artifact.title,
|
|
655
|
-
path: artifact.path ?? null,
|
|
656
|
-
uri: artifact.uri ?? null,
|
|
657
|
-
mimeType: artifact.mimeType ?? null,
|
|
658
|
-
metadata: artifact.metadata ?? {},
|
|
659
|
-
});
|
|
660
|
-
if (taskCtx.taskNodeId && verifierJob) {
|
|
661
|
-
await ctx.taskRegistry.recordTaskEvidence({
|
|
662
|
-
threadId: taskCtx.threadId,
|
|
663
|
-
nodeId: taskCtx.taskNodeId,
|
|
664
|
-
sessionId,
|
|
665
|
-
verifierJobId: verifierJob.id,
|
|
666
|
-
evidenceType: artifact.artifactType,
|
|
667
|
-
title: artifact.title,
|
|
668
|
-
summary: validation.summary,
|
|
669
|
-
path: artifact.path ?? null,
|
|
670
|
-
uri: artifact.uri ?? null,
|
|
671
|
-
content: artifact.metadata &&
|
|
672
|
-
typeof artifact.metadata === "object" &&
|
|
673
|
-
!Array.isArray(artifact.metadata)
|
|
674
|
-
? artifact.metadata
|
|
675
|
-
: {},
|
|
676
|
-
metadata: {
|
|
677
|
-
mimeType: artifact.mimeType ?? null,
|
|
678
|
-
},
|
|
679
|
-
});
|
|
680
|
-
}
|
|
681
|
-
}
|
|
682
|
-
if (validation.verdict !== "pass") {
|
|
683
|
-
const followUpPrompt = validation.followUpPrompt?.trim() ||
|
|
684
|
-
`Validation found the task incomplete. Continue working until this is resolved:\n\n${validation.summary}`;
|
|
685
|
-
const nextStatus = validation.verdict === "escalate" ? "blocked" : "active";
|
|
686
|
-
taskCtx.status = nextStatus;
|
|
687
|
-
await Promise.all([
|
|
688
|
-
ctx.syncTaskContext(taskCtx),
|
|
689
|
-
verifierJob
|
|
690
|
-
? ctx.taskRegistry.updateTaskVerifierJob(verifierJob.id, {
|
|
691
|
-
status: "failed",
|
|
692
|
-
completedAt: new Date().toISOString(),
|
|
693
|
-
metadata: {
|
|
694
|
-
verdict: validation.verdict,
|
|
695
|
-
summary: validation.summary,
|
|
696
|
-
},
|
|
697
|
-
})
|
|
698
|
-
: Promise.resolve(),
|
|
699
|
-
taskCtx.taskNodeId && verifierJob
|
|
700
|
-
? ctx.taskRegistry.recordTaskEvidence({
|
|
701
|
-
threadId: taskCtx.threadId,
|
|
702
|
-
nodeId: taskCtx.taskNodeId,
|
|
703
|
-
sessionId,
|
|
704
|
-
verifierJobId: verifierJob.id,
|
|
705
|
-
evidenceType: "validation_summary",
|
|
706
|
-
title: `Validation ${validation.verdict} for ${taskCtx.label}`,
|
|
707
|
-
summary: validation.summary,
|
|
708
|
-
content: {
|
|
709
|
-
followUpPrompt: validation.verdict === "revise" ? followUpPrompt : null,
|
|
710
|
-
reportPath: validation.reportPath || null,
|
|
711
|
-
verdict: validation.verdict,
|
|
712
|
-
},
|
|
713
|
-
metadata: {
|
|
714
|
-
source: "task-validation",
|
|
715
|
-
},
|
|
716
|
-
})
|
|
717
|
-
: Promise.resolve(),
|
|
718
|
-
ctx.taskRegistry.appendEvent({
|
|
719
|
-
threadId: taskCtx.threadId,
|
|
720
|
-
sessionId,
|
|
721
|
-
eventType: "validation_failed",
|
|
722
|
-
summary: `Validation did not approve "${taskCtx.label}"`,
|
|
723
|
-
data: {
|
|
724
|
-
verdict: validation.verdict,
|
|
725
|
-
summary: validation.summary,
|
|
726
|
-
followUpPrompt: validation.verdict === "revise" ? followUpPrompt : null,
|
|
727
|
-
reportPath: validation.reportPath || null,
|
|
728
|
-
},
|
|
729
|
-
}),
|
|
730
|
-
]);
|
|
731
|
-
if (validation.verdict === "revise") {
|
|
732
|
-
await ctx.ptyService.sendToSession(sessionId, followUpPrompt);
|
|
733
|
-
taskCtx.lastInputSentAt = Date.now();
|
|
734
|
-
await ctx.syncTaskContext(taskCtx);
|
|
735
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Validation asked the agent to continue: ${validation.summary}`, "coding-agent");
|
|
736
|
-
}
|
|
737
|
-
else {
|
|
738
|
-
ctx.broadcast({
|
|
739
|
-
type: "escalation",
|
|
740
|
-
sessionId,
|
|
741
|
-
timestamp: Date.now(),
|
|
742
|
-
data: {
|
|
743
|
-
reason: "validation_escalation",
|
|
744
|
-
summary: validation.summary,
|
|
745
|
-
},
|
|
746
|
-
});
|
|
747
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Validation needs human review: ${validation.summary}`, "coding-agent");
|
|
748
|
-
}
|
|
749
|
-
break;
|
|
750
|
-
}
|
|
751
|
-
taskCtx.status = "completed";
|
|
752
|
-
await Promise.all([
|
|
753
|
-
ctx.syncTaskContext(taskCtx),
|
|
754
|
-
verifierJob
|
|
755
|
-
? ctx.taskRegistry.updateTaskVerifierJob(verifierJob.id, {
|
|
756
|
-
status: "passed",
|
|
757
|
-
completedAt: new Date().toISOString(),
|
|
758
|
-
metadata: {
|
|
759
|
-
summary: validation.summary,
|
|
760
|
-
reportPath: validation.reportPath || null,
|
|
761
|
-
},
|
|
762
|
-
})
|
|
763
|
-
: Promise.resolve(),
|
|
764
|
-
taskCtx.taskNodeId && verifierJob
|
|
765
|
-
? ctx.taskRegistry.recordTaskEvidence({
|
|
766
|
-
threadId: taskCtx.threadId,
|
|
767
|
-
nodeId: taskCtx.taskNodeId,
|
|
768
|
-
sessionId,
|
|
769
|
-
verifierJobId: verifierJob.id,
|
|
770
|
-
evidenceType: "validation_summary",
|
|
771
|
-
title: `Validation passed for ${taskCtx.label}`,
|
|
772
|
-
summary: validation.summary,
|
|
773
|
-
content: {
|
|
774
|
-
completionSummary: taskCtx.completionSummary,
|
|
775
|
-
reportPath: validation.reportPath || null,
|
|
776
|
-
},
|
|
777
|
-
metadata: {
|
|
778
|
-
source: "task-validation",
|
|
779
|
-
},
|
|
780
|
-
})
|
|
781
|
-
: Promise.resolve(),
|
|
782
|
-
ctx.taskRegistry.updateThreadSummary(taskCtx.threadId, taskCtx.completionSummary),
|
|
783
|
-
ctx.taskRegistry.appendEvent({
|
|
784
|
-
threadId: taskCtx.threadId,
|
|
785
|
-
sessionId,
|
|
786
|
-
eventType: "validation_passed",
|
|
787
|
-
summary: `Validation passed for "${taskCtx.label}"`,
|
|
788
|
-
data: {
|
|
789
|
-
summary: validation.summary,
|
|
790
|
-
reportPath: validation.reportPath || null,
|
|
791
|
-
},
|
|
792
|
-
}),
|
|
793
|
-
ctx.taskRegistry.appendEvent({
|
|
794
|
-
threadId: taskCtx.threadId,
|
|
795
|
-
sessionId,
|
|
796
|
-
eventType: "task_status_changed",
|
|
797
|
-
summary: `Task "${taskCtx.label}" completed`,
|
|
798
|
-
data: {
|
|
799
|
-
status: "completed",
|
|
800
|
-
completionSummary: taskCtx.completionSummary,
|
|
801
|
-
validationSummary: validation.summary,
|
|
802
|
-
},
|
|
803
|
-
}),
|
|
804
|
-
]);
|
|
805
|
-
// Log to persistent history (non-blocking but observed)
|
|
806
|
-
ctx.history
|
|
807
|
-
?.append({
|
|
808
|
-
timestamp: Date.now(),
|
|
809
|
-
type: "task_completed",
|
|
810
|
-
sessionId,
|
|
811
|
-
label: taskCtx.label,
|
|
812
|
-
agentType: taskCtx.agentType,
|
|
813
|
-
repo: taskCtx.repo,
|
|
814
|
-
workdir: taskCtx.workdir,
|
|
815
|
-
completionSummary: taskCtx.completionSummary,
|
|
816
|
-
validationSummary: validation.summary,
|
|
817
|
-
})
|
|
818
|
-
.catch((err) => {
|
|
819
|
-
ctx.log(`Failed to persist task completion for "${taskCtx.label}" (${sessionId}): ${err}`);
|
|
820
|
-
});
|
|
821
|
-
ctx.broadcast({
|
|
822
|
-
type: "task_complete",
|
|
823
|
-
sessionId,
|
|
824
|
-
timestamp: Date.now(),
|
|
825
|
-
data: {
|
|
826
|
-
reasoning: decision.reasoning,
|
|
827
|
-
validationSummary: validation.summary,
|
|
828
|
-
},
|
|
829
|
-
});
|
|
830
|
-
ctx.sendChatMessage(taskCtx.completionSummary
|
|
831
|
-
? `Finished "${taskCtx.label}".\n\n${taskCtx.completionSummary}`
|
|
832
|
-
: `Finished "${taskCtx.label}".`, "coding-agent");
|
|
833
|
-
// Force-kill the session — task is done, nothing to save.
|
|
834
|
-
// SIGKILL ensures the PTY and all child processes exit immediately,
|
|
835
|
-
// preventing orphaned workspace processes.
|
|
836
|
-
ctx.ptyService.stopSession(sessionId, /* force */ true).catch((err) => {
|
|
837
|
-
ctx.log(`Failed to stop session after LLM-detected completion: ${err}`);
|
|
838
|
-
});
|
|
839
|
-
// Check if all tasks are now done — send a swarm-wide summary if so
|
|
840
|
-
checkAllTasksComplete(ctx);
|
|
841
|
-
break;
|
|
842
|
-
}
|
|
843
|
-
case "escalate":
|
|
844
|
-
ctx.broadcast({
|
|
845
|
-
type: "escalation",
|
|
846
|
-
sessionId,
|
|
847
|
-
timestamp: Date.now(),
|
|
848
|
-
data: {
|
|
849
|
-
reasoning: decision.reasoning,
|
|
850
|
-
},
|
|
851
|
-
});
|
|
852
|
-
break;
|
|
853
|
-
case "ignore":
|
|
854
|
-
// No action needed
|
|
855
|
-
break;
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
// ─── Event Handlers ───
|
|
859
|
-
/**
|
|
860
|
-
* Handle a "blocked" session event — auto-resolved, escalated, or routed to decision loop.
|
|
861
|
-
*/
|
|
862
|
-
export async function handleBlocked(ctx, sessionId, taskCtx, data) {
|
|
863
|
-
// Event data from pty-init: { promptInfo: BlockingPromptInfo, autoResponded: boolean }
|
|
864
|
-
const eventData = data;
|
|
865
|
-
// Extract prompt text from promptInfo (the actual blocking prompt info object)
|
|
866
|
-
const promptText = eventData.promptInfo?.prompt ?? eventData.promptInfo?.instructions ?? "";
|
|
867
|
-
if (isLoginRequiredPrompt(promptText, eventData.promptInfo?.type)) {
|
|
868
|
-
const instructions = extractLoginInstructions(eventData);
|
|
869
|
-
const url = typeof eventData.promptInfo?.url === "string" &&
|
|
870
|
-
eventData.promptInfo.url.trim().length > 0
|
|
871
|
-
? eventData.promptInfo.url.trim()
|
|
872
|
-
: null;
|
|
873
|
-
taskCtx.status = "blocked";
|
|
874
|
-
await ctx.syncTaskContext(taskCtx);
|
|
875
|
-
await ctx.recordDecision(taskCtx, {
|
|
876
|
-
timestamp: Date.now(),
|
|
877
|
-
event: "blocked",
|
|
878
|
-
promptText,
|
|
879
|
-
decision: "escalate",
|
|
880
|
-
reasoning: "Provider login is required before the task agent can continue.",
|
|
881
|
-
});
|
|
882
|
-
await ctx.taskRegistry.appendEvent({
|
|
883
|
-
threadId: taskCtx.threadId,
|
|
884
|
-
sessionId,
|
|
885
|
-
eventType: "task_status_changed",
|
|
886
|
-
summary: `Task "${taskCtx.label}" is waiting for login`,
|
|
887
|
-
data: {
|
|
888
|
-
status: "blocked",
|
|
889
|
-
reason: "login_required",
|
|
890
|
-
instructions: instructions || null,
|
|
891
|
-
url,
|
|
892
|
-
promptType: eventData.promptInfo?.type ?? null,
|
|
893
|
-
},
|
|
894
|
-
});
|
|
895
|
-
ctx.broadcast({
|
|
896
|
-
type: "login_required",
|
|
897
|
-
sessionId,
|
|
898
|
-
timestamp: Date.now(),
|
|
899
|
-
data: {
|
|
900
|
-
instructions: instructions || null,
|
|
901
|
-
url,
|
|
902
|
-
prompt: promptText,
|
|
903
|
-
promptType: eventData.promptInfo?.type,
|
|
904
|
-
},
|
|
905
|
-
});
|
|
906
|
-
const loginParts = [
|
|
907
|
-
`"${taskCtx.label}" needs a provider login before it can continue.`,
|
|
908
|
-
instructions || "",
|
|
909
|
-
url ? `Login link: ${url}` : "",
|
|
910
|
-
].filter(Boolean);
|
|
911
|
-
ctx.sendChatMessage(loginParts.join(" "), "coding-agent");
|
|
912
|
-
return;
|
|
913
|
-
}
|
|
914
|
-
// Auto-responded by rules — log and broadcast, no LLM needed
|
|
915
|
-
if (eventData.autoResponded) {
|
|
916
|
-
// Safety: check if the auto-approved prompt accessed out-of-scope paths.
|
|
917
|
-
// The approval already happened in pty-manager, but we can stop the session
|
|
918
|
-
// and alert the user to prevent further damage.
|
|
919
|
-
if (isOutOfScopeAccess(promptText, taskCtx.workdir)) {
|
|
920
|
-
taskCtx.status = "error";
|
|
921
|
-
await ctx.recordDecision(taskCtx, {
|
|
922
|
-
timestamp: Date.now(),
|
|
923
|
-
event: "blocked",
|
|
924
|
-
promptText,
|
|
925
|
-
decision: "escalate",
|
|
926
|
-
reasoning: `SECURITY: Auto-response approved access outside workspace (${taskCtx.workdir}). Session stopped.`,
|
|
927
|
-
});
|
|
928
|
-
ctx.broadcast({
|
|
929
|
-
type: "escalation",
|
|
930
|
-
sessionId,
|
|
931
|
-
timestamp: Date.now(),
|
|
932
|
-
data: {
|
|
933
|
-
prompt: promptText,
|
|
934
|
-
reason: "out_of_scope_auto_approved",
|
|
935
|
-
workdir: taskCtx.workdir,
|
|
936
|
-
},
|
|
937
|
-
});
|
|
938
|
-
ctx.sendChatMessage(`[${taskCtx.label}] WARNING: Auto-approved access to path outside workspace (${taskCtx.workdir}). ` +
|
|
939
|
-
`Prompt: "${promptText.slice(0, 150)}". Stopping session for safety.`, "coding-agent");
|
|
940
|
-
// Force-kill the session to prevent further out-of-scope access
|
|
941
|
-
ctx.ptyService?.stopSession(sessionId, /* force */ true).catch((err) => {
|
|
942
|
-
ctx.log(`Failed to stop session after out-of-scope auto-approval: ${err}`);
|
|
943
|
-
});
|
|
944
|
-
return;
|
|
945
|
-
}
|
|
946
|
-
taskCtx.autoResolvedCount++;
|
|
947
|
-
await ctx.recordDecision(taskCtx, {
|
|
948
|
-
timestamp: Date.now(),
|
|
949
|
-
event: "blocked",
|
|
950
|
-
promptText,
|
|
951
|
-
decision: "auto_resolved",
|
|
952
|
-
reasoning: "Handled by auto-response rules",
|
|
953
|
-
});
|
|
954
|
-
ctx.broadcast({
|
|
955
|
-
type: "blocked_auto_resolved",
|
|
956
|
-
sessionId,
|
|
957
|
-
timestamp: Date.now(),
|
|
958
|
-
data: {
|
|
959
|
-
prompt: promptText,
|
|
960
|
-
promptType: eventData.promptInfo?.type,
|
|
961
|
-
autoResolvedCount: taskCtx.autoResolvedCount,
|
|
962
|
-
},
|
|
963
|
-
});
|
|
964
|
-
// Log auto-approvals server-side only — don't persist to chat.
|
|
965
|
-
const count = taskCtx.autoResolvedCount;
|
|
966
|
-
if (count <= 2 || count % 5 === 0) {
|
|
967
|
-
const excerpt = promptText.length > 120 ? `${promptText.slice(0, 120)}...` : promptText;
|
|
968
|
-
ctx.log(`[${taskCtx.label}] Approved: ${excerpt}`);
|
|
969
|
-
}
|
|
970
|
-
return;
|
|
971
|
-
}
|
|
972
|
-
const adapterSuggestedResponse = typeof eventData.promptInfo?.suggestedResponse === "string" &&
|
|
973
|
-
eventData.promptInfo.suggestedResponse.trim().length > 0
|
|
974
|
-
? eventData.promptInfo.suggestedResponse.trim()
|
|
975
|
-
: eventData.promptInfo?.canAutoRespond &&
|
|
976
|
-
eventData.promptInfo?.type === "permission"
|
|
977
|
-
? "keys:enter"
|
|
978
|
-
: undefined;
|
|
979
|
-
const inferredPromptResponse = inferRoutinePromptResponse(promptText, eventData.promptInfo?.type);
|
|
980
|
-
const routineSuggestedResponse = adapterSuggestedResponse ?? inferredPromptResponse?.suggestedResponse;
|
|
981
|
-
if (ctx.getSupervisionLevel() === "autonomous" &&
|
|
982
|
-
(eventData.promptInfo?.canAutoRespond || inferredPromptResponse) &&
|
|
983
|
-
routineSuggestedResponse) {
|
|
984
|
-
const fastDecision = decisionFromSuggestedResponse(routineSuggestedResponse, inferredPromptResponse?.reasoning);
|
|
985
|
-
taskCtx.autoResolvedCount++;
|
|
986
|
-
await ctx.recordDecision(taskCtx, {
|
|
987
|
-
timestamp: Date.now(),
|
|
988
|
-
event: "blocked",
|
|
989
|
-
promptText,
|
|
990
|
-
decision: "auto_resolved",
|
|
991
|
-
response: formatDecisionResponse(fastDecision),
|
|
992
|
-
reasoning: fastDecision.reasoning,
|
|
993
|
-
});
|
|
994
|
-
ctx.broadcast({
|
|
995
|
-
type: "blocked_auto_resolved",
|
|
996
|
-
sessionId,
|
|
997
|
-
timestamp: Date.now(),
|
|
998
|
-
data: {
|
|
999
|
-
prompt: promptText,
|
|
1000
|
-
promptType: eventData.promptInfo?.type,
|
|
1001
|
-
autoResolvedCount: taskCtx.autoResolvedCount,
|
|
1002
|
-
strategy: "adapter_suggested_response",
|
|
1003
|
-
},
|
|
1004
|
-
});
|
|
1005
|
-
await executeDecision(ctx, sessionId, fastDecision);
|
|
1006
|
-
return;
|
|
1007
|
-
}
|
|
1008
|
-
// Deduplicate: if an LLM decision is already in-flight for this session
|
|
1009
|
-
// AND the prompt text matches the one already being handled, skip.
|
|
1010
|
-
// TUI re-renders fire the same prompt many times; a *different* prompt
|
|
1011
|
-
// (theoretically possible if the agent resolves one prompt and immediately
|
|
1012
|
-
// hits another) should not be dropped.
|
|
1013
|
-
const promptFingerprint = promptText.slice(0, 200);
|
|
1014
|
-
if (ctx.inFlightDecisions.has(sessionId)) {
|
|
1015
|
-
if (ctx.lastBlockedPromptFingerprint.get(sessionId) === promptFingerprint) {
|
|
1016
|
-
ctx.log(`Skipping duplicate blocked event for ${taskCtx.label} (decision in-flight, same prompt)`);
|
|
1017
|
-
return;
|
|
1018
|
-
}
|
|
1019
|
-
// Different prompt — buffer it so it's replayed after the current decision completes.
|
|
1020
|
-
ctx.log(`New blocked prompt for ${taskCtx.label} while decision in-flight — buffering`);
|
|
1021
|
-
ctx.pendingBlocked.set(sessionId, data);
|
|
1022
|
-
ctx.lastBlockedPromptFingerprint.set(sessionId, promptFingerprint);
|
|
1023
|
-
return;
|
|
1024
|
-
}
|
|
1025
|
-
ctx.lastBlockedPromptFingerprint.set(sessionId, promptFingerprint);
|
|
1026
|
-
taskCtx.status = "blocked";
|
|
1027
|
-
await ctx.syncTaskContext(taskCtx);
|
|
1028
|
-
// Broadcast that the agent is blocked (for all supervision levels)
|
|
1029
|
-
ctx.broadcast({
|
|
1030
|
-
type: "blocked",
|
|
1031
|
-
sessionId,
|
|
1032
|
-
timestamp: Date.now(),
|
|
1033
|
-
data: {
|
|
1034
|
-
prompt: promptText,
|
|
1035
|
-
promptType: eventData.promptInfo?.type,
|
|
1036
|
-
supervisionLevel: ctx.getSupervisionLevel(),
|
|
1037
|
-
},
|
|
1038
|
-
});
|
|
1039
|
-
// Safety check: escalate after too many consecutive auto-responses
|
|
1040
|
-
if (taskCtx.autoResolvedCount >= MAX_AUTO_RESPONSES) {
|
|
1041
|
-
await ctx.recordDecision(taskCtx, {
|
|
1042
|
-
timestamp: Date.now(),
|
|
1043
|
-
event: "blocked",
|
|
1044
|
-
promptText,
|
|
1045
|
-
decision: "escalate",
|
|
1046
|
-
reasoning: `Escalating after ${MAX_AUTO_RESPONSES} consecutive auto-responses`,
|
|
1047
|
-
});
|
|
1048
|
-
ctx.broadcast({
|
|
1049
|
-
type: "escalation",
|
|
1050
|
-
sessionId,
|
|
1051
|
-
timestamp: Date.now(),
|
|
1052
|
-
data: {
|
|
1053
|
-
prompt: promptText,
|
|
1054
|
-
reason: "max_auto_responses_exceeded",
|
|
1055
|
-
},
|
|
1056
|
-
});
|
|
1057
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Paused for your attention after ${MAX_AUTO_RESPONSES} consecutive automatic approvals. Prompt: ${truncateForUser(promptText, 180)}`, "coding-agent");
|
|
1058
|
-
return;
|
|
1059
|
-
}
|
|
1060
|
-
// Route based on supervision level
|
|
1061
|
-
switch (ctx.getSupervisionLevel()) {
|
|
1062
|
-
case "autonomous":
|
|
1063
|
-
await handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, "", eventData.promptInfo?.type);
|
|
1064
|
-
break;
|
|
1065
|
-
case "confirm":
|
|
1066
|
-
await handleConfirmDecision(ctx, sessionId, taskCtx, promptText, "", eventData.promptInfo?.type);
|
|
1067
|
-
break;
|
|
1068
|
-
case "notify":
|
|
1069
|
-
// Notify mode — broadcast only, no action
|
|
1070
|
-
await ctx.recordDecision(taskCtx, {
|
|
1071
|
-
timestamp: Date.now(),
|
|
1072
|
-
event: "blocked",
|
|
1073
|
-
promptText,
|
|
1074
|
-
decision: "escalate",
|
|
1075
|
-
reasoning: "Supervision level is notify — broadcasting only",
|
|
1076
|
-
});
|
|
1077
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Waiting on a blocked prompt: ${truncateForUser(promptText, 180)}`, "coding-agent");
|
|
1078
|
-
break;
|
|
1079
|
-
}
|
|
1080
|
-
}
|
|
1081
|
-
// ─── Turn Completion Assessment ───
|
|
1082
|
-
/**
|
|
1083
|
-
* Handle a turn completion event. Instead of immediately stopping the session,
|
|
1084
|
-
* ask the LLM whether the overall task is done or the agent needs more turns.
|
|
1085
|
-
*/
|
|
1086
|
-
export async function handleTurnComplete(ctx, sessionId, taskCtx, data) {
|
|
1087
|
-
// Accept both "active" and "tool_running" — subagents using tools sit in
|
|
1088
|
-
// tool_running almost continuously, and we still want to run validation
|
|
1089
|
-
// when they hit task_complete. Only bail on truly terminal/blocked states.
|
|
1090
|
-
if (taskCtx.status !== "active" && taskCtx.status !== "tool_running") {
|
|
1091
|
-
return;
|
|
1092
|
-
}
|
|
1093
|
-
// If another decision (e.g. handleBlocked) is running for this session,
|
|
1094
|
-
// buffer the task_complete event so it's processed when the lock releases.
|
|
1095
|
-
// Without this, task_complete events are silently lost and sessions hang.
|
|
1096
|
-
if (ctx.inFlightDecisions.has(sessionId)) {
|
|
1097
|
-
ctx.log(`Buffering turn-complete for ${sessionId} (in-flight decision running)`);
|
|
1098
|
-
ctx.pendingTurnComplete.set(sessionId, data);
|
|
1099
|
-
return;
|
|
1100
|
-
}
|
|
1101
|
-
// Suppress turn-complete events during the post-send cooldown period.
|
|
1102
|
-
// After the coordinator sends input, the agent needs time to process it.
|
|
1103
|
-
// Without this, stall-classified "task_complete" events from stale output
|
|
1104
|
-
// trigger cascading follow-ups before the agent starts responding.
|
|
1105
|
-
if (taskCtx.lastInputSentAt) {
|
|
1106
|
-
const elapsed = Date.now() - taskCtx.lastInputSentAt;
|
|
1107
|
-
if (elapsed < POST_SEND_COOLDOWN_MS) {
|
|
1108
|
-
ctx.pendingTurnComplete.set(sessionId, data);
|
|
1109
|
-
if (!deferredTurnCompleteTimers.has(sessionId)) {
|
|
1110
|
-
const delayMs = POST_SEND_COOLDOWN_MS - elapsed + 50;
|
|
1111
|
-
const timer = setTimeout(() => {
|
|
1112
|
-
deferredTurnCompleteTimers.delete(sessionId);
|
|
1113
|
-
const pendingData = ctx.pendingTurnComplete.get(sessionId);
|
|
1114
|
-
if (!pendingData)
|
|
1115
|
-
return;
|
|
1116
|
-
const currentTask = ctx.tasks.get(sessionId);
|
|
1117
|
-
if (!currentTask ||
|
|
1118
|
-
(currentTask.status !== "active" &&
|
|
1119
|
-
currentTask.status !== "tool_running")) {
|
|
1120
|
-
ctx.pendingTurnComplete.delete(sessionId);
|
|
1121
|
-
return;
|
|
1122
|
-
}
|
|
1123
|
-
void handleTurnComplete(ctx, sessionId, currentTask, pendingData).catch((err) => {
|
|
1124
|
-
ctx.log(`Deferred turn-complete replay failed for ${sessionId}: ${err}`);
|
|
1125
|
-
});
|
|
1126
|
-
}, delayMs);
|
|
1127
|
-
deferredTurnCompleteTimers.set(sessionId, timer);
|
|
1128
|
-
}
|
|
1129
|
-
ctx.log(`Suppressing turn-complete for "${taskCtx.label}" — ` +
|
|
1130
|
-
`${Math.round(elapsed / 1000)}s since last input (cooldown ${POST_SEND_COOLDOWN_MS / 1000}s)`);
|
|
1131
|
-
return;
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
const deferredTimer = deferredTurnCompleteTimers.get(sessionId);
|
|
1135
|
-
if (deferredTimer) {
|
|
1136
|
-
clearTimeout(deferredTimer);
|
|
1137
|
-
deferredTurnCompleteTimers.delete(sessionId);
|
|
1138
|
-
}
|
|
1139
|
-
ctx.pendingTurnComplete.delete(sessionId);
|
|
1140
|
-
ctx.inFlightDecisions.add(sessionId);
|
|
1141
|
-
try {
|
|
1142
|
-
ctx.log(`Turn complete for "${taskCtx.label}" — assessing whether task is done`);
|
|
1143
|
-
// Get the turn output — prefer the captured response, fall back to PTY output
|
|
1144
|
-
const rawResponse = data.response ?? "";
|
|
1145
|
-
let turnOutput = cleanForChat(rawResponse);
|
|
1146
|
-
if (!turnOutput) {
|
|
1147
|
-
const raw = await fetchRecentOutput(ctx, sessionId);
|
|
1148
|
-
turnOutput = cleanForChat(raw);
|
|
1149
|
-
}
|
|
1150
|
-
// Fast-path: if the turn output contains a PR URL or "Created pull request",
|
|
1151
|
-
// the task is done — skip the LLM assessment entirely. The LLM (especially
|
|
1152
|
-
// Gemini Flash) tends to ignore "do not verify" instructions and sends
|
|
1153
|
-
// unnecessary verification follow-ups, adding 2-5 extra rounds per agent.
|
|
1154
|
-
// Only match explicit PR creation signals — not references to existing PRs.
|
|
1155
|
-
const PR_CREATED_RE = /(?:Created|Opened)\s+pull\s+request\s+#?\d+|gh\s+pr\s+create/i;
|
|
1156
|
-
if (PR_CREATED_RE.test(turnOutput)) {
|
|
1157
|
-
const fastDecision = {
|
|
1158
|
-
action: "complete",
|
|
1159
|
-
reasoning: "PR detected in turn output — task complete.",
|
|
1160
|
-
};
|
|
1161
|
-
ctx.log(`Turn assessment for "${taskCtx.label}": complete (fast-path: PR detected in output)`);
|
|
1162
|
-
await ctx.recordDecision(taskCtx, {
|
|
1163
|
-
timestamp: Date.now(),
|
|
1164
|
-
event: "turn_complete",
|
|
1165
|
-
promptText: "Agent finished a turn",
|
|
1166
|
-
decision: "complete",
|
|
1167
|
-
response: "",
|
|
1168
|
-
reasoning: fastDecision.reasoning,
|
|
1169
|
-
});
|
|
1170
|
-
recordKeyDecision(ctx, taskCtx.label, fastDecision);
|
|
1171
|
-
ctx.broadcast({
|
|
1172
|
-
type: "turn_assessment",
|
|
1173
|
-
sessionId,
|
|
1174
|
-
timestamp: Date.now(),
|
|
1175
|
-
data: { action: "complete", reasoning: fastDecision.reasoning },
|
|
1176
|
-
});
|
|
1177
|
-
await executeDecision(ctx, sessionId, fastDecision);
|
|
1178
|
-
return;
|
|
1179
|
-
}
|
|
1180
|
-
// Turn completions always use the fast small-LLM path.
|
|
1181
|
-
// The assessment is a structured complete/continue/escalate decision
|
|
1182
|
-
// that doesn't benefit from the full Milaidy pipeline, and routing
|
|
1183
|
-
// through it risks hangs that block the inFlightDecisions lock.
|
|
1184
|
-
let decision = null;
|
|
1185
|
-
const decisionFromPipeline = false;
|
|
1186
|
-
const prompt = buildTurnCompletePrompt(toContextSummary(taskCtx), turnOutput, toDecisionHistory(taskCtx), collectSiblings(ctx, sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
1187
|
-
try {
|
|
1188
|
-
const result = await withTrajectoryContext(ctx.runtime, {
|
|
1189
|
-
source: "orchestrator",
|
|
1190
|
-
decisionType: "turn-complete",
|
|
1191
|
-
sessionId,
|
|
1192
|
-
taskLabel: taskCtx.label,
|
|
1193
|
-
repo: taskCtx.repo,
|
|
1194
|
-
workdir: taskCtx.workdir,
|
|
1195
|
-
originalTask: taskCtx.originalTask,
|
|
1196
|
-
}, () => ctx.runtime.useModel(ModelType.TEXT_SMALL, { prompt }));
|
|
1197
|
-
decision = parseCoordinationResponse(result);
|
|
1198
|
-
}
|
|
1199
|
-
catch (err) {
|
|
1200
|
-
ctx.log(`Turn-complete LLM call failed: ${err}`);
|
|
1201
|
-
}
|
|
1202
|
-
if (!decision) {
|
|
1203
|
-
// Both paths failed — escalate so a human can decide rather than
|
|
1204
|
-
// prematurely completing unfinished work on a transient LLM failure.
|
|
1205
|
-
ctx.log(`Turn-complete for "${taskCtx.label}": all decision paths failed — escalating`);
|
|
1206
|
-
decision = {
|
|
1207
|
-
action: "escalate",
|
|
1208
|
-
reasoning: "All decision paths returned invalid response — escalating for human review",
|
|
1209
|
-
};
|
|
1210
|
-
}
|
|
1211
|
-
// Log the decision
|
|
1212
|
-
ctx.log(`Turn assessment for "${taskCtx.label}": ${decision.action}${decision.action === "respond"
|
|
1213
|
-
? ` → "${(decision.response ?? "").slice(0, 80)}"`
|
|
1214
|
-
: ""} — ${decision.reasoning.slice(0, 120)}`);
|
|
1215
|
-
// Record
|
|
1216
|
-
await ctx.recordDecision(taskCtx, {
|
|
1217
|
-
timestamp: Date.now(),
|
|
1218
|
-
event: "turn_complete",
|
|
1219
|
-
promptText: "Agent finished a turn",
|
|
1220
|
-
decision: decision.action,
|
|
1221
|
-
response: formatDecisionResponse(decision),
|
|
1222
|
-
reasoning: decision.reasoning,
|
|
1223
|
-
});
|
|
1224
|
-
// Layer 2: capture significant decisions for cross-agent sharing
|
|
1225
|
-
recordKeyDecision(ctx, taskCtx.label, decision);
|
|
1226
|
-
ctx.broadcast({
|
|
1227
|
-
type: "turn_assessment",
|
|
1228
|
-
sessionId,
|
|
1229
|
-
timestamp: Date.now(),
|
|
1230
|
-
data: {
|
|
1231
|
-
action: decision.action,
|
|
1232
|
-
reasoning: decision.reasoning,
|
|
1233
|
-
},
|
|
1234
|
-
});
|
|
1235
|
-
if (ctx.pendingBlocked.has(sessionId)) {
|
|
1236
|
-
ctx.log(`Deferring turn assessment execution for "${taskCtx.label}" because a newer blocked prompt arrived during assessment`);
|
|
1237
|
-
ctx.pendingTurnComplete.set(sessionId, data);
|
|
1238
|
-
return;
|
|
1239
|
-
}
|
|
1240
|
-
// Send chat message for small-LLM decisions only.
|
|
1241
|
-
// When Milaidy's pipeline handled it, she already spoke via WS broadcast.
|
|
1242
|
-
if (!decisionFromPipeline) {
|
|
1243
|
-
if (decision.action === "respond") {
|
|
1244
|
-
const instruction = decision.response ?? "";
|
|
1245
|
-
const preview = instruction.length > 120
|
|
1246
|
-
? `${instruction.slice(0, 120)}...`
|
|
1247
|
-
: instruction;
|
|
1248
|
-
ctx.log(`[${taskCtx.label}] Turn done, continuing: ${preview}`);
|
|
1249
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Continuing work: ${preview || "sent follow-up instructions."}`, "coding-agent");
|
|
1250
|
-
}
|
|
1251
|
-
else if (decision.action === "escalate") {
|
|
1252
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Turn finished — needs your attention: ${decision.reasoning}`, "coding-agent");
|
|
1253
|
-
}
|
|
1254
|
-
}
|
|
1255
|
-
// "complete" chat message is handled by executeDecision
|
|
1256
|
-
await executeDecision(ctx, sessionId, decision);
|
|
1257
|
-
}
|
|
1258
|
-
finally {
|
|
1259
|
-
ctx.inFlightDecisions.delete(sessionId);
|
|
1260
|
-
await drainPendingBlocked(ctx, sessionId);
|
|
1261
|
-
await drainPendingTurnComplete(ctx, sessionId);
|
|
1262
|
-
}
|
|
1263
|
-
}
|
|
1264
|
-
// ─── Autonomous / Confirm Decision Flows ───
|
|
1265
|
-
/**
|
|
1266
|
-
* Handle an autonomous decision for a blocked session — call the LLM and execute immediately.
|
|
1267
|
-
*/
|
|
1268
|
-
export async function handleAutonomousDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
1269
|
-
// Debounce: skip if decision already in-flight for this session
|
|
1270
|
-
if (ctx.inFlightDecisions.has(sessionId)) {
|
|
1271
|
-
ctx.log(`Skipping duplicate decision for ${sessionId} (in-flight)`);
|
|
1272
|
-
return;
|
|
1273
|
-
}
|
|
1274
|
-
ctx.inFlightDecisions.add(sessionId);
|
|
1275
|
-
try {
|
|
1276
|
-
// Get recent output from PTY if not provided
|
|
1277
|
-
let output = recentOutput;
|
|
1278
|
-
if (!output) {
|
|
1279
|
-
output = await fetchRecentOutput(ctx, sessionId);
|
|
1280
|
-
}
|
|
1281
|
-
// Triage: route to small LLM (routine) or Milaidy pipeline (creative).
|
|
1282
|
-
// Track source so we skip duplicate chat messages when Milaidy already spoke.
|
|
1283
|
-
const agentDecisionCb = ctx.getAgentDecisionCallback();
|
|
1284
|
-
let decision = null;
|
|
1285
|
-
let decisionFromPipeline = false;
|
|
1286
|
-
const triageCtx = {
|
|
1287
|
-
eventType: "blocked",
|
|
1288
|
-
promptText,
|
|
1289
|
-
promptType,
|
|
1290
|
-
recentOutput: output,
|
|
1291
|
-
originalTask: taskCtx.originalTask,
|
|
1292
|
-
};
|
|
1293
|
-
const tier = agentDecisionCb
|
|
1294
|
-
? await classifyEventTier(ctx.runtime, triageCtx, ctx.log)
|
|
1295
|
-
: "routine"; // No pipeline → always small LLM
|
|
1296
|
-
if (tier === "routine") {
|
|
1297
|
-
decision = await makeCoordinationDecision(ctx, taskCtx, promptText, output);
|
|
1298
|
-
}
|
|
1299
|
-
else {
|
|
1300
|
-
// Creative — try Milaidy pipeline, fall back to small LLM
|
|
1301
|
-
if (agentDecisionCb) {
|
|
1302
|
-
const eventMessage = buildBlockedEventMessage(toContextSummary(taskCtx), promptText, output, toDecisionHistory(taskCtx), collectSiblings(ctx, sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
1303
|
-
try {
|
|
1304
|
-
decision = await withTimeout(agentDecisionCb(eventMessage, sessionId, taskCtx), DECISION_CB_TIMEOUT_MS, "agentDecisionCb");
|
|
1305
|
-
if (decision)
|
|
1306
|
-
decisionFromPipeline = true;
|
|
1307
|
-
}
|
|
1308
|
-
catch (err) {
|
|
1309
|
-
ctx.log(`Agent decision callback failed: ${err} — falling back to small LLM`);
|
|
1310
|
-
}
|
|
1311
|
-
}
|
|
1312
|
-
if (!decision) {
|
|
1313
|
-
decision = await makeCoordinationDecision(ctx, taskCtx, promptText, output);
|
|
1314
|
-
}
|
|
1315
|
-
}
|
|
1316
|
-
if (!decision) {
|
|
1317
|
-
// All decision paths returned invalid response — escalate
|
|
1318
|
-
await ctx.recordDecision(taskCtx, {
|
|
1319
|
-
timestamp: Date.now(),
|
|
1320
|
-
event: "blocked",
|
|
1321
|
-
promptText,
|
|
1322
|
-
decision: "escalate",
|
|
1323
|
-
reasoning: "All decision paths returned invalid coordination response",
|
|
1324
|
-
});
|
|
1325
|
-
ctx.broadcast({
|
|
1326
|
-
type: "escalation",
|
|
1327
|
-
sessionId,
|
|
1328
|
-
timestamp: Date.now(),
|
|
1329
|
-
data: {
|
|
1330
|
-
prompt: promptText,
|
|
1331
|
-
reason: "invalid_llm_response",
|
|
1332
|
-
},
|
|
1333
|
-
});
|
|
1334
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Needs your attention: the coordinator could not decide how to handle "${truncateForUser(promptText, 160)}".`, "coding-agent");
|
|
1335
|
-
return;
|
|
1336
|
-
}
|
|
1337
|
-
// Guard: decline + redirect if the prompt references out-of-scope paths.
|
|
1338
|
-
// Instead of stalling via escalate, tell the agent "no" and point it to the
|
|
1339
|
-
// workspace. Also notify the human in case broader access was intended.
|
|
1340
|
-
if (decision.action === "respond" &&
|
|
1341
|
-
isOutOfScopeAccess(promptText, taskCtx.workdir)) {
|
|
1342
|
-
decision = {
|
|
1343
|
-
action: "respond",
|
|
1344
|
-
response: `No — that path is outside your workspace. Use ${taskCtx.workdir} instead. Create any files or directories you need there.`,
|
|
1345
|
-
reasoning: `Declined out-of-scope access (outside ${taskCtx.workdir}) and redirected agent to workspace.`,
|
|
1346
|
-
};
|
|
1347
|
-
// Surface to human so they can grant broader access if intended
|
|
1348
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Declined out-of-scope access and redirected to workspace (${taskCtx.workdir}). If you intended broader access, send the agent an override.`, "coding-agent");
|
|
1349
|
-
}
|
|
1350
|
-
// Record the decision
|
|
1351
|
-
taskCtx.autoResolvedCount = 0;
|
|
1352
|
-
await ctx.recordDecision(taskCtx, {
|
|
1353
|
-
timestamp: Date.now(),
|
|
1354
|
-
event: "blocked",
|
|
1355
|
-
promptText,
|
|
1356
|
-
decision: decision.action,
|
|
1357
|
-
response: formatDecisionResponse(decision),
|
|
1358
|
-
reasoning: decision.reasoning,
|
|
1359
|
-
});
|
|
1360
|
-
// Layer 2: capture significant decisions for cross-agent sharing
|
|
1361
|
-
recordKeyDecision(ctx, taskCtx.label, decision);
|
|
1362
|
-
// Broadcast the decision
|
|
1363
|
-
ctx.broadcast({
|
|
1364
|
-
type: "coordination_decision",
|
|
1365
|
-
sessionId,
|
|
1366
|
-
timestamp: Date.now(),
|
|
1367
|
-
data: {
|
|
1368
|
-
action: decision.action,
|
|
1369
|
-
response: decision.response,
|
|
1370
|
-
useKeys: decision.useKeys,
|
|
1371
|
-
keys: decision.keys,
|
|
1372
|
-
reasoning: decision.reasoning,
|
|
1373
|
-
},
|
|
1374
|
-
});
|
|
1375
|
-
// Send chat message for small-LLM decisions only.
|
|
1376
|
-
// When Milaidy's pipeline handled it, she already spoke via WS broadcast.
|
|
1377
|
-
if (!decisionFromPipeline) {
|
|
1378
|
-
if (decision.action === "respond") {
|
|
1379
|
-
const actionDesc = decision.useKeys
|
|
1380
|
-
? `Sent keys: ${decision.keys?.join(", ")}`
|
|
1381
|
-
: decision.response
|
|
1382
|
-
? `Responded: ${decision.response.length > 100 ? `${decision.response.slice(0, 100)}...` : decision.response}`
|
|
1383
|
-
: "Responded";
|
|
1384
|
-
const reasonExcerpt = decision.reasoning.length > 150
|
|
1385
|
-
? `${decision.reasoning.slice(0, 150)}...`
|
|
1386
|
-
: decision.reasoning;
|
|
1387
|
-
ctx.log(`[${taskCtx.label}] ${actionDesc} — ${reasonExcerpt}`);
|
|
1388
|
-
}
|
|
1389
|
-
else if (decision.action === "escalate") {
|
|
1390
|
-
ctx.sendChatMessage(`[${taskCtx.label}] Needs your attention: ${decision.reasoning}`, "coding-agent");
|
|
1391
|
-
}
|
|
1392
|
-
}
|
|
1393
|
-
// Execute
|
|
1394
|
-
await executeDecision(ctx, sessionId, decision);
|
|
1395
|
-
}
|
|
1396
|
-
finally {
|
|
1397
|
-
ctx.inFlightDecisions.delete(sessionId);
|
|
1398
|
-
await drainPendingBlocked(ctx, sessionId);
|
|
1399
|
-
await drainPendingTurnComplete(ctx, sessionId);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
/**
|
|
1403
|
-
* Handle a confirm-mode decision — call LLM, then queue for human approval.
|
|
1404
|
-
*/
|
|
1405
|
-
export async function handleConfirmDecision(ctx, sessionId, taskCtx, promptText, recentOutput, promptType) {
|
|
1406
|
-
// Debounce
|
|
1407
|
-
if (ctx.inFlightDecisions.has(sessionId))
|
|
1408
|
-
return;
|
|
1409
|
-
ctx.inFlightDecisions.add(sessionId);
|
|
1410
|
-
try {
|
|
1411
|
-
let output = recentOutput;
|
|
1412
|
-
if (!output) {
|
|
1413
|
-
output = await fetchRecentOutput(ctx, sessionId);
|
|
1414
|
-
}
|
|
1415
|
-
// Triage: route to small LLM (routine) or Milaidy pipeline (creative)
|
|
1416
|
-
const agentDecisionCb = ctx.getAgentDecisionCallback();
|
|
1417
|
-
let decision = null;
|
|
1418
|
-
let decisionFromPipeline = false;
|
|
1419
|
-
const triageCtx = {
|
|
1420
|
-
eventType: "blocked",
|
|
1421
|
-
promptText,
|
|
1422
|
-
promptType,
|
|
1423
|
-
recentOutput: output,
|
|
1424
|
-
originalTask: taskCtx.originalTask,
|
|
1425
|
-
};
|
|
1426
|
-
const tier = agentDecisionCb
|
|
1427
|
-
? await classifyEventTier(ctx.runtime, triageCtx, ctx.log)
|
|
1428
|
-
: "routine"; // No pipeline → always small LLM
|
|
1429
|
-
if (tier === "routine") {
|
|
1430
|
-
decision = await makeCoordinationDecision(ctx, taskCtx, promptText, output);
|
|
1431
|
-
}
|
|
1432
|
-
else {
|
|
1433
|
-
// Creative — try Milaidy pipeline, fall back to small LLM
|
|
1434
|
-
if (agentDecisionCb) {
|
|
1435
|
-
const eventMessage = buildBlockedEventMessage(toContextSummary(taskCtx), promptText, output, toDecisionHistory(taskCtx), collectSiblings(ctx, sessionId), ctx.sharedDecisions, ctx.getSwarmContext());
|
|
1436
|
-
try {
|
|
1437
|
-
decision = await withTimeout(agentDecisionCb(eventMessage, sessionId, taskCtx), DECISION_CB_TIMEOUT_MS, "agentDecisionCb");
|
|
1438
|
-
if (decision)
|
|
1439
|
-
decisionFromPipeline = true;
|
|
1440
|
-
}
|
|
1441
|
-
catch (err) {
|
|
1442
|
-
ctx.log(`Agent decision callback failed (confirm): ${err} — falling back to small LLM`);
|
|
1443
|
-
}
|
|
1444
|
-
}
|
|
1445
|
-
if (!decision) {
|
|
1446
|
-
decision = await makeCoordinationDecision(ctx, taskCtx, promptText, output);
|
|
1447
|
-
}
|
|
1448
|
-
}
|
|
1449
|
-
if (!decision) {
|
|
1450
|
-
// Queue for human with no suggestion
|
|
1451
|
-
taskCtx.status = "blocked";
|
|
1452
|
-
await ctx.syncTaskContext(taskCtx);
|
|
1453
|
-
const pendingDecision = {
|
|
1454
|
-
sessionId,
|
|
1455
|
-
promptText,
|
|
1456
|
-
recentOutput: output,
|
|
1457
|
-
llmDecision: {
|
|
1458
|
-
action: "escalate",
|
|
1459
|
-
reasoning: "All decision paths returned invalid response — needs human review",
|
|
1460
|
-
},
|
|
1461
|
-
taskContext: taskCtx,
|
|
1462
|
-
createdAt: Date.now(),
|
|
1463
|
-
};
|
|
1464
|
-
ctx.pendingDecisions.set(sessionId, pendingDecision);
|
|
1465
|
-
await ctx.taskRegistry.upsertPendingDecision({
|
|
1466
|
-
sessionId,
|
|
1467
|
-
threadId: taskCtx.threadId,
|
|
1468
|
-
promptText,
|
|
1469
|
-
recentOutput: output,
|
|
1470
|
-
llmDecision: pendingDecision.llmDecision,
|
|
1471
|
-
taskContext: taskCtx,
|
|
1472
|
-
createdAt: pendingDecision.createdAt,
|
|
1473
|
-
});
|
|
1474
|
-
}
|
|
1475
|
-
else {
|
|
1476
|
-
// Queue the LLM's suggestion for human approval
|
|
1477
|
-
taskCtx.status = "blocked";
|
|
1478
|
-
await ctx.syncTaskContext(taskCtx);
|
|
1479
|
-
const pendingDecision = {
|
|
1480
|
-
sessionId,
|
|
1481
|
-
promptText,
|
|
1482
|
-
recentOutput: output,
|
|
1483
|
-
llmDecision: decision,
|
|
1484
|
-
taskContext: taskCtx,
|
|
1485
|
-
createdAt: Date.now(),
|
|
1486
|
-
};
|
|
1487
|
-
ctx.pendingDecisions.set(sessionId, pendingDecision);
|
|
1488
|
-
await ctx.taskRegistry.upsertPendingDecision({
|
|
1489
|
-
sessionId,
|
|
1490
|
-
threadId: taskCtx.threadId,
|
|
1491
|
-
promptText,
|
|
1492
|
-
recentOutput: output,
|
|
1493
|
-
llmDecision: decision,
|
|
1494
|
-
taskContext: taskCtx,
|
|
1495
|
-
createdAt: pendingDecision.createdAt,
|
|
1496
|
-
});
|
|
1497
|
-
}
|
|
1498
|
-
await ctx.taskRegistry.appendEvent({
|
|
1499
|
-
threadId: taskCtx.threadId,
|
|
1500
|
-
sessionId,
|
|
1501
|
-
eventType: "pending_confirmation",
|
|
1502
|
-
summary: `Queued human confirmation for "${taskCtx.label}"`,
|
|
1503
|
-
data: {
|
|
1504
|
-
promptText,
|
|
1505
|
-
suggestedAction: decision?.action ?? "escalate",
|
|
1506
|
-
},
|
|
1507
|
-
});
|
|
1508
|
-
// When Milaidy's pipeline made the suggestion, she already spoke via WS broadcast.
|
|
1509
|
-
// Only broadcast the pending_confirmation event for small-LLM suggestions or
|
|
1510
|
-
// always broadcast it (the UI needs it regardless) but skip any chat messages.
|
|
1511
|
-
ctx.broadcast({
|
|
1512
|
-
type: "pending_confirmation",
|
|
1513
|
-
sessionId,
|
|
1514
|
-
timestamp: Date.now(),
|
|
1515
|
-
data: {
|
|
1516
|
-
prompt: promptText,
|
|
1517
|
-
suggestedAction: decision?.action,
|
|
1518
|
-
suggestedResponse: decision?.response,
|
|
1519
|
-
reasoning: decision?.reasoning,
|
|
1520
|
-
fromPipeline: decisionFromPipeline,
|
|
1521
|
-
},
|
|
1522
|
-
});
|
|
1523
|
-
ctx.sendChatMessage([
|
|
1524
|
-
`[${taskCtx.label}] Waiting for your approval: ${truncateForUser(promptText, 180)}`,
|
|
1525
|
-
formatSuggestedAction(decision),
|
|
1526
|
-
decision?.reasoning
|
|
1527
|
-
? `Reason: ${truncateForUser(decision.reasoning, 180)}`
|
|
1528
|
-
: "",
|
|
1529
|
-
]
|
|
1530
|
-
.filter(Boolean)
|
|
1531
|
-
.join(" "), "coding-agent");
|
|
1532
|
-
}
|
|
1533
|
-
finally {
|
|
1534
|
-
ctx.inFlightDecisions.delete(sessionId);
|
|
1535
|
-
await drainPendingTurnComplete(ctx, sessionId);
|
|
1536
|
-
await drainPendingBlocked(ctx, sessionId);
|
|
1537
|
-
}
|
|
1538
|
-
}
|