@shepai/cli 1.175.1-pr537.fc6a92c → 1.176.0
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/apis/json-schema/AgentConfig.yaml +0 -3
- package/apis/json-schema/AgentType.yaml +0 -1
- package/dist/packages/core/src/application/ports/output/agents/agent-executor.interface.d.ts +1 -3
- package/dist/packages/core/src/application/ports/output/agents/agent-executor.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/agents/agent-run-repository.interface.d.ts +0 -7
- package/dist/packages/core/src/application/ports/output/agents/agent-run-repository.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/agents/phase-timing-repository.interface.d.ts +0 -7
- package/dist/packages/core/src/application/ports/output/agents/phase-timing-repository.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/services/index.d.ts +0 -3
- package/dist/packages/core/src/application/ports/output/services/index.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/get-agent-session.use-case.d.ts +1 -3
- package/dist/packages/core/src/application/use-cases/agents/get-agent-session.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/get-agent-session.use-case.js +4 -6
- package/dist/packages/core/src/application/use-cases/agents/list-agent-sessions.use-case.d.ts +1 -3
- package/dist/packages/core/src/application/use-cases/agents/list-agent-sessions.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/agents/list-agent-sessions.use-case.js +4 -6
- package/dist/packages/core/src/application/use-cases/agents/reject-agent-run.use-case.js +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts +1 -3
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/create/create-feature.use-case.js +7 -9
- package/dist/packages/core/src/application/use-cases/features/rebase-feature-on-main.use-case.js +2 -2
- package/dist/packages/core/src/application/use-cases/settings/check-onboarding-status.use-case.d.ts +2 -5
- package/dist/packages/core/src/application/use-cases/settings/check-onboarding-status.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/settings/check-onboarding-status.use-case.js +6 -28
- package/dist/packages/core/src/domain/generated/output.d.ts +35 -42
- package/dist/packages/core/src/domain/generated/output.d.ts.map +1 -1
- package/dist/packages/core/src/domain/generated/output.js +1 -7
- package/dist/packages/core/src/infrastructure/di/container.d.ts +0 -3
- package/dist/packages/core/src/infrastructure/di/container.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/di/container.js +501 -27
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/agent-run.mapper.js +2 -2
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts +0 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/mappers/settings.mapper.js +2 -6
- package/dist/packages/core/src/infrastructure/repositories/agent-run.repository.d.ts +0 -1
- package/dist/packages/core/src/infrastructure/repositories/agent-run.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/agent-run.repository.js +0 -8
- package/dist/packages/core/src/infrastructure/repositories/sqlite-phase-timing.repository.d.ts +0 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-phase-timing.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-phase-timing.repository.js +3 -11
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/repositories/sqlite-settings.repository.js +2 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +0 -10
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-runner.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-runner.service.js +4 -4
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/claude-code-executor.service.js +35 -19
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.d.ts +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/codex-cli-executor.service.js +30 -17
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.d.ts +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/copilot-cli-executor.service.js +34 -23
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/cursor-executor.service.js +16 -21
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.d.ts +7 -3
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/gemini-cli-executor.service.js +33 -21
- package/dist/packages/core/src/infrastructure/services/agents/common/types.d.ts +0 -5
- package/dist/packages/core/src/infrastructure/services/agents/common/types.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/types.js +1 -5
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-graph.d.ts +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/feature-agent-process.service.js +1 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/external/github-repository.service.js +7 -16
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts +47 -44
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/git-pr.service.js +853 -121
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts +70 -19
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js +991 -44
- package/dist/packages/core/src/infrastructure/services/notifications/notification-watcher.service.js +3 -3
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +1 -1
- package/dist/src/presentation/cli/commands/agent/show.command.js +2 -3
- package/dist/src/presentation/cli/commands/feat/new.command.js +1 -1
- package/dist/src/presentation/cli/commands/feat/show.command.js +1 -1
- package/dist/src/presentation/tui/prompts/agent-select.prompt.d.ts.map +1 -1
- package/dist/src/presentation/tui/prompts/agent-select.prompt.js +0 -5
- package/dist/src/presentation/web/app/actions/agent-setup-flag.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/agent-setup-flag.js +2 -3
- package/dist/src/presentation/web/app/actions/check-agent-auth.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/check-agent-auth.js +2 -18
- package/dist/src/presentation/web/app/actions/get-all-agent-models.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-all-agent-models.js +0 -2
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +3 -4
- package/dist/src/presentation/web/app/actions/get-supported-models.js +3 -2
- package/dist/src/presentation/web/app/actions/get-workflow-defaults.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-workflow-defaults.js +2 -3
- package/dist/src/presentation/web/app/actions/open-ide.js +3 -2
- package/dist/src/presentation/web/app/actions/open-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/open-shell.js +0 -15
- package/dist/src/presentation/web/app/actions/update-model.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/update-model.js +2 -3
- package/dist/src/presentation/web/app/api/agent-events/health/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/health/route.js +12 -9
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts +14 -7
- package/dist/src/presentation/web/app/api/agent-events/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/agent-events/route.js +301 -20
- package/dist/src/presentation/web/app/api/attachments/preview/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/attachments/preview/route.js +1 -5
- package/dist/src/presentation/web/app/api/attachments/upload/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/attachments/upload/route.js +2 -2
- package/dist/src/presentation/web/app/api/attachments/upload-from-path/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/attachments/upload-from-path/route.js +2 -2
- package/dist/src/presentation/web/app/api/cli-upgrade/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/cli-upgrade/route.js +1 -3
- package/dist/src/presentation/web/app/api/deployment-logs/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/deployment-logs/route.js +6 -2
- package/dist/src/presentation/web/app/api/dialog/pick-files/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/dialog/pick-files/route.js +2 -3
- package/dist/src/presentation/web/app/api/directory/list/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/directory/list/route.js +5 -8
- package/dist/src/presentation/web/app/api/feature-logs/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/feature-logs/route.js +6 -2
- package/dist/src/presentation/web/app/api/graph-data/route.d.ts +4 -1
- package/dist/src/presentation/web/app/api/graph-data/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/graph-data/route.js +2 -8
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/mark-read/route.js +3 -2
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/messages/route.js +10 -5
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/respond/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/respond/route.js +5 -5
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stop/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stop/route.js +3 -2
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stream/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/[featureId]/stream/route.js +6 -2
- package/dist/src/presentation/web/app/api/interactive/chat/turn-statuses/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/chat/turn-statuses/route.js +3 -2
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/messages/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/messages/route.js +10 -5
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/route.js +6 -3
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/stream/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/sessions/[id]/stream/route.js +6 -2
- package/dist/src/presentation/web/app/api/interactive/sessions/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/interactive/sessions/route.js +3 -2
- package/dist/src/presentation/web/app/api/npm-version/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/npm-version/route.js +2 -2
- package/dist/src/presentation/web/app/api/sessions/route.d.ts +15 -1
- package/dist/src/presentation/web/app/api/sessions/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/sessions/route.js +3 -2
- package/dist/src/presentation/web/app/api/sessions-batch/route.d.ts +8 -1
- package/dist/src/presentation/web/app/api/sessions-batch/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/sessions-batch/route.js +3 -2
- package/dist/src/presentation/web/app/api/tools/[id]/install/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/tools/[id]/install/route.js +2 -2
- package/dist/src/presentation/web/app/api/tools/[id]/install/stream/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/tools/[id]/install/stream/route.js +1 -3
- package/dist/src/presentation/web/app/api/tools/[id]/launch/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/tools/[id]/launch/route.js +2 -2
- package/dist/src/presentation/web/app/api/tools/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/tools/route.js +2 -2
- package/dist/src/presentation/web/app/layout.d.ts.map +1 -1
- package/dist/src/presentation/web/app/layout.js +1 -2
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +0 -12
- package/dist/src/presentation/web/components/common/control-center-drawer/adopt-branch-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/control-center-drawer/adopt-branch-drawer.js +2 -2
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/drawer-action-bar/drawer-action-bar.js +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +1 -1
- package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts +1 -1
- package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.js +0 -2
- package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-node/agent-type-icons.stories.js +0 -1
- package/dist/src/presentation/web/components/features/chat/ChatSheet.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/chat/ChatSheet.js +1 -1
- package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/AgentModelPicker/index.js +3 -7
- package/dist/src/presentation/web/components/features/settings/ModelPicker/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/ModelPicker/index.js +2 -2
- package/dist/src/presentation/web/components/features/settings/agent-settings-section.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/settings/agent-settings-section.js +0 -1
- package/dist/src/presentation/web/hooks/use-agent-events.js +1 -5
- package/dist/src/presentation/web/lib/is-same-shep-instance.d.ts.map +1 -1
- package/dist/src/presentation/web/lib/is-same-shep-instance.js +5 -2
- package/dist/translations/ar/common.json +1 -0
- package/dist/translations/ar/tui.json +0 -4
- package/dist/translations/ar/web.json +0 -1
- package/dist/translations/de/common.json +1 -0
- package/dist/translations/de/tui.json +0 -1
- package/dist/translations/de/web.json +0 -1
- package/dist/translations/en/common.json +1 -0
- package/dist/translations/en/tui.json +0 -4
- package/dist/translations/en/web.json +0 -1
- package/dist/translations/es/common.json +1 -0
- package/dist/translations/es/tui.json +0 -4
- package/dist/translations/es/web.json +0 -1
- package/dist/translations/fr/common.json +1 -0
- package/dist/translations/fr/tui.json +0 -4
- package/dist/translations/fr/web.json +0 -1
- package/dist/translations/he/common.json +1 -0
- package/dist/translations/he/tui.json +0 -4
- package/dist/translations/he/web.json +0 -1
- package/dist/translations/pt/common.json +1 -0
- package/dist/translations/pt/tui.json +0 -4
- package/dist/translations/pt/web.json +0 -1
- package/dist/translations/ru/common.json +1 -0
- package/dist/translations/ru/tui.json +0 -4
- package/dist/translations/ru/web.json +0 -1
- package/dist/translations/uk/cli.json +631 -0
- package/dist/translations/uk/common.json +56 -0
- package/dist/translations/uk/tui.json +134 -0
- package/dist/translations/uk/web.json +615 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +3 -7
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +2 -2
- package/web/.next/required-server-files.json +2 -2
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +58 -73
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page/server-reference-manifest.json +54 -69
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +60 -75
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +76 -91
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +76 -91
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +56 -71
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +56 -71
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/chat/page/server-reference-manifest.json +54 -69
- package/web/.next/server/app/(dashboard)/chat/page.js +5 -5
- package/web/.next/server/app/(dashboard)/chat/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/chat/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +60 -75
- package/web/.next/server/app/(dashboard)/create/page.js +5 -5
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +76 -91
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +76 -91
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +54 -69
- package/web/.next/server/app/(dashboard)/page.js +5 -5
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page/server-reference-manifest.json +56 -71
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +56 -71
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js +5 -5
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error/page.js +1 -1
- package/web/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +12 -27
- package/web/.next/server/app/_not-found/page.js +3 -3
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/agent-events/route.js +2 -2
- package/web/.next/server/app/api/agent-events/route.js.nft.json +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/attachments/upload/route.js +1 -1
- package/web/.next/server/app/api/attachments/upload/route.js.nft.json +1 -1
- package/web/.next/server/app/api/attachments/upload-from-path/route.js +1 -1
- package/web/.next/server/app/api/attachments/upload-from-path/route.js.nft.json +1 -1
- package/web/.next/server/app/api/deployment-logs/route.js +1 -2
- package/web/.next/server/app/api/deployment-logs/route.js.nft.json +1 -1
- package/web/.next/server/app/api/directory/list/route.js +1 -1
- package/web/.next/server/app/api/directory/list/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/feature-logs/route.js +1 -2
- package/web/.next/server/app/api/feature-logs/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route.js +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/mark-read/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/messages/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route.js +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/respond/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/stop/route.js +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/stop/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/[featureId]/stream/route.js +1 -2
- package/web/.next/server/app/api/interactive/chat/[featureId]/stream/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/chat/turn-statuses/route.js +1 -1
- package/web/.next/server/app/api/interactive/chat/turn-statuses/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/sessions/[id]/messages/route.js +1 -1
- package/web/.next/server/app/api/interactive/sessions/[id]/messages/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/sessions/[id]/route.js +1 -1
- package/web/.next/server/app/api/interactive/sessions/[id]/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/sessions/[id]/stream/route.js +1 -2
- package/web/.next/server/app/api/interactive/sessions/[id]/stream/route.js.nft.json +1 -1
- package/web/.next/server/app/api/interactive/sessions/route.js +1 -1
- package/web/.next/server/app/api/interactive/sessions/route.js.nft.json +1 -1
- package/web/.next/server/app/api/npm-version/route.js +1 -1
- package/web/.next/server/app/api/npm-version/route.js.nft.json +1 -1
- package/web/.next/server/app/api/sessions/route.js +1 -1
- package/web/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/web/.next/server/app/api/sessions-batch/route.js +1 -1
- package/web/.next/server/app/api/sessions-batch/route.js.nft.json +1 -1
- package/web/.next/server/app/api/tools/[id]/install/route.js +1 -1
- package/web/.next/server/app/api/tools/[id]/install/route.js.nft.json +1 -1
- package/web/.next/server/app/api/tools/[id]/launch/route.js +1 -1
- package/web/.next/server/app/api/tools/[id]/launch/route.js.nft.json +1 -1
- package/web/.next/server/app/api/tools/route.js +1 -1
- package/web/.next/server/app/api/tools/route.js.nft.json +1 -1
- package/web/.next/server/app/features/page/server-reference-manifest.json +12 -27
- package/web/.next/server/app/features/page.js +3 -3
- package/web/.next/server/app/features/page.js.nft.json +1 -1
- package/web/.next/server/app/features/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +18 -33
- package/web/.next/server/app/settings/page.js +3 -4
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +26 -41
- package/web/.next/server/app/skills/page.js +4 -4
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +22 -37
- package/web/.next/server/app/tools/page.js +4 -4
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +12 -27
- package/web/.next/server/app/version/page.js +4 -4
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_370c43b1.js.map +1 -1
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js +12 -0
- package/web/.next/server/chunks/403f9_next_dist_esm_build_templates_app-route_4d623b8e.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__0866d2b5._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__10852c5c._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__10852c5c._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__2b1074db._.js +12 -0
- package/web/.next/server/chunks/[root-of-the-server]__2b1074db._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__2b71641f._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__2b71641f._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__2bb675ff._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__2bb675ff._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__2f61738a._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__2f61738a._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__31598852._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__31598852._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__31944fa2._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__31944fa2._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__32b04219._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__32b04219._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__332c8d91._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__3b72e8b0._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__4408a5ba._.js +12 -0
- package/web/.next/server/chunks/[root-of-the-server]__4408a5ba._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__6565a045._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__6565a045._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__8a281f8d._.js +24 -0
- package/web/.next/server/chunks/[root-of-the-server]__8a281f8d._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__8f8d6afe._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__8f8d6afe._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__9191749c._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__9191749c._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js +9 -0
- package/web/.next/server/chunks/[root-of-the-server]__9a136c79._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__ab4951b1._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__ab4951b1._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__acea6565._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__acea6565._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__b2f9a412._.js +3 -0
- package/web/.next/server/chunks/{[root-of-the-server]__f1aeae12._.js.map → [root-of-the-server]__b2f9a412._.js.map} +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__b4102cc7._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__c78383b1._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__cd67a84c._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js +3 -3
- package/web/.next/server/chunks/[root-of-the-server]__d2c18946._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__d9d410a8._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__d9d410a8._.js.map +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js +3 -3
- package/web/.next/server/chunks/[root-of-the-server]__e247a485._.js.map +1 -1
- package/web/.next/server/chunks/{[root-of-the-server]__937ba94e._.js → [root-of-the-server]__e3692208._.js} +2 -2
- package/web/.next/server/chunks/[root-of-the-server]__ea653642._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__ea653642._.js.map +1 -0
- package/web/.next/server/chunks/[root-of-the-server]__fc6fd958._.js +3 -0
- package/web/.next/server/chunks/[root-of-the-server]__fc6fd958._.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_ad0071c9.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_90d98b2b.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js +3 -0
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_d3828105.js.map +1 -0
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js +2 -2
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_feature-drawer-client_tsx_e9755fc8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1cd4327c._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1f389e5d._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__08e7a080._.js → [root-of-the-server]__22d17c66._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__08e7a080._.js.map → [root-of-the-server]__22d17c66._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__23b5ca2c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__ff332bfb._.js.map → [root-of-the-server]__357d99f9._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__51ec77a8._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__540c615f._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__66047a1b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__16c1388b._.js → [root-of-the-server]__69dd3217._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__16c1388b._.js.map → [root-of-the-server]__69dd3217._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6c7d3936._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__7528eb6f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__a932cd3a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aa72e794._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b7b96453._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d1040bd1._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__f5614810._.js.map → [root-of-the-server]__d1040bd1._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__efeeaed4._.js +3 -0
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__d5e22d1a._.js.map → [root-of-the-server]__efeeaed4._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js +1 -1
- package/web/.next/server/chunks/ssr/_05c23ad9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js +1 -1
- package/web/.next/server/chunks/ssr/_16eb4fec._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_5747febb._.js → _1e08a336._.js} +2 -2
- package/web/.next/server/chunks/ssr/_1e08a336._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_ed2f2799._.js → _295fffde._.js} +2 -2
- package/web/.next/server/chunks/ssr/_295fffde._.js.map +1 -0
- package/web/.next/server/chunks/ssr/{_4db4ac1e._.js → _388d1127._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_4db4ac1e._.js.map → _388d1127._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_45496654._.js +1 -1
- package/web/.next/server/chunks/ssr/_45496654._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js +1 -1
- package/web/.next/server/chunks/ssr/_4cbb7f95._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js +1 -1
- package/web/.next/server/chunks/ssr/_56b9d60f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6abfa39e._.js +1 -1
- package/web/.next/server/chunks/ssr/_6abfa39e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_080b0309._.js → _8f0d3f07._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_080b0309._.js.map → _8f0d3f07._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_31b68712._.js → _98d94927._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_31b68712._.js.map → _98d94927._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/{_819f193a._.js → _d9c0a97a._.js} +2 -2
- package/web/.next/server/chunks/ssr/_d9c0a97a._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_e680c57c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f8c55130._.js +1 -1
- package/web/.next/server/chunks/ssr/_f8c55130._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js +1 -1
- package/web/.next/server/chunks/ssr/f3a1f_components_common_control-center-drawer_repository-drawer-client_tsx_39a00c03._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_17d39233._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_54b02639._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js +5 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_7b7b9e3b._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_807cba76._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_90b5e66e.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_4ce30db7.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_e4032193.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_app_actions_open-ide_ts_baaca5d5._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{src_presentation_web_components_349d9f24._.js → src_presentation_web_components_895e5bfa._.js} +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_components_895e5bfa._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_skills_8a174cac._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e1cd1869._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_e3a30e30._.js.map +1 -0
- package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js +1 -1
- package/web/.next/server/chunks/ssr/translations_23dd5e7e._.js.map +1 -1
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +535 -683
- package/web/.next/static/chunks/{10383f321355e09b.js → 0ffb3738269e15c3.js} +1 -1
- package/web/.next/static/chunks/236744ff71b1aadf.js +1 -0
- package/web/.next/static/chunks/{05c0a8ed7621ea2a.js → 2cfc6022d74e2716.js} +3 -3
- package/web/.next/static/chunks/302f474e4978cc80.js +3 -0
- package/web/.next/static/chunks/{316b0e4597f2083d.js → 46e2693dbc9262fd.js} +2 -2
- package/web/.next/static/chunks/{6853929058e53d1a.js → 476873a9bac35ec8.js} +1 -1
- package/web/.next/static/chunks/{81347e69998eef38.js → 4ff21d16947ec853.js} +1 -1
- package/web/.next/static/chunks/626277ca9a4cc477.js +1 -0
- package/web/.next/static/chunks/{a1ad19e21b6ad1ad.js → 6304540c7cf2b46a.js} +2 -2
- package/web/.next/static/chunks/{fd319c0e5f3cc20a.js → 71a07df9dcb42227.js} +1 -1
- package/web/.next/static/chunks/{71ad5a4155ddd207.js → 885bb8fc631bf477.js} +1 -1
- package/web/.next/static/chunks/a20f2d6f76f469b7.css +1 -0
- package/web/.next/static/chunks/{8bf91dcd1b3077d7.js → afa7e5d2a48cabc7.js} +1 -1
- package/web/.next/static/chunks/c10c0d6d458453bc.js +1 -0
- package/web/.next/static/chunks/{8a68402c32c6a206.js → e8444bf5f6c35f8b.js} +1 -1
- package/web/.next/static/chunks/eab3d361f7a24510.js +1 -0
- package/web/.next/static/chunks/{6bfcb5d1b3eafd81.js → eda9ee3c22b71a69.js} +1 -1
- package/web/.next/static/chunks/{e610f5d703696b34.js → f17d2d0279b8db35.js} +1 -1
- package/web/.next/static/chunks/f9d948464ed409cb.js +1 -0
- package/apis/json-schema/PermissionMode.yaml +0 -8
- package/dist/packages/core/src/application/ports/output/services/file-system.interface.d.ts +0 -68
- package/dist/packages/core/src/application/ports/output/services/file-system.interface.d.ts.map +0 -1
- package/dist/packages/core/src/application/ports/output/services/file-system.interface.js +0 -12
- package/dist/packages/core/src/application/ports/output/services/process-monitor.interface.d.ts +0 -29
- package/dist/packages/core/src/application/ports/output/services/process-monitor.interface.d.ts.map +0 -1
- package/dist/packages/core/src/application/ports/output/services/process-monitor.interface.js +0 -12
- package/dist/packages/core/src/application/ports/output/services/settings-reader.interface.d.ts +0 -35
- package/dist/packages/core/src/application/ports/output/services/settings-reader.interface.d.ts.map +0 -1
- package/dist/packages/core/src/application/ports/output/services/settings-reader.interface.js +0 -12
- package/dist/packages/core/src/application/use-cases/notifications/poll-agent-events.use-case.d.ts +0 -61
- package/dist/packages/core/src/application/use-cases/notifications/poll-agent-events.use-case.d.ts.map +0 -1
- package/dist/packages/core/src/application/use-cases/notifications/poll-agent-events.use-case.js +0 -381
- package/dist/packages/core/src/infrastructure/di/modules/agent-infrastructure.module.d.ts +0 -7
- package/dist/packages/core/src/infrastructure/di/modules/agent-infrastructure.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/agent-infrastructure.module.js +0 -83
- package/dist/packages/core/src/infrastructure/di/modules/database.module.d.ts +0 -12
- package/dist/packages/core/src/infrastructure/di/modules/database.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/database.module.js +0 -16
- package/dist/packages/core/src/infrastructure/di/modules/interactive.module.d.ts +0 -10
- package/dist/packages/core/src/infrastructure/di/modules/interactive.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/interactive.module.js +0 -43
- package/dist/packages/core/src/infrastructure/di/modules/notifications.module.d.ts +0 -6
- package/dist/packages/core/src/infrastructure/di/modules/notifications.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/notifications.module.js +0 -20
- package/dist/packages/core/src/infrastructure/di/modules/repositories.module.d.ts +0 -6
- package/dist/packages/core/src/infrastructure/di/modules/repositories.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/repositories.module.js +0 -26
- package/dist/packages/core/src/infrastructure/di/modules/services.module.d.ts +0 -8
- package/dist/packages/core/src/infrastructure/di/modules/services.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/services.module.js +0 -93
- package/dist/packages/core/src/infrastructure/di/modules/use-cases.module.d.ts +0 -6
- package/dist/packages/core/src/infrastructure/di/modules/use-cases.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/use-cases.module.js +0 -164
- package/dist/packages/core/src/infrastructure/di/modules/web-tokens.module.d.ts +0 -10
- package/dist/packages/core/src/infrastructure/di/modules/web-tokens.module.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/di/modules/web-tokens.module.js +0 -200
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-agent-permission-mode.d.ts +0 -14
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-agent-permission-mode.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/persistence/sqlite/migrations/056-add-agent-permission-mode.js +0 -19
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/abstract-agent-executor.d.ts +0 -37
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/abstract-agent-executor.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/abstract-agent-executor.js +0 -59
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/rovo-dev-executor.service.d.ts +0 -52
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/rovo-dev-executor.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/rovo-dev-executor.service.js +0 -350
- package/dist/packages/core/src/infrastructure/services/filesystem/file-system.service.d.ts +0 -26
- package/dist/packages/core/src/infrastructure/services/filesystem/file-system.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/filesystem/file-system.service.js +0 -47
- package/dist/packages/core/src/infrastructure/services/filesystem/path-sanitizers.d.ts +0 -19
- package/dist/packages/core/src/infrastructure/services/filesystem/path-sanitizers.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/filesystem/path-sanitizers.js +0 -38
- package/dist/packages/core/src/infrastructure/services/git/branch-discovery.service.d.ts +0 -23
- package/dist/packages/core/src/infrastructure/services/git/branch-discovery.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/git/branch-discovery.service.js +0 -185
- package/dist/packages/core/src/infrastructure/services/git/ci-status.service.d.ts +0 -24
- package/dist/packages/core/src/infrastructure/services/git/ci-status.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/git/ci-status.service.js +0 -202
- package/dist/packages/core/src/infrastructure/services/git/diff-analyzer.service.d.ts +0 -19
- package/dist/packages/core/src/infrastructure/services/git/diff-analyzer.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/git/diff-analyzer.service.js +0 -173
- package/dist/packages/core/src/infrastructure/services/git/merge-strategy.service.d.ts +0 -30
- package/dist/packages/core/src/infrastructure/services/git/merge-strategy.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/git/merge-strategy.service.js +0 -341
- package/dist/packages/core/src/infrastructure/services/git/pr-creation.service.d.ts +0 -34
- package/dist/packages/core/src/infrastructure/services/git/pr-creation.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/git/pr-creation.service.js +0 -180
- package/dist/packages/core/src/infrastructure/services/interactive/chat-state-builder.d.ts +0 -21
- package/dist/packages/core/src/infrastructure/services/interactive/chat-state-builder.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/chat-state-builder.js +0 -112
- package/dist/packages/core/src/infrastructure/services/interactive/session-boot-sequence.d.ts +0 -47
- package/dist/packages/core/src/infrastructure/services/interactive/session-boot-sequence.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/session-boot-sequence.js +0 -381
- package/dist/packages/core/src/infrastructure/services/interactive/session-state-manager.d.ts +0 -28
- package/dist/packages/core/src/infrastructure/services/interactive/session-state-manager.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/session-state-manager.js +0 -105
- package/dist/packages/core/src/infrastructure/services/interactive/session-state.d.ts +0 -46
- package/dist/packages/core/src/infrastructure/services/interactive/session-state.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/session-state.js +0 -10
- package/dist/packages/core/src/infrastructure/services/interactive/subscriber-notifier.d.ts +0 -36
- package/dist/packages/core/src/infrastructure/services/interactive/subscriber-notifier.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/subscriber-notifier.js +0 -60
- package/dist/packages/core/src/infrastructure/services/interactive/turn-executor.d.ts +0 -57
- package/dist/packages/core/src/infrastructure/services/interactive/turn-executor.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/interactive/turn-executor.js +0 -503
- package/dist/packages/core/src/infrastructure/services/process/process-monitor.service.d.ts +0 -25
- package/dist/packages/core/src/infrastructure/services/process/process-monitor.service.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/process/process-monitor.service.js +0 -45
- package/dist/packages/core/src/infrastructure/services/settings-reader.adapter.d.ts +0 -15
- package/dist/packages/core/src/infrastructure/services/settings-reader.adapter.d.ts.map +0 -1
- package/dist/packages/core/src/infrastructure/services/settings-reader.adapter.js +0 -28
- package/dist/src/presentation/web/app/actions/check-agent-auth-for-type.d.ts +0 -11
- package/dist/src/presentation/web/app/actions/check-agent-auth-for-type.d.ts.map +0 -1
- package/dist/src/presentation/web/app/actions/check-agent-auth-for-type.js +0 -147
- package/dist/src/presentation/web/components/common/route-announcer.d.ts +0 -2
- package/dist/src/presentation/web/components/common/route-announcer.d.ts.map +0 -1
- package/dist/src/presentation/web/components/common/route-announcer.js +0 -7
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.d.ts +0 -7
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.d.ts.map +0 -1
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.js +0 -26
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.stories.d.ts +0 -11
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.stories.d.ts.map +0 -1
- package/dist/src/presentation/web/components/features/settings/AgentAvailabilityBadge.stories.js +0 -24
- package/dist/src/presentation/web/hooks/use-agent-availability.d.ts +0 -13
- package/dist/src/presentation/web/hooks/use-agent-availability.d.ts.map +0 -1
- package/dist/src/presentation/web/hooks/use-agent-availability.js +0 -75
- package/dist/src/presentation/web/hooks/use-route-announcer.d.ts +0 -2
- package/dist/src/presentation/web/hooks/use-route-announcer.d.ts.map +0 -1
- package/dist/src/presentation/web/hooks/use-route-announcer.js +0 -16
- package/dist/src/presentation/web/lib/api-error.d.ts +0 -7
- package/dist/src/presentation/web/lib/api-error.d.ts.map +0 -1
- package/dist/src/presentation/web/lib/api-error.js +0 -11
- package/web/.next/server/chunks/[root-of-the-server]__0b88f5f0._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__0b88f5f0._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__0d0a9973._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__0d0a9973._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__1f18a881._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__1f18a881._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__3d08be55._.js +0 -9
- package/web/.next/server/chunks/[root-of-the-server]__3d08be55._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__419be0d1._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__419be0d1._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__4747e669._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__4747e669._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__475afd97._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__475afd97._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__483ccc90._.js +0 -9
- package/web/.next/server/chunks/[root-of-the-server]__483ccc90._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__5e90f1e9._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__5e90f1e9._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__62634db9._.js +0 -12
- package/web/.next/server/chunks/[root-of-the-server]__62634db9._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__645a6d08._.js +0 -12
- package/web/.next/server/chunks/[root-of-the-server]__645a6d08._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__74f3dc5c._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__74f3dc5c._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__810add7c._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__810add7c._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__8cfd9f70._.js +0 -24
- package/web/.next/server/chunks/[root-of-the-server]__8cfd9f70._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__8ec23770._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__8ec23770._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__93c391fe._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__93c391fe._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__9e8fc40c._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__9e8fc40c._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__a2426aa4._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__a2426aa4._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__a96ee39d._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__a96ee39d._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__e10befc1._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__e10befc1._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__e94a4a75._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__e94a4a75._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__ea7e9dc2._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__ea7e9dc2._.js.map +0 -1
- package/web/.next/server/chunks/[root-of-the-server]__f1aeae12._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__f7b38c05._.js +0 -3
- package/web/.next/server/chunks/[root-of-the-server]__f7b38c05._.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_f57e8323.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_f57e8323.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_c2027d57.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_chat_page_actions_c2027d57.js.map +0 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_f70a6774.js +0 -3
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_chat_page_actions_f70a6774.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0e34e896._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__0e34e896._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1eb031d8._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__1eb031d8._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__35e7da6b._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__35e7da6b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__36eb7673._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__36eb7673._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4576a805._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__4576a805._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b51b0071._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b51b0071._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__bd113e97._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__bd113e97._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c6f02c81._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c6f02c81._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d5e22d1a._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f13f6a81._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f13f6a81._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f5614810._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ff332bfb._.js +0 -3
- package/web/.next/server/chunks/ssr/_5747febb._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_819f193a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_ed2f2799._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_064c7e73._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_064c7e73._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_1726dc84._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_1726dc84._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_28c682ee._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_28c682ee._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_2d7b0e7b._.js +0 -5
- package/web/.next/server/chunks/ssr/src_presentation_web_2d7b0e7b._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_bcef11e0.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_bcef11e0.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_02d5029f.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_02d5029f.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_67ca1f81.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_67ca1f81.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_b1110b54._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_b1110b54._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_349d9f24._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_d388fcb0._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_d388fcb0._.js.map +0 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_da61a4f3._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_da61a4f3._.js.map +0 -1
- package/web/.next/static/chunks/1f232a3618b82ac1.css +0 -1
- package/web/.next/static/chunks/2621b35c0c9da177.js +0 -1
- package/web/.next/static/chunks/2a3edcf98f609bb7.js +0 -1
- package/web/.next/static/chunks/3370f8dc24c64ce4.js +0 -1
- package/web/.next/static/chunks/47ed89fae0f1542e.js +0 -1
- package/web/.next/static/chunks/6c1664f584f34e6f.js +0 -1
- package/web/.next/static/chunks/f952f152ac0a4abe.js +0 -3
- package/web/public/icons/agents/rovo-dev.svg +0 -6
- /package/web/.next/server/chunks/{[root-of-the-server]__937ba94e._.js.map → [root-of-the-server]__e3692208._.js.map} +0 -0
- /package/web/.next/static/{8CNKMABoDvNDVQD3DEuB4 → 36ONyC02R4wfFe7iWMQLU}/_buildManifest.js +0 -0
- /package/web/.next/static/{8CNKMABoDvNDVQD3DEuB4 → 36ONyC02R4wfFe7iWMQLU}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{8CNKMABoDvNDVQD3DEuB4 → 36ONyC02R4wfFe7iWMQLU}/_ssgManifest.js +0 -0
package/dist/packages/core/src/infrastructure/services/interactive/interactive-session.service.js
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Interactive Session Service
|
|
2
|
+
* Interactive Session Service
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* - TurnExecutor — turn execution, message persistence, user interactions
|
|
9
|
-
* - SessionBootSequence — session initialization and agent boot
|
|
4
|
+
* Singleton service that owns the lifecycle of all interactive agent sessions.
|
|
5
|
+
* Uses the IAgentExecutorFactory to create interactive executors that manage
|
|
6
|
+
* persistent sessions via the agent SDK. Multi-turn context is maintained
|
|
7
|
+
* by the SDK session handle internally.
|
|
10
8
|
*
|
|
9
|
+
* Dependencies are injected via constructor for testability (no real processes
|
|
10
|
+
* are spawned in unit tests — the factory is replaced with a test double).
|
|
11
|
+
*/
|
|
12
|
+
import * as crypto from 'node:crypto';
|
|
13
|
+
import { InteractiveSessionStatus, InteractiveMessageRole, AgentType, AgentAuthMethod, } from '../../../domain/generated/output.js';
|
|
14
|
+
import { ConcurrentSessionLimitError } from '../../../domain/errors/concurrent-session-limit.error.js';
|
|
15
|
+
import { getSettings, hasSettings } from '../settings.service.js';
|
|
16
|
+
/** Default idle timeout if no settings are loaded (15 minutes). */
|
|
17
|
+
const DEFAULT_TIMEOUT_MS = 15 * 60 * 1000;
|
|
18
|
+
/** Default concurrent session cap. */
|
|
19
|
+
const DEFAULT_CAP = 3;
|
|
20
|
+
/** Maximum time to wait for the agent to become ready (60 seconds). */
|
|
21
|
+
const BOOT_TIMEOUT_MS = 60_000;
|
|
22
|
+
/**
|
|
23
|
+
* Core service managing interactive agent session lifecycles.
|
|
11
24
|
* Must be registered as a singleton in the DI container.
|
|
12
25
|
*
|
|
13
26
|
* **Polymorphic `featureId` scope key:** The `featureId` parameter accepted
|
|
@@ -18,87 +31,1014 @@
|
|
|
18
31
|
* - Global chat: literal string `"global"`
|
|
19
32
|
*
|
|
20
33
|
* Sessions and messages are isolated by this key regardless of chat type.
|
|
34
|
+
*
|
|
35
|
+
* @todo Consider renaming to `scopeId` + adding a `scopeType` discriminator.
|
|
21
36
|
*/
|
|
22
|
-
import { DEFAULT_TIMEOUT_MS } from './session-state.js';
|
|
23
|
-
import { SubscriberNotifier } from './subscriber-notifier.js';
|
|
24
|
-
import { SessionStateManager } from './session-state-manager.js';
|
|
25
|
-
import { ChatStateBuilder } from './chat-state-builder.js';
|
|
26
|
-
import { TurnExecutor } from './turn-executor.js';
|
|
27
|
-
import { SessionBootSequence } from './session-boot-sequence.js';
|
|
28
|
-
import { getSettings, hasSettings } from '../settings.service.js';
|
|
29
37
|
export class InteractiveSessionService {
|
|
38
|
+
sessionRepo;
|
|
39
|
+
messageRepo;
|
|
40
|
+
executorFactory;
|
|
41
|
+
featureRepo;
|
|
42
|
+
contextBuilder;
|
|
30
43
|
/** Live sessions indexed by sessionId. */
|
|
31
44
|
sessions = new Map();
|
|
32
45
|
/** Cached agentSessionIds from stopped sessions, keyed by featureId. */
|
|
33
46
|
stoppedAgentSessionIds = new Map();
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Feature-level subscribers that survive session restarts.
|
|
49
|
+
*
|
|
50
|
+
* Unlike session-level subscribers (in SessionState.subscribers), these
|
|
51
|
+
* persist when a session dies and a new one boots. SSE connections
|
|
52
|
+
* subscribe here so they continue receiving events from new sessions.
|
|
53
|
+
*/
|
|
54
|
+
featureSubscribers = new Map();
|
|
40
55
|
constructor(sessionRepo, messageRepo, executorFactory, featureRepo, contextBuilder) {
|
|
41
|
-
this.
|
|
42
|
-
this.
|
|
43
|
-
this.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
this.turnExecutor = new TurnExecutor(sessionRepo, messageRepo, this.notifier, resetTimer);
|
|
47
|
-
this.bootSequence = new SessionBootSequence(sessionRepo, messageRepo, executorFactory, featureRepo, contextBuilder, this.notifier, this.turnExecutor, resetTimer);
|
|
56
|
+
this.sessionRepo = sessionRepo;
|
|
57
|
+
this.messageRepo = messageRepo;
|
|
58
|
+
this.executorFactory = executorFactory;
|
|
59
|
+
this.featureRepo = featureRepo;
|
|
60
|
+
this.contextBuilder = contextBuilder;
|
|
48
61
|
}
|
|
49
62
|
// ---------------------------------------------------------------------------
|
|
50
|
-
// Public API
|
|
63
|
+
// Public API
|
|
51
64
|
// ---------------------------------------------------------------------------
|
|
52
65
|
async startSession(featureId, worktreePath, model, agentType) {
|
|
53
|
-
|
|
66
|
+
const cap = this.getCap();
|
|
67
|
+
const activeCount = await this.sessionRepo.countActiveSessions();
|
|
68
|
+
if (activeCount >= cap) {
|
|
69
|
+
throw new ConcurrentSessionLimitError(activeCount, cap);
|
|
70
|
+
}
|
|
71
|
+
// Create DB record with booting status
|
|
72
|
+
const now = new Date();
|
|
73
|
+
const session = {
|
|
74
|
+
id: crypto.randomUUID(),
|
|
75
|
+
featureId,
|
|
76
|
+
status: InteractiveSessionStatus.booting,
|
|
77
|
+
startedAt: now,
|
|
78
|
+
lastActivityAt: now,
|
|
79
|
+
createdAt: now,
|
|
80
|
+
updatedAt: now,
|
|
81
|
+
};
|
|
82
|
+
await this.sessionRepo.create(session);
|
|
83
|
+
// Mark as processing immediately so the FAB shows the spinner during boot
|
|
84
|
+
void this.sessionRepo.updateTurnStatus(session.id, 'processing');
|
|
85
|
+
// Carry over agentSessionId from previous session so resumption works
|
|
86
|
+
let previousAgentSessionId;
|
|
87
|
+
for (const [, s] of this.sessions) {
|
|
88
|
+
if (s.featureId === featureId && s.agentSessionId) {
|
|
89
|
+
previousAgentSessionId = s.agentSessionId;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Also check stoppedSessions cache (populated on stop)
|
|
94
|
+
previousAgentSessionId ??= this.stoppedAgentSessionIds.get(featureId);
|
|
95
|
+
// Fall back to DB — the in-memory cache may be empty after service restart
|
|
96
|
+
if (!previousAgentSessionId) {
|
|
97
|
+
const latestDbSession = await this.sessionRepo.findByFeatureId(featureId);
|
|
98
|
+
if (latestDbSession) {
|
|
99
|
+
previousAgentSessionId =
|
|
100
|
+
(await this.sessionRepo.getAgentSessionId(latestDbSession.id)) ?? undefined;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Set up in-memory state
|
|
104
|
+
const state = {
|
|
105
|
+
sessionId: session.id,
|
|
106
|
+
featureId,
|
|
107
|
+
worktreePath,
|
|
108
|
+
model,
|
|
109
|
+
agentType,
|
|
110
|
+
handle: null,
|
|
111
|
+
agentSessionId: previousAgentSessionId,
|
|
112
|
+
timer: null,
|
|
113
|
+
currentAssistantBuffer: '',
|
|
114
|
+
toolEventsLog: [],
|
|
115
|
+
subscribers: new Set(),
|
|
116
|
+
turnInProgress: false,
|
|
117
|
+
turnQueue: [],
|
|
118
|
+
pendingInteraction: null,
|
|
119
|
+
pendingInteractionResolver: null,
|
|
120
|
+
};
|
|
121
|
+
this.sessions.set(session.id, state);
|
|
122
|
+
// Fire-and-forget the async boot sequence. The API returns the session
|
|
123
|
+
// immediately in "booting" status; the frontend polls until "ready".
|
|
124
|
+
void this.completeBootAsync(state, featureId, worktreePath);
|
|
125
|
+
return session;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Asynchronously complete the boot sequence: build feature context,
|
|
129
|
+
* create an SDK session via the interactive executor, send the boot
|
|
130
|
+
* prompt, iterate the stream for the greeting, persist the greeting,
|
|
131
|
+
* and transition the session to "ready".
|
|
132
|
+
*/
|
|
133
|
+
async completeBootAsync(state, featureId, worktreePath) {
|
|
134
|
+
try {
|
|
135
|
+
// Build the feature context prompt
|
|
136
|
+
const feature = await this.featureRepo.findById(featureId);
|
|
137
|
+
const openPRs = feature?.pr?.url ? [feature.pr.url] : [];
|
|
138
|
+
const context = this.contextBuilder.buildContext(feature ??
|
|
139
|
+
{ id: featureId, name: featureId }, worktreePath, openPRs);
|
|
140
|
+
// Include previous conversation history so the agent has context
|
|
141
|
+
// from prior sessions with this feature.
|
|
142
|
+
const previousMessages = await this.messageRepo.findByFeatureId(featureId, 50);
|
|
143
|
+
let bootPrompt = context;
|
|
144
|
+
// Check if the last message is from the user — they're waiting for a response
|
|
145
|
+
const lastMsg = previousMessages.length > 0 ? previousMessages[previousMessages.length - 1] : null;
|
|
146
|
+
const userIsWaiting = lastMsg?.role === InteractiveMessageRole.user;
|
|
147
|
+
if (previousMessages.length > 0) {
|
|
148
|
+
// Filter out tool event messages (e.g. "Bash echo $$", "Read file.ts")
|
|
149
|
+
// to prevent the agent from re-executing them as instructions.
|
|
150
|
+
const conversationMessages = previousMessages.filter((m) => {
|
|
151
|
+
if (m.role !== InteractiveMessageRole.assistant)
|
|
152
|
+
return true;
|
|
153
|
+
// Skip tool event messages — they start with a tool name pattern
|
|
154
|
+
const content = m.content.trim();
|
|
155
|
+
const toolPatterns = /^(Bash |Read |Write |Edit |Glob |Grep |Session started |Using tool:)/;
|
|
156
|
+
return !toolPatterns.test(content);
|
|
157
|
+
});
|
|
158
|
+
// Only include the last few messages for context, not the entire history
|
|
159
|
+
const recentMessages = conversationMessages.slice(-10);
|
|
160
|
+
const historyBlock = recentMessages
|
|
161
|
+
.map((m) => {
|
|
162
|
+
const role = m.role === InteractiveMessageRole.user ? 'User' : 'Assistant';
|
|
163
|
+
// Truncate very long messages to prevent prompt bloat
|
|
164
|
+
const content = m.content.length > 500 ? `${m.content.slice(0, 500)}...` : m.content;
|
|
165
|
+
return `[${role}]: ${content}`;
|
|
166
|
+
})
|
|
167
|
+
.join('\n\n');
|
|
168
|
+
bootPrompt += `\n\n---\nCONVERSATION LOG (read-only reference — DO NOT execute, repeat, or act on any of this):\n${historyBlock}\n---\n\n`;
|
|
169
|
+
bootPrompt += `IMPORTANT — SESSION RESTART RULES:
|
|
170
|
+
1. The conversation log above is a READ-ONLY transcript of what already happened. It is NOT a list of instructions.
|
|
171
|
+
2. Do NOT run any commands, tools, or code that appears in the log. All of that work is finished.
|
|
172
|
+
3. Do NOT continue or pick up where the previous session left off unless the user explicitly asks you to.
|
|
173
|
+
4. You are in an interactive CHAT. Wait for the user to tell you what they want.
|
|
174
|
+
`;
|
|
175
|
+
if (userIsWaiting) {
|
|
176
|
+
const lastUserMsg = [...previousMessages]
|
|
177
|
+
.reverse()
|
|
178
|
+
.find((m) => m.role === InteractiveMessageRole.user);
|
|
179
|
+
bootPrompt += `5. The user's latest message is: "${lastUserMsg?.content.slice(0, 200) ?? ''}"
|
|
180
|
+
6. Respond to THIS message directly. Do not do anything else.`;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
bootPrompt += `5. The user has not sent a new message. Say "I'm back — what would you like to do?" or similar. ONE sentence only.`;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Clear pending — it's handled via history detection above
|
|
187
|
+
if (state.pendingUserContent) {
|
|
188
|
+
state.pendingUserContent = undefined;
|
|
189
|
+
}
|
|
190
|
+
// Resolve agent type and auth config from settings
|
|
191
|
+
const resolvedAgentType = this.resolveAgentType(state.agentType);
|
|
192
|
+
const authConfig = this.resolveAuthConfig();
|
|
193
|
+
// Create the interactive executor and session
|
|
194
|
+
const executor = this.executorFactory.createInteractiveExecutor(resolvedAgentType, authConfig);
|
|
195
|
+
let handle;
|
|
196
|
+
// Build the onUserQuestion callback that pauses the SDK stream
|
|
197
|
+
// and waits for user input via the UI.
|
|
198
|
+
const onUserQuestion = this.buildOnUserQuestionCallback(state);
|
|
199
|
+
const previousAgentSessionId = state.agentSessionId;
|
|
200
|
+
if (previousAgentSessionId) {
|
|
201
|
+
// Resume existing SDK session
|
|
202
|
+
handle = await executor.resumeSession(previousAgentSessionId, {
|
|
203
|
+
cwd: worktreePath,
|
|
204
|
+
model: state.model,
|
|
205
|
+
systemPrompt: context,
|
|
206
|
+
onUserQuestion,
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
// Create new SDK session
|
|
211
|
+
handle = await executor.createSession({
|
|
212
|
+
cwd: worktreePath,
|
|
213
|
+
model: state.model,
|
|
214
|
+
systemPrompt: context,
|
|
215
|
+
onUserQuestion,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
state.handle = handle;
|
|
219
|
+
// Send the boot prompt and iterate stream for the greeting
|
|
220
|
+
await handle.send(bootPrompt);
|
|
221
|
+
let greetingText = '';
|
|
222
|
+
const bootAbort = new AbortController();
|
|
223
|
+
state.streamAbort = bootAbort;
|
|
224
|
+
// Set up boot timeout
|
|
225
|
+
const bootTimeout = setTimeout(() => {
|
|
226
|
+
bootAbort.abort();
|
|
227
|
+
}, BOOT_TIMEOUT_MS);
|
|
228
|
+
try {
|
|
229
|
+
for await (const event of handle.stream()) {
|
|
230
|
+
if (bootAbort.signal.aborted) {
|
|
231
|
+
throw new Error(`Agent boot timed out after ${BOOT_TIMEOUT_MS / 1000}s`);
|
|
232
|
+
}
|
|
233
|
+
this.resetTimer(state);
|
|
234
|
+
switch (event.type) {
|
|
235
|
+
case 'delta':
|
|
236
|
+
if (event.content) {
|
|
237
|
+
greetingText += event.content;
|
|
238
|
+
state.currentAssistantBuffer += event.content;
|
|
239
|
+
this.notify(state, { delta: event.content, done: false });
|
|
240
|
+
}
|
|
241
|
+
break;
|
|
242
|
+
case 'tool_use':
|
|
243
|
+
if (event.label) {
|
|
244
|
+
const toolLabel = event.label;
|
|
245
|
+
const toolDetail = event.detail;
|
|
246
|
+
void this.persistToolEvent(state, toolLabel, toolDetail);
|
|
247
|
+
this.notify(state, {
|
|
248
|
+
delta: '',
|
|
249
|
+
done: false,
|
|
250
|
+
log: `Using tool: ${toolLabel}`,
|
|
251
|
+
activity: { kind: 'tool_use', label: toolLabel, detail: toolDetail },
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
break;
|
|
255
|
+
case 'tool_result':
|
|
256
|
+
if (event.label) {
|
|
257
|
+
const resultLabel = event.label;
|
|
258
|
+
const resultDetail = event.detail;
|
|
259
|
+
void this.persistToolEvent(state, resultLabel, resultDetail);
|
|
260
|
+
this.notify(state, {
|
|
261
|
+
delta: '',
|
|
262
|
+
done: false,
|
|
263
|
+
log: `Completed: ${resultLabel}`,
|
|
264
|
+
activity: { kind: 'tool_result', label: resultLabel, detail: resultDetail },
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
break;
|
|
268
|
+
case 'status':
|
|
269
|
+
if (event.content) {
|
|
270
|
+
const statusContent = event.content;
|
|
271
|
+
this.notify(state, { delta: '', done: false, log: statusContent });
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
case 'done': {
|
|
275
|
+
// Use result text if provided and non-empty, otherwise use accumulated buffer
|
|
276
|
+
const resultText = event.content && event.content.length > 0 ? event.content : greetingText;
|
|
277
|
+
// Capture the SDK session ID (available after first message exchange)
|
|
278
|
+
const sdkSessionId = handle.sessionId;
|
|
279
|
+
if (sdkSessionId) {
|
|
280
|
+
// Detect CWD mismatch: if we tried to resume but got a different
|
|
281
|
+
// session ID, the SDK silently created a fresh session (typically
|
|
282
|
+
// because the cwd changed or session JSONL was lost).
|
|
283
|
+
if (previousAgentSessionId && sdkSessionId !== previousAgentSessionId) {
|
|
284
|
+
// eslint-disable-next-line no-console
|
|
285
|
+
console.warn(`[InteractiveSession] Session resume mismatch for feature ${featureId}: ` +
|
|
286
|
+
`expected ${previousAgentSessionId}, got ${sdkSessionId}. ` +
|
|
287
|
+
`SDK created a fresh session (likely cwd changed or session expired).`);
|
|
288
|
+
}
|
|
289
|
+
state.agentSessionId = sdkSessionId;
|
|
290
|
+
// Persist to DB so it survives service restarts
|
|
291
|
+
void this.sessionRepo.updateAgentSessionId(state.sessionId, sdkSessionId);
|
|
292
|
+
}
|
|
293
|
+
// Persist greeting and mark session ready
|
|
294
|
+
const greetingMsg = {
|
|
295
|
+
id: crypto.randomUUID(),
|
|
296
|
+
featureId,
|
|
297
|
+
sessionId: state.sessionId,
|
|
298
|
+
role: InteractiveMessageRole.assistant,
|
|
299
|
+
content: resultText,
|
|
300
|
+
createdAt: new Date(),
|
|
301
|
+
updatedAt: new Date(),
|
|
302
|
+
};
|
|
303
|
+
await this.messageRepo.create(greetingMsg);
|
|
304
|
+
await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.ready);
|
|
305
|
+
// If there's a pending user message, the next turn will set 'processing'.
|
|
306
|
+
// Otherwise boot greeting is expected — mark idle.
|
|
307
|
+
if (!state.pendingUserContent) {
|
|
308
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
|
|
309
|
+
}
|
|
310
|
+
state.currentAssistantBuffer = '';
|
|
311
|
+
state.toolEventsLog = [];
|
|
312
|
+
// Notify subscribers of end-of-turn
|
|
313
|
+
this.notify(state, { delta: '', done: true });
|
|
314
|
+
// Start idle timer now that the session is live
|
|
315
|
+
this.resetTimer(state);
|
|
316
|
+
return; // Boot complete
|
|
317
|
+
}
|
|
318
|
+
case 'error':
|
|
319
|
+
throw new Error(`Agent error during boot: ${event.content ?? 'unknown'}`);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
finally {
|
|
324
|
+
clearTimeout(bootTimeout);
|
|
325
|
+
state.streamAbort = undefined;
|
|
326
|
+
}
|
|
327
|
+
// If we get here without a 'done' event, use whatever text we accumulated
|
|
328
|
+
if (greetingText) {
|
|
329
|
+
const greetingMsg = {
|
|
330
|
+
id: crypto.randomUUID(),
|
|
331
|
+
featureId,
|
|
332
|
+
sessionId: state.sessionId,
|
|
333
|
+
role: InteractiveMessageRole.assistant,
|
|
334
|
+
content: greetingText,
|
|
335
|
+
createdAt: new Date(),
|
|
336
|
+
updatedAt: new Date(),
|
|
337
|
+
};
|
|
338
|
+
await this.messageRepo.create(greetingMsg);
|
|
339
|
+
}
|
|
340
|
+
await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.ready);
|
|
341
|
+
if (!state.pendingUserContent) {
|
|
342
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
|
|
343
|
+
}
|
|
344
|
+
state.currentAssistantBuffer = '';
|
|
345
|
+
state.toolEventsLog = [];
|
|
346
|
+
this.resetTimer(state);
|
|
347
|
+
}
|
|
348
|
+
catch (err) {
|
|
349
|
+
// If session was already cleaned up by stopSession, nothing more to do
|
|
350
|
+
if (!this.sessions.has(state.sessionId))
|
|
351
|
+
return;
|
|
352
|
+
// Boot failed — mark session as error so the frontend can show the failure
|
|
353
|
+
// eslint-disable-next-line no-console
|
|
354
|
+
console.error(`[InteractiveSession] boot failed for session ${state.sessionId}:`, err);
|
|
355
|
+
try {
|
|
356
|
+
await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.error);
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
// Best-effort DB update
|
|
360
|
+
}
|
|
361
|
+
if (state.agentSessionId) {
|
|
362
|
+
this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
|
|
363
|
+
}
|
|
364
|
+
this.sessions.delete(state.sessionId);
|
|
365
|
+
}
|
|
54
366
|
}
|
|
55
367
|
async stopSession(sessionId) {
|
|
56
|
-
|
|
368
|
+
const state = this.sessions.get(sessionId);
|
|
369
|
+
if (!state) {
|
|
370
|
+
// Already stopped — idempotent
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
// eslint-disable-next-line no-console
|
|
374
|
+
console.log(`[InteractiveSession] stopSession called for ${sessionId} (feature: ${state.featureId})`, new Error().stack?.split('\n').slice(1, 4).join(' <- '));
|
|
375
|
+
// Abort any active stream iteration and clear pending turns
|
|
376
|
+
if (state.streamAbort) {
|
|
377
|
+
state.streamAbort.abort();
|
|
378
|
+
state.streamAbort = undefined;
|
|
379
|
+
}
|
|
380
|
+
state.turnQueue.length = 0;
|
|
381
|
+
state.turnInProgress = false;
|
|
382
|
+
this.clearTimer(state);
|
|
383
|
+
// Cache agentSessionId so resumption works when session restarts
|
|
384
|
+
if (state.agentSessionId) {
|
|
385
|
+
this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
|
|
386
|
+
}
|
|
387
|
+
this.sessions.delete(sessionId);
|
|
388
|
+
// Close the SDK session handle
|
|
389
|
+
if (state.handle) {
|
|
390
|
+
try {
|
|
391
|
+
await state.handle.close();
|
|
392
|
+
}
|
|
393
|
+
catch {
|
|
394
|
+
// Session may already be closed
|
|
395
|
+
}
|
|
396
|
+
state.handle = null;
|
|
397
|
+
}
|
|
398
|
+
await this.sessionRepo.updateStatus(sessionId, InteractiveSessionStatus.stopped, new Date());
|
|
399
|
+
void this.sessionRepo.updateTurnStatus(sessionId, 'idle');
|
|
57
400
|
}
|
|
58
401
|
async sendMessage(sessionId, content) {
|
|
59
|
-
|
|
402
|
+
const dbSession = await this.sessionRepo.findById(sessionId);
|
|
403
|
+
if (!dbSession || dbSession.status !== InteractiveSessionStatus.ready) {
|
|
404
|
+
throw new Error(`Session ${sessionId} is not ready — cannot send message`);
|
|
405
|
+
}
|
|
406
|
+
const state = this.sessions.get(sessionId);
|
|
407
|
+
if (!state) {
|
|
408
|
+
throw new Error(`Session ${sessionId} is not ready — cannot send message`);
|
|
409
|
+
}
|
|
410
|
+
// Persist user message
|
|
411
|
+
const now = new Date();
|
|
412
|
+
const message = {
|
|
413
|
+
id: crypto.randomUUID(),
|
|
414
|
+
featureId: state.featureId,
|
|
415
|
+
sessionId,
|
|
416
|
+
role: InteractiveMessageRole.user,
|
|
417
|
+
content,
|
|
418
|
+
createdAt: now,
|
|
419
|
+
updatedAt: now,
|
|
420
|
+
};
|
|
421
|
+
await this.messageRepo.create(message);
|
|
422
|
+
// Reset idle timer on user activity
|
|
423
|
+
this.resetTimer(state);
|
|
424
|
+
await this.sessionRepo.updateLastActivity(sessionId, now);
|
|
425
|
+
// Guard: only one turn at a time per session (SDK stream is not concurrent-safe)
|
|
426
|
+
if (state.turnInProgress) {
|
|
427
|
+
state.turnQueue.push(content);
|
|
428
|
+
}
|
|
429
|
+
else {
|
|
430
|
+
state.turnInProgress = true;
|
|
431
|
+
void this.executeAndPersistTurn(state, content);
|
|
432
|
+
}
|
|
433
|
+
return message;
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Execute a turn via the SDK session handle and persist the assistant response.
|
|
437
|
+
*/
|
|
438
|
+
async executeAndPersistTurn(state, prompt) {
|
|
439
|
+
try {
|
|
440
|
+
if (!state.handle) {
|
|
441
|
+
throw new Error('No active session handle — cannot execute turn');
|
|
442
|
+
}
|
|
443
|
+
state.currentAssistantBuffer = '';
|
|
444
|
+
state.toolEventsLog = [];
|
|
445
|
+
// Mark turn as processing for dot indicator
|
|
446
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'processing');
|
|
447
|
+
// Send the message to the SDK session
|
|
448
|
+
await state.handle.send(prompt);
|
|
449
|
+
// Set up abort controller for this stream
|
|
450
|
+
const abort = new AbortController();
|
|
451
|
+
state.streamAbort = abort;
|
|
452
|
+
let responseText = '';
|
|
453
|
+
try {
|
|
454
|
+
for await (const event of state.handle.stream()) {
|
|
455
|
+
if (abort.signal.aborted)
|
|
456
|
+
break;
|
|
457
|
+
// Reset idle timer on each event received
|
|
458
|
+
this.resetTimer(state);
|
|
459
|
+
switch (event.type) {
|
|
460
|
+
case 'delta':
|
|
461
|
+
if (event.content) {
|
|
462
|
+
responseText += event.content;
|
|
463
|
+
state.currentAssistantBuffer += event.content;
|
|
464
|
+
this.notify(state, { delta: event.content, done: false });
|
|
465
|
+
}
|
|
466
|
+
break;
|
|
467
|
+
case 'tool_use':
|
|
468
|
+
if (event.label) {
|
|
469
|
+
const toolLabel = event.label;
|
|
470
|
+
const toolDetail = event.detail;
|
|
471
|
+
void this.persistToolEvent(state, toolLabel, toolDetail);
|
|
472
|
+
this.notify(state, {
|
|
473
|
+
delta: '',
|
|
474
|
+
done: false,
|
|
475
|
+
log: `Using tool: ${toolLabel}`,
|
|
476
|
+
activity: { kind: 'tool_use', label: toolLabel, detail: toolDetail },
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
break;
|
|
480
|
+
case 'tool_result':
|
|
481
|
+
if (event.label) {
|
|
482
|
+
const resultLabel = event.label;
|
|
483
|
+
const resultDetail = event.detail;
|
|
484
|
+
void this.persistToolEvent(state, resultLabel, resultDetail);
|
|
485
|
+
this.notify(state, {
|
|
486
|
+
delta: '',
|
|
487
|
+
done: false,
|
|
488
|
+
log: `Completed: ${resultLabel}`,
|
|
489
|
+
activity: { kind: 'tool_result', label: resultLabel, detail: resultDetail },
|
|
490
|
+
});
|
|
491
|
+
}
|
|
492
|
+
break;
|
|
493
|
+
case 'status':
|
|
494
|
+
if (event.content) {
|
|
495
|
+
const statusContent = event.content;
|
|
496
|
+
this.notify(state, { delta: '', done: false, log: statusContent });
|
|
497
|
+
}
|
|
498
|
+
break;
|
|
499
|
+
case 'done': {
|
|
500
|
+
// Use result text if provided and non-empty, otherwise use accumulated buffer
|
|
501
|
+
const resultText = event.content && event.content.length > 0 ? event.content : responseText;
|
|
502
|
+
// Persist assistant message
|
|
503
|
+
const now = new Date();
|
|
504
|
+
const msg = {
|
|
505
|
+
id: crypto.randomUUID(),
|
|
506
|
+
featureId: state.featureId,
|
|
507
|
+
sessionId: state.sessionId,
|
|
508
|
+
role: InteractiveMessageRole.assistant,
|
|
509
|
+
content: resultText,
|
|
510
|
+
createdAt: now,
|
|
511
|
+
updatedAt: now,
|
|
512
|
+
};
|
|
513
|
+
await this.messageRepo.create(msg);
|
|
514
|
+
state.currentAssistantBuffer = '';
|
|
515
|
+
state.toolEventsLog = [];
|
|
516
|
+
// Accumulate usage from this turn
|
|
517
|
+
if (event.usage) {
|
|
518
|
+
void this.sessionRepo.accumulateUsage(state.sessionId, {
|
|
519
|
+
costUsd: event.usage.costUsd ?? 0,
|
|
520
|
+
inputTokens: event.usage.inputTokens ?? 0,
|
|
521
|
+
outputTokens: event.usage.outputTokens ?? 0,
|
|
522
|
+
turns: event.usage.numTurns ?? 1,
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
// Mark as unread — if user has the chat open, the frontend
|
|
526
|
+
// will immediately call markRead to clear it
|
|
527
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'unread');
|
|
528
|
+
// Notify subscribers of end-of-turn
|
|
529
|
+
this.notify(state, { delta: '', done: true });
|
|
530
|
+
return; // Turn complete
|
|
531
|
+
}
|
|
532
|
+
case 'error':
|
|
533
|
+
// eslint-disable-next-line no-console
|
|
534
|
+
console.error(`[InteractiveSession] agent error during turn for session ${state.sessionId}:`, event.content);
|
|
535
|
+
// Accumulate usage even on errors — cost was still incurred
|
|
536
|
+
if (event.usage) {
|
|
537
|
+
void this.sessionRepo.accumulateUsage(state.sessionId, {
|
|
538
|
+
costUsd: event.usage.costUsd ?? 0,
|
|
539
|
+
inputTokens: event.usage.inputTokens ?? 0,
|
|
540
|
+
outputTokens: event.usage.outputTokens ?? 0,
|
|
541
|
+
turns: event.usage.numTurns ?? 1,
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
this.notify(state, {
|
|
545
|
+
delta: '',
|
|
546
|
+
done: true,
|
|
547
|
+
log: `Error: ${event.content ?? 'unknown'}`,
|
|
548
|
+
});
|
|
549
|
+
break;
|
|
550
|
+
case 'init':
|
|
551
|
+
// The SDK emits init on every turn, but we only show "Session started"
|
|
552
|
+
// during boot (handled in completeBootAsync). Ignore it here to avoid
|
|
553
|
+
// spamming the chat with repeated session-started messages.
|
|
554
|
+
break;
|
|
555
|
+
case 'api_retry':
|
|
556
|
+
this.notify(state, {
|
|
557
|
+
delta: '',
|
|
558
|
+
done: false,
|
|
559
|
+
log: event.content ?? 'Retrying API call...',
|
|
560
|
+
});
|
|
561
|
+
break;
|
|
562
|
+
case 'rate_limit':
|
|
563
|
+
this.notify(state, { delta: '', done: false, log: event.content ?? 'Rate limited' });
|
|
564
|
+
break;
|
|
565
|
+
case 'task_started':
|
|
566
|
+
if (event.content) {
|
|
567
|
+
void this.persistToolEvent(state, 'Subtask started', event.content);
|
|
568
|
+
this.notify(state, {
|
|
569
|
+
delta: '',
|
|
570
|
+
done: false,
|
|
571
|
+
log: `Subtask: ${event.content}`,
|
|
572
|
+
activity: { kind: 'system', label: 'Subtask started', detail: event.content },
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
break;
|
|
576
|
+
case 'task_progress':
|
|
577
|
+
if (event.content) {
|
|
578
|
+
this.notify(state, { delta: '', done: false, log: `Subtask: ${event.content}` });
|
|
579
|
+
}
|
|
580
|
+
break;
|
|
581
|
+
case 'task_done':
|
|
582
|
+
if (event.content) {
|
|
583
|
+
const taskStatus = event.detail ?? 'completed';
|
|
584
|
+
void this.persistToolEvent(state, `Subtask ${taskStatus}`, event.content);
|
|
585
|
+
this.notify(state, {
|
|
586
|
+
delta: '',
|
|
587
|
+
done: false,
|
|
588
|
+
log: `Subtask ${taskStatus}: ${event.content}`,
|
|
589
|
+
activity: {
|
|
590
|
+
kind: 'system',
|
|
591
|
+
label: `Subtask ${taskStatus}`,
|
|
592
|
+
detail: event.content,
|
|
593
|
+
},
|
|
594
|
+
});
|
|
595
|
+
}
|
|
596
|
+
break;
|
|
597
|
+
case 'user_question':
|
|
598
|
+
// AskUserQuestion is now handled by the canUseTool callback
|
|
599
|
+
// (buildOnUserQuestionCallback) which pauses the SDK stream.
|
|
600
|
+
// This event should not appear in the stream anymore, but if it
|
|
601
|
+
// does (e.g. from a different code path), ignore it here.
|
|
602
|
+
break;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
finally {
|
|
607
|
+
state.streamAbort = undefined;
|
|
608
|
+
}
|
|
609
|
+
// If we exit the stream loop without a 'done' event (stream ended),
|
|
610
|
+
// persist whatever text we accumulated
|
|
611
|
+
if (responseText && state.currentAssistantBuffer) {
|
|
612
|
+
const now = new Date();
|
|
613
|
+
const msg = {
|
|
614
|
+
id: crypto.randomUUID(),
|
|
615
|
+
featureId: state.featureId,
|
|
616
|
+
sessionId: state.sessionId,
|
|
617
|
+
role: InteractiveMessageRole.assistant,
|
|
618
|
+
content: responseText,
|
|
619
|
+
createdAt: now,
|
|
620
|
+
updatedAt: now,
|
|
621
|
+
};
|
|
622
|
+
await this.messageRepo.create(msg);
|
|
623
|
+
state.currentAssistantBuffer = '';
|
|
624
|
+
state.toolEventsLog = [];
|
|
625
|
+
this.notify(state, { delta: '', done: true });
|
|
626
|
+
}
|
|
627
|
+
else if (!responseText) {
|
|
628
|
+
// Stream ended without any response — SDK session likely died.
|
|
629
|
+
// Mark as error so the next message triggers a fresh session.
|
|
630
|
+
// eslint-disable-next-line no-console
|
|
631
|
+
console.error(`[InteractiveSession] stream ended without response for session ${state.sessionId} — session may have died`);
|
|
632
|
+
this.notify(state, {
|
|
633
|
+
delta: '',
|
|
634
|
+
done: true,
|
|
635
|
+
log: 'Session disconnected — will restart on next message',
|
|
636
|
+
});
|
|
637
|
+
if (state.agentSessionId) {
|
|
638
|
+
this.stoppedAgentSessionIds.set(state.featureId, state.agentSessionId);
|
|
639
|
+
}
|
|
640
|
+
this.sessions.delete(state.sessionId);
|
|
641
|
+
try {
|
|
642
|
+
await this.sessionRepo.updateStatus(state.sessionId, InteractiveSessionStatus.error);
|
|
643
|
+
}
|
|
644
|
+
catch {
|
|
645
|
+
// Best-effort DB update
|
|
646
|
+
}
|
|
647
|
+
return; // Skip queue drain — session is dead
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
catch (err) {
|
|
651
|
+
// If session was already stopped, ignore
|
|
652
|
+
if (!this.sessions.has(state.sessionId))
|
|
653
|
+
return;
|
|
654
|
+
// eslint-disable-next-line no-console
|
|
655
|
+
console.error(`[InteractiveSession] turn failed for session ${state.sessionId}:`, err);
|
|
656
|
+
}
|
|
657
|
+
finally {
|
|
658
|
+
// Release the turn lock and drain the queue
|
|
659
|
+
state.turnInProgress = false;
|
|
660
|
+
if (this.sessions.has(state.sessionId) && state.turnQueue.length > 0) {
|
|
661
|
+
const nextContent = state.turnQueue.shift();
|
|
662
|
+
state.turnInProgress = true;
|
|
663
|
+
void this.executeAndPersistTurn(state, nextContent);
|
|
664
|
+
}
|
|
665
|
+
}
|
|
60
666
|
}
|
|
61
667
|
async getMessages(featureId, limit) {
|
|
62
|
-
return this.
|
|
668
|
+
return this.messageRepo.findByFeatureId(featureId, limit);
|
|
63
669
|
}
|
|
64
670
|
async clearMessages(featureId) {
|
|
65
|
-
|
|
671
|
+
// Stop any active session so the agent doesn't retain old context
|
|
672
|
+
const state = this.findActiveStateForFeature(featureId);
|
|
673
|
+
if (state) {
|
|
674
|
+
await this.stopSession(state.sessionId);
|
|
675
|
+
}
|
|
676
|
+
// Also clear the cached agentSessionId so next session starts fresh
|
|
677
|
+
this.stoppedAgentSessionIds.delete(featureId);
|
|
678
|
+
return this.messageRepo.deleteByFeatureId(featureId);
|
|
66
679
|
}
|
|
67
680
|
async getSession(sessionId) {
|
|
68
|
-
return this.
|
|
681
|
+
return this.sessionRepo.findById(sessionId);
|
|
69
682
|
}
|
|
70
683
|
subscribe(sessionId, onChunk) {
|
|
71
|
-
|
|
684
|
+
const state = this.sessions.get(sessionId);
|
|
685
|
+
if (!state) {
|
|
686
|
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
|
687
|
+
return () => { };
|
|
688
|
+
}
|
|
689
|
+
state.subscribers.add(onChunk);
|
|
690
|
+
return () => state.subscribers.delete(onChunk);
|
|
72
691
|
}
|
|
73
692
|
// ---------------------------------------------------------------------------
|
|
74
693
|
// Feature-scoped API (frontend doesn't manage sessions)
|
|
75
694
|
// ---------------------------------------------------------------------------
|
|
76
695
|
async sendUserMessage(featureId, content, worktreePath, model, agentType) {
|
|
77
|
-
|
|
696
|
+
// 1. Persist user message to DB immediately — this is the source of truth
|
|
697
|
+
const now = new Date();
|
|
698
|
+
const userMsg = {
|
|
699
|
+
id: crypto.randomUUID(),
|
|
700
|
+
featureId,
|
|
701
|
+
role: InteractiveMessageRole.user,
|
|
702
|
+
content,
|
|
703
|
+
createdAt: now,
|
|
704
|
+
updatedAt: now,
|
|
705
|
+
};
|
|
706
|
+
await this.messageRepo.create(userMsg);
|
|
707
|
+
// 2. Find active session for this feature
|
|
708
|
+
let state = this.findActiveStateForFeature(featureId);
|
|
709
|
+
// If the caller requested a different model/agent than the running session,
|
|
710
|
+
// silently stop the current session so a new one boots with the new config.
|
|
711
|
+
// Also clear the cached agentSessionId so we create a fresh SDK session
|
|
712
|
+
// instead of resuming the old one (which would keep the old model).
|
|
713
|
+
if (state && model && state.model !== model) {
|
|
714
|
+
await this.stopSession(state.sessionId);
|
|
715
|
+
this.stoppedAgentSessionIds.delete(featureId);
|
|
716
|
+
state = undefined;
|
|
717
|
+
}
|
|
718
|
+
else if (state && agentType && state.agentType !== agentType) {
|
|
719
|
+
await this.stopSession(state.sessionId);
|
|
720
|
+
this.stoppedAgentSessionIds.delete(featureId);
|
|
721
|
+
state = undefined;
|
|
722
|
+
}
|
|
723
|
+
if (state) {
|
|
724
|
+
const dbSession = await this.sessionRepo.findById(state.sessionId);
|
|
725
|
+
if (dbSession?.status === InteractiveSessionStatus.ready) {
|
|
726
|
+
// Session ready — send to agent (guarded: one turn at a time)
|
|
727
|
+
this.resetTimer(state);
|
|
728
|
+
await this.sessionRepo.updateLastActivity(state.sessionId, now);
|
|
729
|
+
if (state.turnInProgress) {
|
|
730
|
+
state.turnQueue.push(content);
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
state.turnInProgress = true;
|
|
734
|
+
void this.executeAndPersistTurn(state, content);
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
else if (dbSession?.status === InteractiveSessionStatus.booting) {
|
|
738
|
+
// Session booting — queue the message
|
|
739
|
+
state.pendingUserContent = content;
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
// No in-memory session — check DB for an orphaned active session (e.g. after
|
|
744
|
+
// service restart / hot-reload) and mark it stopped before booting a new one.
|
|
745
|
+
// The agentSessionId is persisted in DB so startSession will pick it up for
|
|
746
|
+
// SDK session resumption.
|
|
747
|
+
const dbSession = await this.sessionRepo.findByFeatureId(featureId);
|
|
748
|
+
if (dbSession &&
|
|
749
|
+
(dbSession.status === InteractiveSessionStatus.ready ||
|
|
750
|
+
dbSession.status === InteractiveSessionStatus.booting)) {
|
|
751
|
+
await this.sessionRepo.updateStatus(dbSession.id, InteractiveSessionStatus.stopped, new Date());
|
|
752
|
+
}
|
|
753
|
+
// Boot a new session — startSession will find the agentSessionId from DB
|
|
754
|
+
const session = await this.startSession(featureId, worktreePath, model, agentType);
|
|
755
|
+
const newState = this.sessions.get(session.id);
|
|
756
|
+
if (newState) {
|
|
757
|
+
newState.pendingUserContent = content;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
return userMsg;
|
|
78
761
|
}
|
|
79
762
|
async getChatState(featureId) {
|
|
80
|
-
|
|
763
|
+
// DB messages
|
|
764
|
+
const messages = await this.messageRepo.findByFeatureId(featureId);
|
|
765
|
+
// Find active in-memory session
|
|
766
|
+
const state = this.findActiveStateForFeature(featureId);
|
|
767
|
+
let sessionStatus = null;
|
|
768
|
+
let streamingText = null;
|
|
769
|
+
let sessionInfo = null;
|
|
770
|
+
if (state) {
|
|
771
|
+
const dbSession = await this.sessionRepo.findById(state.sessionId);
|
|
772
|
+
sessionStatus = dbSession?.status ?? null;
|
|
773
|
+
if (state.currentAssistantBuffer) {
|
|
774
|
+
streamingText = state.currentAssistantBuffer;
|
|
775
|
+
}
|
|
776
|
+
// Resolve model display: explicit override > default
|
|
777
|
+
const displayModel = state.model ?? 'claude-sonnet-4-6';
|
|
778
|
+
const usage = await this.sessionRepo.getUsage(state.sessionId);
|
|
779
|
+
sessionInfo = {
|
|
780
|
+
pid: null, // SDK manages process internally
|
|
781
|
+
sessionId: state.agentSessionId ?? state.sessionId,
|
|
782
|
+
model: displayModel,
|
|
783
|
+
startedAt: dbSession?.startedAt
|
|
784
|
+
? new Date(dbSession.startedAt).toISOString()
|
|
785
|
+
: new Date().toISOString(),
|
|
786
|
+
idleTimeoutMinutes: Math.round(this.getTimeoutMs() / 60_000),
|
|
787
|
+
lastActivityAt: dbSession?.lastActivityAt
|
|
788
|
+
? new Date(dbSession.lastActivityAt).toISOString()
|
|
789
|
+
: new Date().toISOString(),
|
|
790
|
+
totalCostUsd: usage?.totalCostUsd ?? null,
|
|
791
|
+
totalInputTokens: usage?.totalInputTokens ?? null,
|
|
792
|
+
totalOutputTokens: usage?.totalOutputTokens ?? null,
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
// No in-memory state — check DB for last session (e.g. after server restart / hot-reload)
|
|
797
|
+
const latest = await this.sessionRepo.findByFeatureId(featureId);
|
|
798
|
+
if (latest) {
|
|
799
|
+
sessionStatus = latest.status;
|
|
800
|
+
// Show DB info even without live process (process was lost on restart)
|
|
801
|
+
if (latest.status !== InteractiveSessionStatus.stopped &&
|
|
802
|
+
latest.status !== InteractiveSessionStatus.error) {
|
|
803
|
+
const latestUsage = await this.sessionRepo.getUsage(latest.id);
|
|
804
|
+
sessionInfo = {
|
|
805
|
+
pid: null,
|
|
806
|
+
sessionId: latest.id,
|
|
807
|
+
model: null,
|
|
808
|
+
startedAt: latest.startedAt
|
|
809
|
+
? new Date(latest.startedAt).toISOString()
|
|
810
|
+
: new Date().toISOString(),
|
|
811
|
+
idleTimeoutMinutes: Math.round(this.getTimeoutMs() / 60_000),
|
|
812
|
+
lastActivityAt: latest.lastActivityAt
|
|
813
|
+
? new Date(latest.lastActivityAt).toISOString()
|
|
814
|
+
: new Date().toISOString(),
|
|
815
|
+
totalCostUsd: latestUsage?.totalCostUsd ?? null,
|
|
816
|
+
totalInputTokens: latestUsage?.totalInputTokens ?? null,
|
|
817
|
+
totalOutputTokens: latestUsage?.totalOutputTokens ?? null,
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
// Resolve turn status from DB
|
|
823
|
+
let turnStatus = 'idle';
|
|
824
|
+
const activeState = state;
|
|
825
|
+
if (activeState) {
|
|
826
|
+
const statuses = await this.sessionRepo.getTurnStatuses([featureId]);
|
|
827
|
+
turnStatus = statuses.get(featureId) ?? 'idle';
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
// Check DB for the latest session's turn status
|
|
831
|
+
const latest = await this.sessionRepo.findByFeatureId(featureId);
|
|
832
|
+
if (latest) {
|
|
833
|
+
const statuses = await this.sessionRepo.getTurnStatuses([featureId]);
|
|
834
|
+
turnStatus = statuses.get(featureId) ?? 'idle';
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
// Include pending interaction if one exists
|
|
838
|
+
const pendingInteraction = state?.pendingInteraction ?? null;
|
|
839
|
+
return { messages, sessionStatus, streamingText, sessionInfo, turnStatus, pendingInteraction };
|
|
81
840
|
}
|
|
82
841
|
subscribeByFeature(featureId, onChunk) {
|
|
83
|
-
|
|
842
|
+
// Subscribe at the feature level so the callback survives session restarts.
|
|
843
|
+
// When a session dies (idle timeout, error) and a new one boots, the SSE
|
|
844
|
+
// connection keeps receiving events from the new session automatically.
|
|
845
|
+
let subs = this.featureSubscribers.get(featureId);
|
|
846
|
+
if (!subs) {
|
|
847
|
+
subs = new Set();
|
|
848
|
+
this.featureSubscribers.set(featureId, subs);
|
|
849
|
+
}
|
|
850
|
+
subs.add(onChunk);
|
|
851
|
+
return () => {
|
|
852
|
+
subs.delete(onChunk);
|
|
853
|
+
if (subs.size === 0) {
|
|
854
|
+
this.featureSubscribers.delete(featureId);
|
|
855
|
+
}
|
|
856
|
+
};
|
|
84
857
|
}
|
|
85
858
|
async stopByFeature(featureId) {
|
|
86
|
-
|
|
859
|
+
const state = this.findActiveStateForFeature(featureId);
|
|
860
|
+
if (!state)
|
|
861
|
+
return;
|
|
862
|
+
await this.stopSession(state.sessionId);
|
|
87
863
|
}
|
|
88
864
|
async markRead(featureId) {
|
|
89
|
-
|
|
865
|
+
// Find the active session for this feature and clear unread status
|
|
866
|
+
const state = this.findActiveStateForFeature(featureId);
|
|
867
|
+
if (state) {
|
|
868
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'idle');
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
// Fallback: check DB for the latest active session
|
|
872
|
+
const latest = await this.sessionRepo.findByFeatureId(featureId);
|
|
873
|
+
if (latest) {
|
|
874
|
+
void this.sessionRepo.updateTurnStatus(latest.id, 'idle');
|
|
875
|
+
}
|
|
90
876
|
}
|
|
91
877
|
async getTurnStatuses(featureIds) {
|
|
92
|
-
return this.
|
|
878
|
+
return this.sessionRepo.getTurnStatuses(featureIds);
|
|
93
879
|
}
|
|
94
880
|
async getAllActiveTurnStatuses() {
|
|
95
|
-
return this.
|
|
881
|
+
return this.sessionRepo.getAllActiveTurnStatuses();
|
|
96
882
|
}
|
|
97
883
|
async respondToInteraction(featureId, answers) {
|
|
98
|
-
|
|
884
|
+
const state = this.findActiveStateForFeature(featureId);
|
|
885
|
+
if (!state?.pendingInteraction || !state.pendingInteractionResolver) {
|
|
886
|
+
throw new Error(`No pending interaction for feature ${featureId}`);
|
|
887
|
+
}
|
|
888
|
+
// Persist the user's answers as a structured user message.
|
|
889
|
+
// The {{interaction}} prefix lets the frontend detect and render it
|
|
890
|
+
// as a compact green bubble instead of a regular text message.
|
|
891
|
+
const interactionPayload = {
|
|
892
|
+
questions: state.pendingInteraction.questions.map((q) => ({
|
|
893
|
+
header: q.header,
|
|
894
|
+
question: q.question,
|
|
895
|
+
})),
|
|
896
|
+
answers,
|
|
897
|
+
};
|
|
898
|
+
const now = new Date();
|
|
899
|
+
const userMsg = {
|
|
900
|
+
id: crypto.randomUUID(),
|
|
901
|
+
featureId: state.featureId,
|
|
902
|
+
sessionId: state.sessionId,
|
|
903
|
+
role: InteractiveMessageRole.user,
|
|
904
|
+
content: `{{interaction}}${JSON.stringify(interactionPayload)}`,
|
|
905
|
+
createdAt: now,
|
|
906
|
+
updatedAt: now,
|
|
907
|
+
};
|
|
908
|
+
await this.messageRepo.create(userMsg);
|
|
909
|
+
// Resolve the Promise that the canUseTool callback is awaiting.
|
|
910
|
+
// This unblocks the SDK stream — the agent resumes with the user's answers.
|
|
911
|
+
state.pendingInteractionResolver(answers);
|
|
912
|
+
// Clear pending interaction state
|
|
913
|
+
state.pendingInteraction = null;
|
|
914
|
+
state.pendingInteractionResolver = null;
|
|
915
|
+
// Update turn status back to processing
|
|
916
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'processing');
|
|
917
|
+
// Clear the "Waiting for your response..." log
|
|
918
|
+
state.subscribers.forEach((sub) => sub({ delta: '', done: false }));
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* Build the onUserQuestion callback for a session.
|
|
922
|
+
* Called by the SDK's canUseTool when the agent invokes AskUserQuestion.
|
|
923
|
+
* Returns a Promise that doesn't resolve until the user submits their answers.
|
|
924
|
+
*/
|
|
925
|
+
buildOnUserQuestionCallback(state) {
|
|
926
|
+
return async (interaction) => {
|
|
927
|
+
// Flush any accumulated assistant text as a separate message BEFORE
|
|
928
|
+
// the interaction. This ensures the agent's question text appears
|
|
929
|
+
// above the green answer bubble in the conversation history.
|
|
930
|
+
if (state.currentAssistantBuffer.trim()) {
|
|
931
|
+
const now = new Date();
|
|
932
|
+
const msg = {
|
|
933
|
+
id: crypto.randomUUID(),
|
|
934
|
+
featureId: state.featureId,
|
|
935
|
+
sessionId: state.sessionId,
|
|
936
|
+
role: InteractiveMessageRole.assistant,
|
|
937
|
+
content: state.currentAssistantBuffer,
|
|
938
|
+
createdAt: now,
|
|
939
|
+
updatedAt: now,
|
|
940
|
+
};
|
|
941
|
+
await this.messageRepo.create(msg);
|
|
942
|
+
state.currentAssistantBuffer = '';
|
|
943
|
+
state.toolEventsLog = [];
|
|
944
|
+
// Notify subscribers so the frontend picks up the new message
|
|
945
|
+
state.subscribers.forEach((sub) => sub({ delta: '', done: true }));
|
|
946
|
+
// Small delay so the refetch completes before the interaction appears
|
|
947
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
948
|
+
}
|
|
949
|
+
// Store the interaction data for the frontend
|
|
950
|
+
state.pendingInteraction = interaction;
|
|
951
|
+
// Update turn status so the dot indicator shows amber
|
|
952
|
+
void this.sessionRepo.updateTurnStatus(state.sessionId, 'awaiting_input');
|
|
953
|
+
// Notify subscribers so SSE pushes the interaction to the frontend
|
|
954
|
+
state.subscribers.forEach((sub) => sub({
|
|
955
|
+
delta: '',
|
|
956
|
+
done: false,
|
|
957
|
+
log: 'Waiting for your response...',
|
|
958
|
+
interaction,
|
|
959
|
+
}));
|
|
960
|
+
// Create a Promise that will be resolved when the user calls respondToInteraction
|
|
961
|
+
return new Promise((resolve) => {
|
|
962
|
+
state.pendingInteractionResolver = resolve;
|
|
963
|
+
});
|
|
964
|
+
};
|
|
965
|
+
}
|
|
966
|
+
/** Find the in-memory state for an active session for a feature. */
|
|
967
|
+
findActiveStateForFeature(featureId) {
|
|
968
|
+
for (const state of this.sessions.values()) {
|
|
969
|
+
if (state.featureId === featureId)
|
|
970
|
+
return state;
|
|
971
|
+
}
|
|
972
|
+
return undefined;
|
|
973
|
+
}
|
|
974
|
+
// ---------------------------------------------------------------------------
|
|
975
|
+
// Agent resolution helpers
|
|
976
|
+
// ---------------------------------------------------------------------------
|
|
977
|
+
/** Resolve the agent type from an explicit override or settings. */
|
|
978
|
+
resolveAgentType(agentTypeOverride) {
|
|
979
|
+
if (agentTypeOverride) {
|
|
980
|
+
return agentTypeOverride;
|
|
981
|
+
}
|
|
982
|
+
if (hasSettings()) {
|
|
983
|
+
return getSettings().agent.type;
|
|
984
|
+
}
|
|
985
|
+
return AgentType.ClaudeCode;
|
|
986
|
+
}
|
|
987
|
+
/** Resolve the auth config from settings, with a safe fallback. */
|
|
988
|
+
resolveAuthConfig() {
|
|
989
|
+
if (hasSettings()) {
|
|
990
|
+
return getSettings().agent;
|
|
991
|
+
}
|
|
992
|
+
// Fallback for when settings haven't been initialized yet
|
|
993
|
+
return {
|
|
994
|
+
type: AgentType.ClaudeCode,
|
|
995
|
+
authMethod: AgentAuthMethod.Session,
|
|
996
|
+
};
|
|
997
|
+
}
|
|
998
|
+
// ---------------------------------------------------------------------------
|
|
999
|
+
// Tool detail extraction
|
|
1000
|
+
// ---------------------------------------------------------------------------
|
|
1001
|
+
/**
|
|
1002
|
+
* Persist a tool/system event as its own assistant message in the DB.
|
|
1003
|
+
* Each event gets its own bubble in the chat thread.
|
|
1004
|
+
*/
|
|
1005
|
+
async persistToolEvent(state, label, detail) {
|
|
1006
|
+
try {
|
|
1007
|
+
const content = detail ? `**${label}** \`${detail}\`` : `**${label}**`;
|
|
1008
|
+
const msg = {
|
|
1009
|
+
id: crypto.randomUUID(),
|
|
1010
|
+
featureId: state.featureId,
|
|
1011
|
+
sessionId: state.sessionId,
|
|
1012
|
+
role: InteractiveMessageRole.assistant,
|
|
1013
|
+
content,
|
|
1014
|
+
createdAt: new Date(),
|
|
1015
|
+
updatedAt: new Date(),
|
|
1016
|
+
};
|
|
1017
|
+
await this.messageRepo.create(msg);
|
|
1018
|
+
}
|
|
1019
|
+
catch {
|
|
1020
|
+
// Non-critical — don't fail the turn for a tool event
|
|
1021
|
+
}
|
|
99
1022
|
}
|
|
100
1023
|
// ---------------------------------------------------------------------------
|
|
101
|
-
//
|
|
1024
|
+
// Event dispatch
|
|
1025
|
+
// ---------------------------------------------------------------------------
|
|
1026
|
+
/**
|
|
1027
|
+
* Dispatch a StreamChunk to all subscribers for a session.
|
|
1028
|
+
*
|
|
1029
|
+
* Sends to both session-level subscribers (legacy, for sessionId-based
|
|
1030
|
+
* subscribe()) and feature-level subscribers (for SSE connections that
|
|
1031
|
+
* must survive session restarts).
|
|
1032
|
+
*/
|
|
1033
|
+
notify(state, chunk) {
|
|
1034
|
+
state.subscribers.forEach((sub) => sub(chunk));
|
|
1035
|
+
const featureSubs = this.featureSubscribers.get(state.featureId);
|
|
1036
|
+
if (featureSubs) {
|
|
1037
|
+
featureSubs.forEach((sub) => sub(chunk));
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
// ---------------------------------------------------------------------------
|
|
1041
|
+
// Timer helpers
|
|
102
1042
|
// ---------------------------------------------------------------------------
|
|
103
1043
|
/** Start or restart the idle timeout timer for a session. */
|
|
104
1044
|
resetTimer(state) {
|
|
@@ -123,4 +1063,11 @@ export class InteractiveSessionService {
|
|
|
123
1063
|
const minutes = settings.interactiveAgent?.autoTimeoutMinutes ?? 15;
|
|
124
1064
|
return minutes * 60 * 1000;
|
|
125
1065
|
}
|
|
1066
|
+
/** Read the concurrent session cap from settings or fall back to default. */
|
|
1067
|
+
getCap() {
|
|
1068
|
+
if (!hasSettings())
|
|
1069
|
+
return DEFAULT_CAP;
|
|
1070
|
+
const settings = getSettings();
|
|
1071
|
+
return settings.interactiveAgent?.maxConcurrentSessions ?? DEFAULT_CAP;
|
|
1072
|
+
}
|
|
126
1073
|
}
|