@itphx/synth-core 0.2.0 → 0.4.4
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/definitions/protected-paths.json +36 -0
- package/definitions/shell-policy.json +36 -0
- package/dist/auth/local.d.ts +14 -0
- package/dist/auth/local.d.ts.map +1 -1
- package/dist/auth/local.js +63 -11
- package/dist/auth/local.js.map +1 -1
- package/dist/auth/local.test.js +59 -0
- package/dist/auth/local.test.js.map +1 -1
- package/dist/definitions/protected-paths.json +36 -0
- package/dist/definitions/shell-policy.json +36 -0
- package/dist/engine/agents/definitions/admin.json +3 -1
- package/dist/engine/agents/definitions/analyst.json +3 -1
- package/dist/engine/agents/definitions/assistant.json +2 -2
- package/dist/engine/agents/definitions/auditor.json +4 -1
- package/dist/engine/agents/definitions/developer.json +4 -1
- package/dist/engine/agents/definitions/devops.json +4 -1
- package/dist/engine/agents/definitions/explore.json +3 -3
- package/dist/engine/agents/definitions/general.json +2 -2
- package/dist/engine/agents/definitions/pm.json +5 -1
- package/dist/engine/agents/definitions/qa.json +4 -1
- package/dist/engine/agents/definitions/title.json +2 -2
- package/dist/engine/agents/index.d.ts +4 -0
- package/dist/engine/agents/index.d.ts.map +1 -1
- package/dist/engine/agents/index.js +9 -3
- package/dist/engine/agents/index.js.map +1 -1
- package/dist/engine/agents/mode.d.ts +5 -3
- package/dist/engine/agents/mode.d.ts.map +1 -1
- package/dist/engine/agents/mode.js +6 -6
- package/dist/engine/agents/mode.js.map +1 -1
- package/dist/engine/agents/mode.test.js +9 -3
- package/dist/engine/agents/mode.test.js.map +1 -1
- package/dist/engine/agents/normalize.d.ts +9 -0
- package/dist/engine/agents/normalize.d.ts.map +1 -0
- package/dist/engine/agents/normalize.js +22 -0
- package/dist/engine/agents/normalize.js.map +1 -0
- package/dist/engine/agents/normalize.test.d.ts +2 -0
- package/dist/engine/agents/normalize.test.d.ts.map +1 -0
- package/dist/engine/agents/normalize.test.js +37 -0
- package/dist/engine/agents/normalize.test.js.map +1 -0
- package/dist/engine/agents/registry.d.ts +2 -1
- package/dist/engine/agents/registry.d.ts.map +1 -1
- package/dist/engine/agents/registry.js +7 -6
- package/dist/engine/agents/registry.js.map +1 -1
- package/dist/engine/agents/registry.test.js +24 -0
- package/dist/engine/agents/registry.test.js.map +1 -1
- package/dist/engine/context/config.d.ts +43 -6
- package/dist/engine/context/config.d.ts.map +1 -1
- package/dist/engine/context/config.js +123 -26
- package/dist/engine/context/config.js.map +1 -1
- package/dist/engine/context/config.security.test.d.ts +2 -0
- package/dist/engine/context/config.security.test.d.ts.map +1 -0
- package/dist/engine/context/config.security.test.js +82 -0
- package/dist/engine/context/config.security.test.js.map +1 -0
- package/dist/engine/context/config.test.js +199 -10
- package/dist/engine/context/config.test.js.map +1 -1
- package/dist/engine/context/optimizer.d.ts +20 -1
- package/dist/engine/context/optimizer.d.ts.map +1 -1
- package/dist/engine/context/optimizer.js +63 -29
- package/dist/engine/context/optimizer.js.map +1 -1
- package/dist/engine/context/optimizer.test.js +156 -0
- package/dist/engine/context/optimizer.test.js.map +1 -1
- package/dist/engine/gateway/gateway-provider.d.ts +4 -0
- package/dist/engine/gateway/gateway-provider.d.ts.map +1 -1
- package/dist/engine/gateway/gateway-provider.js +7 -2
- package/dist/engine/gateway/gateway-provider.js.map +1 -1
- package/dist/engine/gateway/gateway-provider.test.js +3 -3
- package/dist/engine/gateway/gateway-provider.test.js.map +1 -1
- package/dist/engine/gateway/input-guard.d.ts.map +1 -1
- package/dist/engine/gateway/input-guard.js +2 -1
- package/dist/engine/gateway/input-guard.js.map +1 -1
- package/dist/engine/gateway/secret-detector.d.ts.map +1 -1
- package/dist/engine/gateway/secret-detector.js +2 -3
- package/dist/engine/gateway/secret-detector.js.map +1 -1
- package/dist/engine/gateway/secret-detector.test.js +4 -4
- package/dist/engine/gateway/secret-detector.test.js.map +1 -1
- package/dist/engine/llm-error.d.ts +23 -0
- package/dist/engine/llm-error.d.ts.map +1 -0
- package/dist/engine/llm-error.js +86 -0
- package/dist/engine/llm-error.js.map +1 -0
- package/dist/engine/llm-error.test.d.ts +2 -0
- package/dist/engine/llm-error.test.d.ts.map +1 -0
- package/dist/engine/llm-error.test.js +101 -0
- package/dist/engine/llm-error.test.js.map +1 -0
- package/dist/engine/orchestrator-deny-abort.test.d.ts +2 -0
- package/dist/engine/orchestrator-deny-abort.test.d.ts.map +1 -0
- package/dist/engine/orchestrator-deny-abort.test.js +414 -0
- package/dist/engine/orchestrator-deny-abort.test.js.map +1 -0
- package/dist/engine/orchestrator-error.test.d.ts +2 -0
- package/dist/engine/orchestrator-error.test.d.ts.map +1 -0
- package/dist/engine/orchestrator-error.test.js +136 -0
- package/dist/engine/orchestrator-error.test.js.map +1 -0
- package/dist/engine/orchestrator.d.ts +123 -10
- package/dist/engine/orchestrator.d.ts.map +1 -1
- package/dist/engine/orchestrator.js +791 -181
- package/dist/engine/orchestrator.js.map +1 -1
- package/dist/engine/orchestrator.test.js +723 -0
- package/dist/engine/orchestrator.test.js.map +1 -1
- package/dist/engine/permission/approval.d.ts.map +1 -1
- package/dist/engine/permission/approval.js +29 -10
- package/dist/engine/permission/approval.js.map +1 -1
- package/dist/engine/permission/approval.test.js +57 -0
- package/dist/engine/permission/approval.test.js.map +1 -1
- package/dist/engine/permission/evaluator.d.ts +13 -0
- package/dist/engine/permission/evaluator.d.ts.map +1 -1
- package/dist/engine/permission/evaluator.js +121 -22
- package/dist/engine/permission/evaluator.js.map +1 -1
- package/dist/engine/permission/evaluator.test.js +188 -4
- package/dist/engine/permission/evaluator.test.js.map +1 -1
- package/dist/engine/permission/groups.d.ts.map +1 -1
- package/dist/engine/permission/groups.js +19 -1
- package/dist/engine/permission/groups.js.map +1 -1
- package/dist/engine/permission/integration.test.js +165 -4
- package/dist/engine/permission/integration.test.js.map +1 -1
- package/dist/engine/plan.integration.test.js +142 -33
- package/dist/engine/plan.integration.test.js.map +1 -1
- package/dist/engine/router/micro/tasks/classify-intent.d.ts.map +1 -1
- package/dist/engine/router/micro/tasks/classify-intent.js +24 -18
- package/dist/engine/router/micro/tasks/classify-intent.js.map +1 -1
- package/dist/engine/router/micro/tasks/classify-intent.test.js +4 -4
- package/dist/engine/router/micro/tasks/classify-intent.test.js.map +1 -1
- package/dist/engine/router/micro/tasks/enum-decision.d.ts.map +1 -1
- package/dist/engine/router/micro/tasks/enum-decision.js +14 -8
- package/dist/engine/router/micro/tasks/enum-decision.js.map +1 -1
- package/dist/engine/router/micro/tasks/enum-decision.test.js +2 -2
- package/dist/engine/router/micro/tasks/enum-decision.test.js.map +1 -1
- package/dist/engine/router/micro/tasks/small-talk.d.ts.map +1 -1
- package/dist/engine/router/micro/tasks/small-talk.js +20 -17
- package/dist/engine/router/micro/tasks/small-talk.js.map +1 -1
- package/dist/engine/router/micro/types.d.ts +2 -0
- package/dist/engine/router/micro/types.d.ts.map +1 -1
- package/dist/engine/router/provider-pool.d.ts +2 -2
- package/dist/engine/router/provider-pool.d.ts.map +1 -1
- package/dist/engine/router/provider-pool.js +5 -3
- package/dist/engine/router/provider-pool.js.map +1 -1
- package/dist/engine/router/quality-checker.d.ts.map +1 -1
- package/dist/engine/router/quality-checker.js +15 -14
- package/dist/engine/router/quality-checker.js.map +1 -1
- package/dist/engine/router/router.d.ts +2 -2
- package/dist/engine/router/router.d.ts.map +1 -1
- package/dist/engine/router/router.js +8 -5
- package/dist/engine/router/router.js.map +1 -1
- package/dist/engine/router/utils.d.ts +2 -2
- package/dist/engine/router/utils.d.ts.map +1 -1
- package/dist/engine/router/utils.js +2 -1
- package/dist/engine/router/utils.js.map +1 -1
- package/dist/engine/security/index.d.ts +6 -0
- package/dist/engine/security/index.d.ts.map +1 -1
- package/dist/engine/security/index.js +3 -0
- package/dist/engine/security/index.js.map +1 -1
- package/dist/engine/security/integration.test.js +11 -11
- package/dist/engine/security/integration.test.js.map +1 -1
- package/dist/engine/security/prompt-injection.d.ts +1 -1
- package/dist/engine/security/prompt-injection.d.ts.map +1 -1
- package/dist/engine/security/prompt-injection.js +2 -1
- package/dist/engine/security/prompt-injection.js.map +1 -1
- package/dist/engine/security/prompt-injection.test.js +1 -1
- package/dist/engine/security/prompt-injection.test.js.map +1 -1
- package/dist/engine/security/protected-paths-store.d.ts +56 -0
- package/dist/engine/security/protected-paths-store.d.ts.map +1 -0
- package/dist/engine/security/protected-paths-store.js +239 -0
- package/dist/engine/security/protected-paths-store.js.map +1 -0
- package/dist/engine/security/protected-paths.d.ts +54 -0
- package/dist/engine/security/protected-paths.d.ts.map +1 -0
- package/dist/engine/security/protected-paths.js +193 -0
- package/dist/engine/security/protected-paths.js.map +1 -0
- package/dist/engine/security/protected-paths.test.d.ts +2 -0
- package/dist/engine/security/protected-paths.test.d.ts.map +1 -0
- package/dist/engine/security/protected-paths.test.js +166 -0
- package/dist/engine/security/protected-paths.test.js.map +1 -0
- package/dist/engine/security/shell-guard.d.ts +117 -0
- package/dist/engine/security/shell-guard.d.ts.map +1 -0
- package/dist/engine/security/shell-guard.js +578 -0
- package/dist/engine/security/shell-guard.js.map +1 -0
- package/dist/engine/security/shell-guard.test.d.ts +2 -0
- package/dist/engine/security/shell-guard.test.d.ts.map +1 -0
- package/dist/engine/security/shell-guard.test.js +378 -0
- package/dist/engine/security/shell-guard.test.js.map +1 -0
- package/dist/engine/system-messages.d.ts +237 -0
- package/dist/engine/system-messages.d.ts.map +1 -0
- package/dist/engine/system-messages.js +276 -0
- package/dist/engine/system-messages.js.map +1 -0
- package/dist/engine/system-messages.test.d.ts +2 -0
- package/dist/engine/system-messages.test.d.ts.map +1 -0
- package/dist/engine/system-messages.test.js +81 -0
- package/dist/engine/system-messages.test.js.map +1 -0
- package/dist/engine/tools/abort.d.ts +21 -0
- package/dist/engine/tools/abort.d.ts.map +1 -0
- package/dist/engine/tools/abort.js +44 -0
- package/dist/engine/tools/abort.js.map +1 -0
- package/dist/engine/tools/classify-conversation.d.ts.map +1 -1
- package/dist/engine/tools/classify-conversation.js +7 -2
- package/dist/engine/tools/classify-conversation.js.map +1 -1
- package/dist/engine/tools/fs-read.d.ts.map +1 -1
- package/dist/engine/tools/fs-read.js +17 -6
- package/dist/engine/tools/fs-read.js.map +1 -1
- package/dist/engine/tools/fs-read.test.js +43 -0
- package/dist/engine/tools/fs-read.test.js.map +1 -1
- package/dist/engine/tools/fs-write.d.ts.map +1 -1
- package/dist/engine/tools/fs-write.js +47 -17
- package/dist/engine/tools/fs-write.js.map +1 -1
- package/dist/engine/tools/git.d.ts +2 -1
- package/dist/engine/tools/git.d.ts.map +1 -1
- package/dist/engine/tools/git.js +85 -17
- package/dist/engine/tools/git.js.map +1 -1
- package/dist/engine/tools/git.test.js +39 -0
- package/dist/engine/tools/git.test.js.map +1 -1
- package/dist/engine/tools/index.d.ts.map +1 -1
- package/dist/engine/tools/index.js +16 -2
- package/dist/engine/tools/index.js.map +1 -1
- package/dist/engine/tools/json-schema.js +38 -0
- package/dist/engine/tools/json-schema.js.map +1 -1
- package/dist/engine/tools/json-schema.test.d.ts +2 -0
- package/dist/engine/tools/json-schema.test.d.ts.map +1 -0
- package/dist/engine/tools/json-schema.test.js +40 -0
- package/dist/engine/tools/json-schema.test.js.map +1 -0
- package/dist/engine/tools/path-utils.d.ts.map +1 -1
- package/dist/engine/tools/path-utils.js +24 -0
- package/dist/engine/tools/path-utils.js.map +1 -1
- package/dist/engine/tools/path-utils.test.js +15 -0
- package/dist/engine/tools/path-utils.test.js.map +1 -1
- package/dist/engine/tools/plan.d.ts +11 -3
- package/dist/engine/tools/plan.d.ts.map +1 -1
- package/dist/engine/tools/plan.js +326 -95
- package/dist/engine/tools/plan.js.map +1 -1
- package/dist/engine/tools/plan.test.js +161 -47
- package/dist/engine/tools/plan.test.js.map +1 -1
- package/dist/engine/tools/project-context.d.ts.map +1 -1
- package/dist/engine/tools/project-context.js +54 -42
- package/dist/engine/tools/project-context.js.map +1 -1
- package/dist/engine/tools/project-context.test.js +37 -22
- package/dist/engine/tools/project-context.test.js.map +1 -1
- package/dist/engine/tools/project-manage.d.ts +24 -0
- package/dist/engine/tools/project-manage.d.ts.map +1 -0
- package/dist/engine/tools/project-manage.js +311 -0
- package/dist/engine/tools/project-manage.js.map +1 -0
- package/dist/engine/tools/project-manage.test.d.ts +2 -0
- package/dist/engine/tools/project-manage.test.d.ts.map +1 -0
- package/dist/engine/tools/project-manage.test.js +196 -0
- package/dist/engine/tools/project-manage.test.js.map +1 -0
- package/dist/engine/tools/read-reference.d.ts.map +1 -1
- package/dist/engine/tools/read-reference.js +10 -5
- package/dist/engine/tools/read-reference.js.map +1 -1
- package/dist/engine/tools/read-reference.test.js +5 -2
- package/dist/engine/tools/read-reference.test.js.map +1 -1
- package/dist/engine/tools/search.d.ts.map +1 -1
- package/dist/engine/tools/search.js +16 -6
- package/dist/engine/tools/search.js.map +1 -1
- package/dist/engine/tools/shell.d.ts.map +1 -1
- package/dist/engine/tools/shell.js +17 -4
- package/dist/engine/tools/shell.js.map +1 -1
- package/dist/engine/tools/shell.test.js +63 -1
- package/dist/engine/tools/shell.test.js.map +1 -1
- package/dist/engine/tools/task-resume.d.ts +93 -0
- package/dist/engine/tools/task-resume.d.ts.map +1 -0
- package/dist/engine/tools/task-resume.js +269 -0
- package/dist/engine/tools/task-resume.js.map +1 -0
- package/dist/engine/tools/task-resume.test.d.ts +2 -0
- package/dist/engine/tools/task-resume.test.d.ts.map +1 -0
- package/dist/engine/tools/task-resume.test.js +423 -0
- package/dist/engine/tools/task-resume.test.js.map +1 -0
- package/dist/engine/tools/task.d.ts +81 -2
- package/dist/engine/tools/task.d.ts.map +1 -1
- package/dist/engine/tools/task.js +898 -471
- package/dist/engine/tools/task.js.map +1 -1
- package/dist/engine/tools/task.test.js +371 -3
- package/dist/engine/tools/task.test.js.map +1 -1
- package/dist/engine/tools/todo.d.ts +27 -1
- package/dist/engine/tools/todo.d.ts.map +1 -1
- package/dist/engine/tools/todo.js +320 -14
- package/dist/engine/tools/todo.js.map +1 -1
- package/dist/engine/tools/todo.test.js +150 -48
- package/dist/engine/tools/todo.test.js.map +1 -1
- package/dist/engine/tools/web.d.ts.map +1 -1
- package/dist/engine/tools/web.js +65 -18
- package/dist/engine/tools/web.js.map +1 -1
- package/dist/engine/tools/web.test.js +94 -2
- package/dist/engine/tools/web.test.js.map +1 -1
- package/dist/events/bus.d.ts +7 -0
- package/dist/events/bus.d.ts.map +1 -1
- package/dist/events/bus.js +26 -3
- package/dist/events/bus.js.map +1 -1
- package/dist/events/bus.test.js +46 -0
- package/dist/events/bus.test.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +0 -1
- package/dist/logger.js.map +1 -1
- package/dist/main.js +250 -10
- package/dist/main.js.map +1 -1
- package/dist/prompts/roles/ADMIN.en.md +12 -11
- package/dist/prompts/roles/ADMIN.ru.md +12 -11
- package/dist/prompts/roles/ANALYST.en.md +12 -11
- package/dist/prompts/roles/ANALYST.ru.md +12 -11
- package/dist/prompts/roles/ASSISTANT.en.md +12 -11
- package/dist/prompts/roles/ASSISTANT.ru.md +12 -11
- package/dist/prompts/roles/AUDITOR.en.md +12 -11
- package/dist/prompts/roles/AUDITOR.ru.md +12 -11
- package/dist/prompts/roles/DEVELOPER.en.md +12 -11
- package/dist/prompts/roles/DEVELOPER.ru.md +12 -11
- package/dist/prompts/roles/DEVOPS.en.md +12 -11
- package/dist/prompts/roles/DEVOPS.ru.md +12 -11
- package/dist/prompts/roles/PM.en.md +12 -11
- package/dist/prompts/roles/PM.ru.md +12 -11
- package/dist/prompts/roles/QA.en.md +12 -11
- package/dist/prompts/roles/QA.ru.md +12 -11
- package/dist/prompts/roles/TITLE.en.md +30 -0
- package/dist/prompts/roles/TITLE.ru.md +3 -11
- package/dist/prompts/security/ask-protected-path.en.md +1 -0
- package/dist/prompts/security/ask-protected-path.ru.md +1 -0
- package/dist/prompts/security/deny-command.en.md +1 -0
- package/dist/prompts/security/deny-command.ru.md +1 -0
- package/dist/prompts/security/deny-protected-dir.en.md +1 -0
- package/dist/prompts/security/deny-protected-dir.ru.md +1 -0
- package/dist/prompts/security/deny-protected-path.en.md +1 -0
- package/dist/prompts/security/deny-protected-path.ru.md +1 -0
- package/dist/prompts/subagents/explore.en.md +23 -0
- package/dist/prompts/subagents/general.en.md +19 -0
- package/dist/prompts/system/MODE_ACT.en.md +20 -0
- package/{prompts/modes/act.md → dist/prompts/system/MODE_ACT.ru.md} +2 -0
- package/dist/prompts/system/MODE_PLAN.en.md +22 -0
- package/dist/prompts/{modes/plan.md → system/MODE_PLAN.ru.md} +4 -3
- package/dist/prompts/system/MODE_YOLO.en.md +22 -0
- package/{prompts/modes/yolo.md → dist/prompts/system/MODE_YOLO.ru.md} +2 -0
- package/dist/prompts/system/PLAN_GUIDE.en.md +36 -0
- package/dist/prompts/system/PLAN_GUIDE.ru.md +33 -0
- package/dist/prompts/system/PLAN_MODE_AUTO.en.md +11 -0
- package/dist/prompts/system/PLAN_MODE_AUTO.ru.md +12 -0
- package/dist/prompts/system/PLAN_MODE_STRICT_APPROVED.en.md +8 -0
- package/dist/prompts/system/PLAN_MODE_STRICT_APPROVED.ru.md +8 -0
- package/dist/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.en.md +7 -0
- package/dist/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.ru.md +7 -0
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +28 -2
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/base.d.ts +20 -1
- package/dist/providers/base.d.ts.map +1 -1
- package/dist/providers/base.js +17 -0
- package/dist/providers/base.js.map +1 -1
- package/dist/providers/exceptions.d.ts.map +1 -1
- package/dist/providers/exceptions.js +3 -2
- package/dist/providers/exceptions.js.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +4 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/ollama.d.ts +23 -0
- package/dist/providers/ollama.d.ts.map +1 -1
- package/dist/providers/ollama.js +128 -12
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/ollama.test.d.ts +2 -0
- package/dist/providers/ollama.test.d.ts.map +1 -0
- package/dist/providers/ollama.test.js +129 -0
- package/dist/providers/ollama.test.js.map +1 -0
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +82 -9
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openai.test.d.ts +2 -0
- package/dist/providers/openai.test.d.ts.map +1 -0
- package/dist/providers/openai.test.js +84 -0
- package/dist/providers/openai.test.js.map +1 -0
- package/dist/providers/remote.d.ts +60 -0
- package/dist/providers/remote.d.ts.map +1 -0
- package/dist/providers/remote.js +394 -0
- package/dist/providers/remote.js.map +1 -0
- package/dist/providers/remote.test.d.ts +2 -0
- package/dist/providers/remote.test.d.ts.map +1 -0
- package/dist/providers/remote.test.js +258 -0
- package/dist/providers/remote.test.js.map +1 -0
- package/dist/providers/stream-error.test.d.ts +2 -0
- package/dist/providers/stream-error.test.d.ts.map +1 -0
- package/dist/providers/stream-error.test.js +63 -0
- package/dist/providers/stream-error.test.js.map +1 -0
- package/dist/providers/timeout.test.d.ts +2 -0
- package/dist/providers/timeout.test.d.ts.map +1 -0
- package/dist/providers/timeout.test.js +129 -0
- package/dist/providers/timeout.test.js.map +1 -0
- package/dist/queue/processor.d.ts +22 -0
- package/dist/queue/processor.d.ts.map +1 -1
- package/dist/queue/processor.js +150 -25
- package/dist/queue/processor.js.map +1 -1
- package/dist/queue/processor.test.d.ts +2 -0
- package/dist/queue/processor.test.d.ts.map +1 -0
- package/dist/queue/processor.test.js +211 -0
- package/dist/queue/processor.test.js.map +1 -0
- package/dist/remote/aggregate.d.ts +43 -0
- package/dist/remote/aggregate.d.ts.map +1 -0
- package/dist/remote/aggregate.js +84 -0
- package/dist/remote/aggregate.js.map +1 -0
- package/dist/remote/aggregate.test.d.ts +2 -0
- package/dist/remote/aggregate.test.d.ts.map +1 -0
- package/dist/remote/aggregate.test.js +120 -0
- package/dist/remote/aggregate.test.js.map +1 -0
- package/dist/remote/client.d.ts +142 -0
- package/dist/remote/client.d.ts.map +1 -0
- package/dist/remote/client.js +290 -0
- package/dist/remote/client.js.map +1 -0
- package/dist/remote/client.test.d.ts +2 -0
- package/dist/remote/client.test.d.ts.map +1 -0
- package/dist/remote/client.test.js +176 -0
- package/dist/remote/client.test.js.map +1 -0
- package/dist/remote/connection.d.ts +66 -0
- package/dist/remote/connection.d.ts.map +1 -0
- package/dist/remote/connection.js +298 -0
- package/dist/remote/connection.js.map +1 -0
- package/dist/remote/connection.test.d.ts +2 -0
- package/dist/remote/connection.test.d.ts.map +1 -0
- package/dist/remote/connection.test.js +323 -0
- package/dist/remote/connection.test.js.map +1 -0
- package/dist/remote/credentials.d.ts +13 -0
- package/dist/remote/credentials.d.ts.map +1 -0
- package/dist/remote/credentials.js +81 -0
- package/dist/remote/credentials.js.map +1 -0
- package/dist/remote/credentials.test.d.ts +2 -0
- package/dist/remote/credentials.test.d.ts.map +1 -0
- package/dist/remote/credentials.test.js +69 -0
- package/dist/remote/credentials.test.js.map +1 -0
- package/dist/remote/device-flow.d.ts +72 -0
- package/dist/remote/device-flow.d.ts.map +1 -0
- package/dist/remote/device-flow.js +229 -0
- package/dist/remote/device-flow.js.map +1 -0
- package/dist/remote/device-flow.test.d.ts +2 -0
- package/dist/remote/device-flow.test.d.ts.map +1 -0
- package/dist/remote/device-flow.test.js +103 -0
- package/dist/remote/device-flow.test.js.map +1 -0
- package/dist/remote/event-bridge.d.ts +46 -0
- package/dist/remote/event-bridge.d.ts.map +1 -0
- package/dist/remote/event-bridge.js +218 -0
- package/dist/remote/event-bridge.js.map +1 -0
- package/dist/remote/event-bridge.test.d.ts +2 -0
- package/dist/remote/event-bridge.test.d.ts.map +1 -0
- package/dist/remote/event-bridge.test.js +240 -0
- package/dist/remote/event-bridge.test.js.map +1 -0
- package/dist/remote/index.d.ts +19 -0
- package/dist/remote/index.d.ts.map +1 -0
- package/dist/remote/index.js +11 -0
- package/dist/remote/index.js.map +1 -0
- package/dist/remote/session.d.ts +72 -0
- package/dist/remote/session.d.ts.map +1 -0
- package/dist/remote/session.js +248 -0
- package/dist/remote/session.js.map +1 -0
- package/dist/remote/session.test.d.ts +2 -0
- package/dist/remote/session.test.d.ts.map +1 -0
- package/dist/remote/session.test.js +482 -0
- package/dist/remote/session.test.js.map +1 -0
- package/dist/remote/transfer.d.ts +75 -0
- package/dist/remote/transfer.d.ts.map +1 -0
- package/dist/remote/transfer.js +491 -0
- package/dist/remote/transfer.js.map +1 -0
- package/dist/remote/transfer.test.d.ts +2 -0
- package/dist/remote/transfer.test.d.ts.map +1 -0
- package/dist/remote/transfer.test.js +416 -0
- package/dist/remote/transfer.test.js.map +1 -0
- package/dist/remote/types.d.ts +28 -0
- package/dist/remote/types.d.ts.map +1 -0
- package/dist/remote/types.js +10 -0
- package/dist/remote/types.js.map +1 -0
- package/dist/server/app.d.ts +62 -1
- package/dist/server/app.d.ts.map +1 -1
- package/dist/server/app.js +393 -27
- package/dist/server/app.js.map +1 -1
- package/dist/server/app.proxy.test.d.ts +2 -0
- package/dist/server/app.proxy.test.d.ts.map +1 -0
- package/dist/server/app.proxy.test.js +193 -0
- package/dist/server/app.proxy.test.js.map +1 -0
- package/dist/server/app.remote.test.d.ts +2 -0
- package/dist/server/app.remote.test.d.ts.map +1 -0
- package/dist/server/app.remote.test.js +674 -0
- package/dist/server/app.remote.test.js.map +1 -0
- package/dist/server/chat.d.ts.map +1 -1
- package/dist/server/chat.js +18 -2
- package/dist/server/chat.js.map +1 -1
- package/dist/server/proxy.d.ts +14 -0
- package/dist/server/proxy.d.ts.map +1 -0
- package/dist/server/proxy.js +93 -0
- package/dist/server/proxy.js.map +1 -0
- package/dist/server/routes/agents.d.ts.map +1 -1
- package/dist/server/routes/agents.js +39 -23
- package/dist/server/routes/agents.js.map +1 -1
- package/dist/server/routes/auth.d.ts +26 -2
- package/dist/server/routes/auth.d.ts.map +1 -1
- package/dist/server/routes/auth.js +269 -36
- package/dist/server/routes/auth.js.map +1 -1
- package/dist/server/routes/auth.test.d.ts +2 -0
- package/dist/server/routes/auth.test.d.ts.map +1 -0
- package/dist/server/routes/auth.test.js +466 -0
- package/dist/server/routes/auth.test.js.map +1 -0
- package/dist/server/routes/fs.d.ts +2 -1
- package/dist/server/routes/fs.d.ts.map +1 -1
- package/dist/server/routes/fs.js +340 -7
- package/dist/server/routes/fs.js.map +1 -1
- package/dist/server/routes/hybrid.d.ts +32 -0
- package/dist/server/routes/hybrid.d.ts.map +1 -0
- package/dist/server/routes/hybrid.js +21 -0
- package/dist/server/routes/hybrid.js.map +1 -0
- package/dist/server/routes/hybrid.test.d.ts +2 -0
- package/dist/server/routes/hybrid.test.d.ts.map +1 -0
- package/dist/server/routes/hybrid.test.js +454 -0
- package/dist/server/routes/hybrid.test.js.map +1 -0
- package/dist/server/routes/messages.d.ts +2 -1
- package/dist/server/routes/messages.d.ts.map +1 -1
- package/dist/server/routes/messages.js +104 -1
- package/dist/server/routes/messages.js.map +1 -1
- package/dist/server/routes/models.cache.test.d.ts +2 -0
- package/dist/server/routes/models.cache.test.d.ts.map +1 -0
- package/dist/server/routes/models.cache.test.js +59 -0
- package/dist/server/routes/models.cache.test.js.map +1 -0
- package/dist/server/routes/models.d.ts +9 -1
- package/dist/server/routes/models.d.ts.map +1 -1
- package/dist/server/routes/models.js +38 -3
- package/dist/server/routes/models.js.map +1 -1
- package/dist/server/routes/models.remote.test.d.ts +2 -0
- package/dist/server/routes/models.remote.test.d.ts.map +1 -0
- package/dist/server/routes/models.remote.test.js +101 -0
- package/dist/server/routes/models.remote.test.js.map +1 -0
- package/dist/server/routes/project-transfer.d.ts +16 -0
- package/dist/server/routes/project-transfer.d.ts.map +1 -0
- package/dist/server/routes/project-transfer.js +141 -0
- package/dist/server/routes/project-transfer.js.map +1 -0
- package/dist/server/routes/project-transfer.test.d.ts +2 -0
- package/dist/server/routes/project-transfer.test.d.ts.map +1 -0
- package/dist/server/routes/project-transfer.test.js +199 -0
- package/dist/server/routes/project-transfer.test.js.map +1 -0
- package/dist/server/routes/projects.d.ts +2 -1
- package/dist/server/routes/projects.d.ts.map +1 -1
- package/dist/server/routes/projects.js +101 -5
- package/dist/server/routes/projects.js.map +1 -1
- package/dist/server/routes/providers.d.ts +1 -1
- package/dist/server/routes/providers.d.ts.map +1 -1
- package/dist/server/routes/providers.js +3 -1
- package/dist/server/routes/providers.js.map +1 -1
- package/dist/server/routes/providers.test.d.ts +2 -0
- package/dist/server/routes/providers.test.d.ts.map +1 -0
- package/dist/server/routes/providers.test.js +58 -0
- package/dist/server/routes/providers.test.js.map +1 -0
- package/dist/server/routes/queue.d.ts +2 -1
- package/dist/server/routes/queue.d.ts.map +1 -1
- package/dist/server/routes/queue.js +180 -18
- package/dist/server/routes/queue.js.map +1 -1
- package/dist/server/routes/sessions.d.ts +9 -1
- package/dist/server/routes/sessions.d.ts.map +1 -1
- package/dist/server/routes/sessions.js +269 -18
- package/dist/server/routes/sessions.js.map +1 -1
- package/dist/server/routes/sessions.test.js +102 -2
- package/dist/server/routes/sessions.test.js.map +1 -1
- package/dist/server/routes/settings.d.ts +6 -1
- package/dist/server/routes/settings.d.ts.map +1 -1
- package/dist/server/routes/settings.js +138 -0
- package/dist/server/routes/settings.js.map +1 -1
- package/dist/server/routes/settings.test.js +65 -1
- package/dist/server/routes/settings.test.js.map +1 -1
- package/dist/server/serialize.d.ts +11 -3
- package/dist/server/serialize.d.ts.map +1 -1
- package/dist/server/serialize.js +11 -3
- package/dist/server/serialize.js.map +1 -1
- package/dist/sessions/auto-title.d.ts +1 -1
- package/dist/sessions/auto-title.d.ts.map +1 -1
- package/dist/sessions/auto-title.js +24 -13
- package/dist/sessions/auto-title.js.map +1 -1
- package/dist/sessions/manager.d.ts +1 -2
- package/dist/sessions/manager.d.ts.map +1 -1
- package/dist/sessions/manager.js +11 -36
- package/dist/sessions/manager.js.map +1 -1
- package/dist/sessions/manager.test.js +2 -10
- package/dist/sessions/manager.test.js.map +1 -1
- package/dist/storage/file-store.d.ts.map +1 -1
- package/dist/storage/file-store.js +2 -6
- package/dist/storage/file-store.js.map +1 -1
- package/dist/storage/file-store.test.js +1 -6
- package/dist/storage/file-store.test.js.map +1 -1
- package/dist/storage/project-store.d.ts.map +1 -1
- package/dist/storage/project-store.js +12 -0
- package/dist/storage/project-store.js.map +1 -1
- package/dist/storage/runtime-settings.d.ts +25 -1
- package/dist/storage/runtime-settings.d.ts.map +1 -1
- package/dist/storage/runtime-settings.js +31 -0
- package/dist/storage/runtime-settings.js.map +1 -1
- package/package.json +10 -5
- package/prompts/roles/TITLE.en.md +30 -0
- package/prompts/security/ask-protected-path.en.md +1 -0
- package/prompts/security/ask-protected-path.ru.md +1 -0
- package/prompts/security/deny-command.en.md +1 -0
- package/prompts/security/deny-command.ru.md +1 -0
- package/prompts/security/deny-protected-dir.en.md +1 -0
- package/prompts/security/deny-protected-dir.ru.md +1 -0
- package/prompts/security/deny-protected-path.en.md +1 -0
- package/prompts/security/deny-protected-path.ru.md +1 -0
- package/prompts/subagents/explore.en.md +23 -0
- package/prompts/subagents/general.en.md +19 -0
- package/prompts/system/MODE_ACT.en.md +20 -0
- package/{dist/prompts/modes/act.md → prompts/system/MODE_ACT.ru.md} +2 -0
- package/prompts/system/MODE_PLAN.en.md +22 -0
- package/{dist/prompts/prompts/modes/plan.md → prompts/system/MODE_PLAN.ru.md} +4 -3
- package/prompts/system/MODE_YOLO.en.md +22 -0
- package/{dist/prompts/prompts/modes/yolo.md → prompts/system/MODE_YOLO.ru.md} +2 -0
- package/prompts/system/PLAN_GUIDE.en.md +36 -0
- package/prompts/system/PLAN_GUIDE.ru.md +33 -0
- package/prompts/system/PLAN_MODE_AUTO.en.md +11 -0
- package/prompts/system/PLAN_MODE_AUTO.ru.md +12 -0
- package/prompts/system/PLAN_MODE_STRICT_APPROVED.en.md +8 -0
- package/prompts/system/PLAN_MODE_STRICT_APPROVED.ru.md +8 -0
- package/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.en.md +7 -0
- package/prompts/system/PLAN_MODE_STRICT_NOT_APPROVED.ru.md +7 -0
- package/dist/dictionaries/dictionaries/coding.en.yaml +0 -20
- package/dist/dictionaries/dictionaries/coding.ru.yaml +0 -22
- package/dist/dictionaries/dictionaries/coding.tools.yaml +0 -12
- package/dist/dictionaries/dictionaries/enum.en.yaml +0 -54
- package/dist/dictionaries/dictionaries/enum.ru.yaml +0 -67
- package/dist/dictionaries/dictionaries/injection.en.yaml +0 -51
- package/dist/dictionaries/dictionaries/injection.ru.yaml +0 -51
- package/dist/dictionaries/dictionaries/intents.en.yaml +0 -68
- package/dist/dictionaries/dictionaries/intents.ru.yaml +0 -78
- package/dist/dictionaries/dictionaries/research.en.yaml +0 -17
- package/dist/dictionaries/dictionaries/research.ru.yaml +0 -17
- package/dist/dictionaries/dictionaries/small-talk.en.yaml +0 -67
- package/dist/dictionaries/dictionaries/small-talk.ru.yaml +0 -81
- package/dist/prompts/modes/yolo.md +0 -20
- package/dist/prompts/prompts/modes/act.md +0 -18
- package/dist/prompts/prompts/roles/ADMIN.en.md +0 -33
- package/dist/prompts/prompts/roles/ADMIN.ru.md +0 -33
- package/dist/prompts/prompts/roles/ANALYST.en.md +0 -33
- package/dist/prompts/prompts/roles/ANALYST.ru.md +0 -33
- package/dist/prompts/prompts/roles/ASSISTANT.en.md +0 -38
- package/dist/prompts/prompts/roles/ASSISTANT.ru.md +0 -38
- package/dist/prompts/prompts/roles/AUDITOR.en.md +0 -33
- package/dist/prompts/prompts/roles/AUDITOR.ru.md +0 -33
- package/dist/prompts/prompts/roles/DEVELOPER.en.md +0 -42
- package/dist/prompts/prompts/roles/DEVELOPER.ru.md +0 -42
- package/dist/prompts/prompts/roles/DEVOPS.en.md +0 -35
- package/dist/prompts/prompts/roles/DEVOPS.ru.md +0 -35
- package/dist/prompts/prompts/roles/PM.en.md +0 -33
- package/dist/prompts/prompts/roles/PM.ru.md +0 -33
- package/dist/prompts/prompts/roles/QA.en.md +0 -33
- package/dist/prompts/prompts/roles/QA.ru.md +0 -33
- package/dist/prompts/prompts/roles/TITLE.ru.md +0 -30
- package/dist/prompts/prompts/subagents/explore.ru.md +0 -23
- package/dist/prompts/prompts/subagents/general.ru.md +0 -19
- package/dist/prompts/prompts/system/COMPRESSED_DIALOG.en.md +0 -5
- package/dist/prompts/prompts/system/COMPRESSED_DIALOG.ru.md +0 -5
- package/dist/prompts/prompts/system/INTERVIEW.en.md +0 -18
- package/dist/prompts/prompts/system/INTERVIEW.ru.md +0 -18
- package/dist/prompts/prompts/system/PARTICIPANTS_NOTICE.en.md +0 -7
- package/dist/prompts/prompts/system/PARTICIPANTS_NOTICE.ru.md +0 -7
- package/dist/prompts/prompts/system/ROLES_DESCRIPTION.en.md +0 -16
- package/dist/prompts/prompts/system/ROLES_DESCRIPTION.ru.md +0 -16
- package/dist/prompts/prompts/system/ROUTING.en.md +0 -13
- package/dist/prompts/prompts/system/ROUTING.md +0 -6
- package/dist/prompts/prompts/system/ROUTING.ru.md +0 -13
- package/dist/prompts/prompts/system/RULES.en.md +0 -10
- package/dist/prompts/prompts/system/RULES.md +0 -10
- package/dist/prompts/prompts/system/RULES.ru.md +0 -10
- package/dist/prompts/prompts/system/STICKY_NOTES.en.md +0 -6
- package/dist/prompts/prompts/system/STICKY_NOTES.ru.md +0 -6
- package/dist/prompts/prompts/system/SUMMARIZER.en.md +0 -54
- package/dist/prompts/prompts/system/SUMMARIZER.ru.md +0 -54
- package/dist/prompts/prompts/system/USER_CONTEXT.en.md +0 -5
- package/dist/prompts/prompts/system/USER_CONTEXT.ru.md +0 -5
- package/dist/prompts/system/ROUTING.md +0 -6
- package/dist/prompts/system/RULES.md +0 -10
- package/dist/server/routes/i18n.d.ts +0 -3
- package/dist/server/routes/i18n.d.ts.map +0 -1
- package/dist/server/routes/i18n.js +0 -83
- package/dist/server/routes/i18n.js.map +0 -1
- package/prompts/modes/plan.md +0 -20
- package/prompts/system/ROUTING.md +0 -6
- package/prompts/system/RULES.md +0 -10
- /package/dist/prompts/{prompts/system → system}/GATEWAY.en.md +0 -0
- /package/dist/prompts/{prompts/system → system}/GATEWAY.ru.md +0 -0
|
@@ -1,13 +1,47 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { ToolCapability, MessageRole, nowISO, generateId, makeTextPart
|
|
2
|
+
import { ToolCapability, MessageRole, nowISO, generateId, makeTextPart } from '@itphx/synth-shared';
|
|
3
|
+
import { normalizeAgentModes } from '../agents/normalize.js';
|
|
3
4
|
import { EventBus } from '../../events/bus.js';
|
|
5
|
+
import { classifyLlmError, isLlmErrorRecoverable, LLM_MAX_ATTEMPTS, LLM_RETRY_DELAYS_MS } from '../llm-error.js';
|
|
4
6
|
import { deriveSubagentPermission } from '../permission/derive.js';
|
|
5
|
-
import { PermissionEvaluator } from '../permission/evaluator.js';
|
|
7
|
+
import { PermissionEvaluator, isPlanRestricted, isPlanBlockedTool, getMcpToolAvailability } from '../permission/evaluator.js';
|
|
6
8
|
import { PermissionApprovalManager } from '../permission/approval.js';
|
|
7
9
|
import { serializeSession, serializeMessage } from '../../server/serialize.js';
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
import { t as sm, i18n as i18nMeta } from '../system-messages.js';
|
|
8
13
|
const DEFAULT_SUBAGENT_MAX_STEPS = 15;
|
|
9
14
|
const DEFAULT_LAST_N = 4;
|
|
10
|
-
|
|
15
|
+
/** Retry саб-агента: максимум попыток LLM-вызова (единая политика — LLM_MAX_ATTEMPTS). */
|
|
16
|
+
export const SUBAGENT_MAX_ATTEMPTS = LLM_MAX_ATTEMPTS;
|
|
17
|
+
/** Backoff между попытками (единая политика — LLM_RETRY_DELAYS_MS). */
|
|
18
|
+
export const SUBAGENT_RETRY_DELAYS_MS = LLM_RETRY_DELAYS_MS;
|
|
19
|
+
/**
|
|
20
|
+
* Промпт саб-агента по языку сессии: prompts/subagents/{type}.{lang}.md →
|
|
21
|
+
* {type}.md → agentDef.subagentPrompt (definitions JSON, легаси).
|
|
22
|
+
* Каталог промптов — systemPromptsDir из ContextConfig (резолв prompts/ или dist/prompts).
|
|
23
|
+
*/
|
|
24
|
+
export function resolveSubagentPrompt(agentDef, subagentType, language, systemPromptsDir) {
|
|
25
|
+
if (systemPromptsDir) {
|
|
26
|
+
const lang = language === 'en' ? 'en' : 'ru';
|
|
27
|
+
const localizedPath = join(systemPromptsDir, 'subagents', `${subagentType}.${lang}.md`);
|
|
28
|
+
if (existsSync(localizedPath)) {
|
|
29
|
+
try {
|
|
30
|
+
return readFileSync(localizedPath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
catch { /* fallback ниже */ }
|
|
33
|
+
}
|
|
34
|
+
const basePath = join(systemPromptsDir, 'subagents', `${subagentType}.md`);
|
|
35
|
+
if (existsSync(basePath)) {
|
|
36
|
+
try {
|
|
37
|
+
return readFileSync(basePath, 'utf-8');
|
|
38
|
+
}
|
|
39
|
+
catch { /* fallback ниже */ }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return agentDef.subagentPrompt || '';
|
|
43
|
+
}
|
|
44
|
+
export function messageToLLMMessage(msg) {
|
|
11
45
|
const roleMap = {
|
|
12
46
|
[MessageRole.USER]: 'user',
|
|
13
47
|
[MessageRole.ASSISTANT]: 'assistant',
|
|
@@ -27,9 +61,10 @@ function messageToLLMMessage(msg) {
|
|
|
27
61
|
pinned: false,
|
|
28
62
|
branchId: '',
|
|
29
63
|
toolCallId: msg.toolCallId,
|
|
64
|
+
toolUse: msg.toolCalls,
|
|
30
65
|
};
|
|
31
66
|
}
|
|
32
|
-
async function publishMessageAdded(eventBus, parentSessionId, childSessionId, msg, index, childSession) {
|
|
67
|
+
export async function publishMessageAdded(eventBus, parentSessionId, childSessionId, msg, index, childSession) {
|
|
33
68
|
const serialized = serializeMessage(msg, index);
|
|
34
69
|
const payload = {
|
|
35
70
|
session_id: childSessionId,
|
|
@@ -73,44 +108,42 @@ export const taskTool = {
|
|
|
73
108
|
async execute(args, ctx) {
|
|
74
109
|
const parsed = this.parameters.safeParse(args);
|
|
75
110
|
if (!parsed.success) {
|
|
76
|
-
return { content:
|
|
111
|
+
return { content: sm('tool.args_error', { tool: this.name, issues: parsed.error.issues.map(i => `${i.path.join('.') || 'root'}: ${i.message}`).join('; ') }), isError: true, metadata: { i18n: i18nMeta('tool.args_error', { tool: this.name }) } };
|
|
77
112
|
}
|
|
78
113
|
const params = parsed.data;
|
|
79
114
|
const extra = ctx.extra;
|
|
80
115
|
if (!extra?.provider || !extra?.agentRegistry) {
|
|
81
116
|
return {
|
|
82
|
-
content: '
|
|
117
|
+
content: sm('task.deps_unavailable'),
|
|
83
118
|
isError: true,
|
|
84
119
|
};
|
|
85
120
|
}
|
|
86
121
|
const agentDef = extra.agentRegistry.get(params.subagent_type);
|
|
87
122
|
if (!agentDef) {
|
|
88
123
|
return {
|
|
89
|
-
content:
|
|
124
|
+
content: sm('task.subagent_not_found', { type: params.subagent_type, types: extra.agentRegistry.getSubagents().map((a) => a.id).join(', ') }),
|
|
90
125
|
isError: true,
|
|
91
126
|
};
|
|
92
127
|
}
|
|
93
|
-
if (agentDef.agentMode
|
|
128
|
+
if (!normalizeAgentModes(agentDef.agentMode).includes('subagent')) {
|
|
94
129
|
return {
|
|
95
|
-
content:
|
|
130
|
+
content: sm('task.subagent_not_allowed', { type: params.subagent_type, modes: String(agentDef.agentMode) }),
|
|
96
131
|
isError: true,
|
|
97
132
|
};
|
|
98
133
|
}
|
|
99
134
|
const contextMode = params.context_mode || 'none';
|
|
100
135
|
const contextCount = params.context_count || DEFAULT_LAST_N;
|
|
101
|
-
const systemPrompt = agentDef.
|
|
136
|
+
const systemPrompt = resolveSubagentPrompt(agentDef, params.subagent_type, extra.parentSessionSettings?.language, extra.contextConfig?.systemPromptsDir);
|
|
102
137
|
const tools = extra.agentRegistry.getToolsForAgent(agentDef.id);
|
|
103
138
|
const maxSteps = agentDef.maxSteps ?? DEFAULT_SUBAGENT_MAX_STEPS;
|
|
104
|
-
const effectiveMaxSteps = (maxSteps === 0)
|
|
105
|
-
? Number.POSITIVE_INFINITY
|
|
106
|
-
: maxSteps;
|
|
107
|
-
const publish = extra.publish;
|
|
108
139
|
// ─── Настройки роутинга для дочерней сессии (AD-034 Фаза 4) ──
|
|
109
140
|
const childRoutingOverrides = {};
|
|
110
141
|
if (params.model)
|
|
111
142
|
childRoutingOverrides.model = params.model;
|
|
112
143
|
if (params.provider)
|
|
113
144
|
childRoutingOverrides.provider = params.provider;
|
|
145
|
+
if (agentDef?.reasoningLevel)
|
|
146
|
+
childRoutingOverrides.reasoningLevel = agentDef.reasoningLevel;
|
|
114
147
|
if (params.routing_strategy) {
|
|
115
148
|
if (params.routing_strategy === 'none') {
|
|
116
149
|
childRoutingOverrides.routingEnabled = false;
|
|
@@ -149,7 +182,7 @@ export const taskTool = {
|
|
|
149
182
|
const effectiveMode = contextMode === 'summary' && !extra.contextOptimizer ? 'none' : contextMode;
|
|
150
183
|
if (effectiveMode === 'inherit') {
|
|
151
184
|
const fork = await extra.sessionManager.forkSession(extra.sessionId, {
|
|
152
|
-
title:
|
|
185
|
+
title: sm('session.subtask_title', { description: params.description }),
|
|
153
186
|
});
|
|
154
187
|
fork.sessionOrigin = 'subagent';
|
|
155
188
|
fork.userId = parentSession.userId;
|
|
@@ -164,7 +197,7 @@ export const taskTool = {
|
|
|
164
197
|
const startIdx = Math.max(0, parentSession.messages.length - contextCount);
|
|
165
198
|
const fork = await extra.sessionManager.forkSession(extra.sessionId, {
|
|
166
199
|
messageIndex: startIdx,
|
|
167
|
-
title:
|
|
200
|
+
title: sm('session.subtask_title', { description: params.description }),
|
|
168
201
|
});
|
|
169
202
|
fork.sessionOrigin = 'subagent';
|
|
170
203
|
fork.userId = parentSession.userId;
|
|
@@ -177,7 +210,7 @@ export const taskTool = {
|
|
|
177
210
|
}
|
|
178
211
|
else if (effectiveMode === 'summary') {
|
|
179
212
|
const fork = await extra.sessionManager.forkSession(extra.sessionId, {
|
|
180
|
-
title:
|
|
213
|
+
title: sm('session.subtask_title', { description: params.description }),
|
|
181
214
|
});
|
|
182
215
|
fork.sessionOrigin = 'subagent';
|
|
183
216
|
fork.userId = parentSession.userId;
|
|
@@ -223,7 +256,7 @@ export const taskTool = {
|
|
|
223
256
|
else {
|
|
224
257
|
// none mode (default)
|
|
225
258
|
const child = await extra.sessionManager.createSession({
|
|
226
|
-
title:
|
|
259
|
+
title: sm('session.subtask_title', { description: params.description }),
|
|
227
260
|
projectId: parentSession.projectId,
|
|
228
261
|
engine: parentSession.engine,
|
|
229
262
|
parentId: extra.sessionId,
|
|
@@ -382,49 +415,275 @@ export const taskTool = {
|
|
|
382
415
|
// не фатально
|
|
383
416
|
}
|
|
384
417
|
}
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
418
|
+
// ─── Запуск цикла саб-агента: общий код для task и resume (ниже) ──
|
|
419
|
+
return runSubagent({
|
|
420
|
+
subagentType: params.subagent_type,
|
|
421
|
+
description: params.description,
|
|
422
|
+
contextMode,
|
|
423
|
+
maxSteps,
|
|
424
|
+
systemPrompt,
|
|
425
|
+
llmSystemPrompt,
|
|
426
|
+
initialMessages: messages.slice(1),
|
|
427
|
+
provider: effectiveProvider,
|
|
428
|
+
tools,
|
|
429
|
+
childSessionId,
|
|
430
|
+
parentSessionId: extra.sessionId,
|
|
431
|
+
routingDecisionInfo,
|
|
432
|
+
extra,
|
|
433
|
+
ctx,
|
|
434
|
+
retry: extra.retry,
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
};
|
|
438
|
+
/** Пауза backoff порциями с проверкой отмены. Возвращает true, если отмена. */
|
|
439
|
+
async function sleepAbortable(ms, isAborted) {
|
|
440
|
+
const SLICE_MS = 200;
|
|
441
|
+
let waited = 0;
|
|
442
|
+
while (waited < ms) {
|
|
443
|
+
if (isAborted())
|
|
444
|
+
return true;
|
|
445
|
+
await new Promise((resolve) => setTimeout(resolve, Math.min(SLICE_MS, ms - waited)));
|
|
446
|
+
waited += SLICE_MS;
|
|
447
|
+
}
|
|
448
|
+
return isAborted();
|
|
449
|
+
}
|
|
450
|
+
export async function runSubagent(config) {
|
|
451
|
+
const { subagentType, description, contextMode, maxSteps, systemPrompt, llmSystemPrompt, initialMessages, provider: effectiveProvider, tools: toolsInput, childSessionId, parentSessionId, extra, ctx, } = config;
|
|
452
|
+
let tools = toolsInput;
|
|
453
|
+
let routingDecisionInfo = config.routingDecisionInfo;
|
|
454
|
+
const publish = extra.publish;
|
|
455
|
+
const effectiveMaxSteps = (!maxSteps || maxSteps === 0)
|
|
456
|
+
? Number.POSITIVE_INFINITY
|
|
457
|
+
: maxSteps;
|
|
458
|
+
// ─── Retry-параметры (аналог QueueProcessor: 3 попытки, backoff 5/15/30с) ──
|
|
459
|
+
const retryCfg = config.retry ?? extra.retry
|
|
460
|
+
?? { maxRetries: LLM_MAX_ATTEMPTS, delaysMs: LLM_RETRY_DELAYS_MS };
|
|
461
|
+
const retryMaxAttempts = Math.max(1, retryCfg.maxRetries);
|
|
462
|
+
const retryDelaysMs = retryCfg.delaysMs.length > 0 ? retryCfg.delaysMs : LLM_RETRY_DELAYS_MS;
|
|
463
|
+
// ─── Permissions дочерней сессии (AD-029): родитель + deny-дополнения ──
|
|
464
|
+
const derivedPermission = deriveSubagentPermission(extra.permissionConfig);
|
|
465
|
+
// ─── LLM-сообщения: system + начальные (история/промпт) ─────────
|
|
466
|
+
const messages = [
|
|
467
|
+
{
|
|
468
|
+
id: '',
|
|
469
|
+
role: 'system',
|
|
470
|
+
content: llmSystemPrompt,
|
|
471
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
472
|
+
disabled: false,
|
|
473
|
+
pinned: false,
|
|
474
|
+
branchId: '',
|
|
475
|
+
},
|
|
476
|
+
...initialMessages,
|
|
477
|
+
];
|
|
478
|
+
const cancelToken = { cancelled: false, cancel: () => { cancelToken.cancelled = true; } };
|
|
479
|
+
// Связка локального cancel-токена саб-агента с родительским сигналом отмены:
|
|
480
|
+
// «Стоп» в родительской сессии (POST /sessions/:id/abort → orchestrator.cancel
|
|
481
|
+
// → внутренний toolAbortController.abort → ctx.abortSignal) должен немедленно
|
|
482
|
+
// прерывать LLM-стрим саб-агента и его цикл, а не ждать завершения всех шагов.
|
|
483
|
+
const isAborted = () => cancelToken.cancelled || ctx.abortSignal?.aborted === true;
|
|
484
|
+
if (ctx.abortSignal?.aborted) {
|
|
485
|
+
cancelToken.cancel();
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
ctx.abortSignal?.addEventListener('abort', () => cancelToken.cancel(), { once: true });
|
|
489
|
+
}
|
|
490
|
+
// ─── Permissions саб-агента (AD-029): проверка перед каждым tool_call ──
|
|
491
|
+
// Дочерняя сессия наследует permissions родителя (deriveSubagentPermission).
|
|
492
|
+
// ask-запросы публикуются в EventBus РОДИТЕЛЬСКОЙ сессии — подтверждение
|
|
493
|
+
// видит пользователь основной сессии, approval_id связывает ответ.
|
|
494
|
+
const childEvaluator = new PermissionEvaluator(derivedPermission);
|
|
495
|
+
const childApprovalManager = new PermissionApprovalManager(extra.eventBus ?? new EventBus());
|
|
496
|
+
let childSessionMode = 'act';
|
|
497
|
+
let childPlanApproved = false;
|
|
498
|
+
let childPlanMode = 'auto';
|
|
499
|
+
let childMcpToolSettings;
|
|
500
|
+
if (childSessionId && extra.sessionManager) {
|
|
501
|
+
try {
|
|
502
|
+
const child = await extra.sessionManager.getSession(childSessionId);
|
|
503
|
+
if (child) {
|
|
504
|
+
childSessionMode = child.mode ?? 'act';
|
|
505
|
+
childPlanApproved = Boolean(child.planApproved);
|
|
506
|
+
childPlanMode = child.settings.planMode ?? 'auto';
|
|
507
|
+
childMcpToolSettings = child.settings.mcpToolSettings;
|
|
405
508
|
}
|
|
406
|
-
|
|
407
|
-
|
|
509
|
+
}
|
|
510
|
+
catch {
|
|
511
|
+
// не фатально — остаёмся в act/auto
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
// B5: режимная фильтрация списка тулов саб-агента (аналог
|
|
515
|
+
// orchestrator._filterToolsByMode). В plan-режиме (или strict без
|
|
516
|
+
// утверждённого плана) скрываем write/edit-тулы и git-запись — модель не
|
|
517
|
+
// видит инструменты, которые всё равно будут отклонены evaluator'ом.
|
|
518
|
+
if (isPlanRestricted(childSessionMode, childPlanMode, childPlanApproved) && tools) {
|
|
519
|
+
const filtered = [];
|
|
520
|
+
for (const tool of tools) {
|
|
521
|
+
const toolName = tool.function.name;
|
|
522
|
+
const toolDef = extra.toolRegistry?.get(toolName);
|
|
523
|
+
const capabilities = toolDef?.capabilities;
|
|
524
|
+
if (isPlanBlockedTool(toolName, capabilities))
|
|
525
|
+
continue;
|
|
526
|
+
// MCP-инструменты: в plan-режиме недоступный по настройкам тул убираем.
|
|
527
|
+
if (capabilities?.includes(ToolCapability.MCP) && childMcpToolSettings) {
|
|
528
|
+
const availability = getMcpToolAvailability(childMcpToolSettings, toolName);
|
|
529
|
+
if (availability && !availability.plan)
|
|
530
|
+
continue;
|
|
408
531
|
}
|
|
532
|
+
filtered.push(tool);
|
|
409
533
|
}
|
|
534
|
+
tools = filtered;
|
|
535
|
+
}
|
|
536
|
+
// Финализация дочерней сессии: обновление updatedAt + события для UI.
|
|
537
|
+
// Отдельного статусного поля «завершена/прервана» у сессии нет
|
|
538
|
+
// (SessionStatus — только процессная блокировка blocked/blockedAt),
|
|
539
|
+
// поэтому факт прерывания/ошибки фиксируется metadata-маркерами
|
|
540
|
+
// в сообщениях истории дочерней сессии.
|
|
541
|
+
const finalizeChildSession = async () => {
|
|
542
|
+
if (!childSessionId || !extra.sessionManager)
|
|
543
|
+
return;
|
|
410
544
|
try {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
545
|
+
const childSession = await extra.sessionManager.getSession(childSessionId);
|
|
546
|
+
if (childSession) {
|
|
547
|
+
childSession.updatedAt = nowISO();
|
|
548
|
+
await extra.sessionManager.updateSession(childSession);
|
|
549
|
+
if (extra.eventBus) {
|
|
550
|
+
extra.eventBus.publish(childSessionId, 'session.updated', {
|
|
551
|
+
session_id: childSessionId,
|
|
552
|
+
});
|
|
553
|
+
extra.eventBus.publish(parentSessionId, 'child.session.updated', {
|
|
554
|
+
session: serializeSession(childSession),
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
catch {
|
|
560
|
+
// не фатально
|
|
561
|
+
}
|
|
562
|
+
};
|
|
563
|
+
/** Добавить сообщение в дочернюю сессию + опубликовать события. */
|
|
564
|
+
const addChildMessage = async (msg) => {
|
|
565
|
+
if (!childSessionId || !extra.sessionManager)
|
|
566
|
+
return;
|
|
567
|
+
try {
|
|
568
|
+
const updated = await extra.sessionManager.addMessage(childSessionId, msg);
|
|
569
|
+
if (updated && extra.eventBus) {
|
|
570
|
+
const idx = updated.messages.length - 1;
|
|
571
|
+
await publishMessageAdded(extra.eventBus, parentSessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
catch {
|
|
575
|
+
// не фатально
|
|
576
|
+
}
|
|
577
|
+
};
|
|
578
|
+
try {
|
|
579
|
+
let finalContent = '';
|
|
580
|
+
let iteration = 0;
|
|
581
|
+
const doomTracker = new Map();
|
|
582
|
+
let subagentReasoning = '';
|
|
583
|
+
let subagentDenied = false;
|
|
584
|
+
const allSubagentReasoning = [];
|
|
585
|
+
const allSubagentIntermediateTexts = [];
|
|
586
|
+
const allSubagentToolCalls = [];
|
|
587
|
+
// Завершение по отмене (Стоп в родительской сессии): сохранить частичный
|
|
588
|
+
// текст (если есть), поставить маркер прерывания в историю дочерней
|
|
589
|
+
// сессии, финализировать её (без статуса completed) и вернуть родителю
|
|
590
|
+
// tool_result с маркером остановки, частичным ответом и списком шагов.
|
|
591
|
+
const finishAborted = async (partialContent, partialReasoning) => {
|
|
592
|
+
// 1. Частичный стрим оборванной итерации — в историю дочерней сессии
|
|
593
|
+
if (partialContent) {
|
|
594
|
+
await addChildMessage({
|
|
595
|
+
id: generateId(),
|
|
596
|
+
role: MessageRole.ASSISTANT,
|
|
597
|
+
seq: 0,
|
|
598
|
+
origin: 'local',
|
|
599
|
+
parts: [makeTextPart(partialContent)],
|
|
600
|
+
content: partialContent,
|
|
601
|
+
createdAt: nowISO(),
|
|
602
|
+
disabled: false,
|
|
603
|
+
pinned: false,
|
|
604
|
+
hidden: false,
|
|
605
|
+
agentRole: subagentType,
|
|
606
|
+
...(partialReasoning ? { reasoning: partialReasoning } : {}),
|
|
607
|
+
metadata: {
|
|
608
|
+
stream_id: extra.streamId,
|
|
609
|
+
partial: true,
|
|
610
|
+
interrupted: true,
|
|
611
|
+
},
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
// 2. Маркер прерывания в историю дочерней сессии
|
|
615
|
+
const stopMarkerText = sm('task.stopped_by_user');
|
|
616
|
+
await addChildMessage({
|
|
617
|
+
id: generateId(),
|
|
618
|
+
role: MessageRole.INFO,
|
|
619
|
+
seq: 0,
|
|
620
|
+
origin: 'local',
|
|
621
|
+
parts: [makeTextPart(stopMarkerText)],
|
|
622
|
+
content: stopMarkerText,
|
|
623
|
+
createdAt: nowISO(),
|
|
624
|
+
disabled: false,
|
|
625
|
+
pinned: false,
|
|
626
|
+
hidden: false,
|
|
627
|
+
agentRole: subagentType,
|
|
628
|
+
metadata: {
|
|
629
|
+
stream_id: extra.streamId,
|
|
630
|
+
stopped_by: 'user',
|
|
631
|
+
interrupted: true,
|
|
632
|
+
i18n: i18nMeta('task.stopped_by_user'),
|
|
633
|
+
},
|
|
634
|
+
});
|
|
635
|
+
// 3. Финализация дочерней сессии
|
|
636
|
+
await finalizeChildSession();
|
|
637
|
+
// 4. tool_result родителю: маркер отмены + частичный текст + шаги + id сессии
|
|
638
|
+
const stepsCompleted = allSubagentToolCalls.length > 0
|
|
639
|
+
? allSubagentToolCalls.map((t) => t.name).join(', ')
|
|
640
|
+
: 'none';
|
|
641
|
+
return {
|
|
642
|
+
content: [
|
|
643
|
+
'<task_result>',
|
|
644
|
+
`<summary>${description}</summary>`,
|
|
645
|
+
'<status>stopped_by_user</status>',
|
|
646
|
+
...(childSessionId ? [`<child_session_id>${childSessionId}</child_session_id>`] : []),
|
|
647
|
+
...(partialContent ? [`<partial_output>\n${partialContent}\n</partial_output>`] : []),
|
|
648
|
+
`<steps_completed>${stepsCompleted}</steps_completed>`,
|
|
649
|
+
sm('task.stopped_before_completion'),
|
|
650
|
+
'</task_result>',
|
|
651
|
+
].join('\n'),
|
|
652
|
+
metadata: {
|
|
653
|
+
subagent_type: subagentType,
|
|
654
|
+
description: description,
|
|
655
|
+
context_mode: contextMode,
|
|
656
|
+
steps: iteration,
|
|
657
|
+
child_session_id: childSessionId,
|
|
658
|
+
stopped_by: 'user',
|
|
659
|
+
interrupted: true,
|
|
660
|
+
tool_calls: allSubagentToolCalls.length > 0 ? allSubagentToolCalls : undefined,
|
|
661
|
+
partial_output: partialContent || undefined,
|
|
662
|
+
},
|
|
663
|
+
};
|
|
664
|
+
};
|
|
665
|
+
while (iteration < effectiveMaxSteps) {
|
|
666
|
+
if (isAborted())
|
|
667
|
+
break;
|
|
668
|
+
let accumulatedContent = '';
|
|
669
|
+
let toolCalls = [];
|
|
670
|
+
let reasoning = '';
|
|
671
|
+
let lastPublishedReasoning = '';
|
|
672
|
+
let lastPublishedContentLen = 0;
|
|
673
|
+
// ─── LLM-вызов с retry (B1, аналог QueueProcessor) ──────────────
|
|
674
|
+
// Recoverable-ошибки (network/timeout/rate_limit/server_error) ретраятся
|
|
675
|
+
// до retryMaxAttempts попыток с backoff; unrecoverable (auth/
|
|
676
|
+
// model_not_found/context_length) — сразу финальная ошибка. Backoff-пауза
|
|
677
|
+
// спит порциями с проверкой отмены: «Стоп» прерывает ожидание мгновенно.
|
|
678
|
+
// Событие subagent.retry и паузы НЕ пишут ничего в историю дочерней
|
|
679
|
+
// сессии — мусорные сообщения не создаются (только финальный ERROR).
|
|
680
|
+
let llmFailure = null;
|
|
681
|
+
for (let attempt = 1; attempt <= retryMaxAttempts; attempt++) {
|
|
682
|
+
if (isAborted())
|
|
421
683
|
break;
|
|
422
|
-
let accumulatedContent = '';
|
|
423
|
-
let toolCalls = [];
|
|
424
|
-
let reasoning = '';
|
|
425
684
|
try {
|
|
426
685
|
for await (const chunk of effectiveProvider.chatAsync(messages, systemPrompt || undefined, tools, undefined, cancelToken)) {
|
|
427
|
-
if (
|
|
686
|
+
if (isAborted())
|
|
428
687
|
break;
|
|
429
688
|
if (chunk.isFinal) {
|
|
430
689
|
accumulatedContent = chunk.content;
|
|
@@ -432,62 +691,148 @@ export const taskTool = {
|
|
|
432
691
|
}
|
|
433
692
|
else {
|
|
434
693
|
accumulatedContent += chunk.content;
|
|
694
|
+
const chunkReasoning = chunk.reasoning;
|
|
695
|
+
if (chunkReasoning)
|
|
696
|
+
reasoning = chunkReasoning;
|
|
435
697
|
}
|
|
436
698
|
if (chunk.toolCalls && chunk.toolCalls.length > 0) {
|
|
437
699
|
toolCalls = chunk.toolCalls;
|
|
438
700
|
}
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
if (reasoning)
|
|
456
|
-
subagentReasoning = reasoning;
|
|
457
|
-
// Сохранить финальный ответ ассистента в дочернюю сессию
|
|
458
|
-
if (childSessionId && extra.sessionManager) {
|
|
459
|
-
try {
|
|
460
|
-
const assistantMsg = {
|
|
461
|
-
id: generateId(),
|
|
462
|
-
role: MessageRole.ASSISTANT,
|
|
463
|
-
seq: 0,
|
|
464
|
-
origin: 'local',
|
|
465
|
-
parts: [makeTextPart(accumulatedContent)],
|
|
466
|
-
content: accumulatedContent,
|
|
467
|
-
createdAt: nowISO(),
|
|
468
|
-
disabled: false,
|
|
469
|
-
pinned: false,
|
|
470
|
-
hidden: false,
|
|
471
|
-
agentRole: params.subagent_type,
|
|
472
|
-
reasoning: reasoning || undefined,
|
|
473
|
-
};
|
|
474
|
-
const updated = await extra.sessionManager.addMessage(childSessionId, assistantMsg);
|
|
475
|
-
if (updated && extra.eventBus) {
|
|
476
|
-
const idx = updated.messages.length - 1;
|
|
477
|
-
await publishMessageAdded(extra.eventBus, extra.sessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
701
|
+
// Стримим размышления/промежуточный текст саб-агента РОДИТЕЛЮ,
|
|
702
|
+
// чтобы в блоке `task` (по parent_call_id) они были видны во время работы.
|
|
703
|
+
if (publish) {
|
|
704
|
+
const liveReasoning = reasoning || '';
|
|
705
|
+
const liveContent = accumulatedContent || '';
|
|
706
|
+
if (liveReasoning !== lastPublishedReasoning || liveContent.length !== lastPublishedContentLen) {
|
|
707
|
+
publish('subagent.progress', {
|
|
708
|
+
stream_id: extra.streamId,
|
|
709
|
+
session_id: extra.sessionId,
|
|
710
|
+
parent_call_id: extra.callId,
|
|
711
|
+
reasoning: liveReasoning,
|
|
712
|
+
content: liveContent,
|
|
713
|
+
iteration,
|
|
714
|
+
});
|
|
715
|
+
lastPublishedReasoning = liveReasoning;
|
|
716
|
+
lastPublishedContentLen = liveContent.length;
|
|
478
717
|
}
|
|
479
718
|
}
|
|
480
|
-
catch {
|
|
481
|
-
// не фатально
|
|
482
|
-
}
|
|
483
719
|
}
|
|
720
|
+
llmFailure = null;
|
|
484
721
|
break;
|
|
485
722
|
}
|
|
486
|
-
|
|
487
|
-
|
|
723
|
+
catch (err) {
|
|
724
|
+
// Прерывание пользователем во время стрима (провайдер бросил
|
|
725
|
+
// AbortError) — не ошибка, обработается через finishAborted ниже.
|
|
726
|
+
if (isAborted())
|
|
727
|
+
break;
|
|
728
|
+
const rawError = err instanceof Error ? err.message : String(err);
|
|
729
|
+
const errorType = classifyLlmError(rawError);
|
|
730
|
+
if (!isLlmErrorRecoverable(err, rawError) || attempt >= retryMaxAttempts) {
|
|
731
|
+
// Unrecoverable или попытки исчерпаны — финальная ошибка
|
|
732
|
+
llmFailure = { error: err, errorType, attempts: attempt };
|
|
733
|
+
break;
|
|
734
|
+
}
|
|
735
|
+
const delay = retryDelaysMs[Math.min(attempt - 1, retryDelaysMs.length - 1)] ?? 0;
|
|
736
|
+
publish?.('subagent.retry', {
|
|
737
|
+
stream_id: extra.streamId,
|
|
738
|
+
session_id: extra.sessionId,
|
|
739
|
+
child_session_id: childSessionId,
|
|
740
|
+
parent_call_id: extra.callId,
|
|
741
|
+
attempt,
|
|
742
|
+
max_retries: retryMaxAttempts,
|
|
743
|
+
retry_in: delay,
|
|
744
|
+
error_type: errorType,
|
|
745
|
+
error: rawError,
|
|
746
|
+
});
|
|
747
|
+
if (await sleepAbortable(delay, isAborted))
|
|
748
|
+
break;
|
|
749
|
+
// Сброс частичного контекста неудавшейся попытки
|
|
750
|
+
accumulatedContent = '';
|
|
751
|
+
reasoning = '';
|
|
752
|
+
toolCalls = [];
|
|
753
|
+
lastPublishedReasoning = '';
|
|
754
|
+
lastPublishedContentLen = 0;
|
|
488
755
|
}
|
|
489
|
-
|
|
490
|
-
|
|
756
|
+
}
|
|
757
|
+
if (llmFailure) {
|
|
758
|
+
// Ошибка провайдера внутри саб-агента (после retry-цикла): фиксируем
|
|
759
|
+
// в истории дочерней сессии, финализируем её и возвращаем родителю
|
|
760
|
+
// tool_result с описанием ошибки, счётчиком попыток и child_session_id.
|
|
761
|
+
const attempts = llmFailure.attempts;
|
|
762
|
+
const errParams = { type: subagentType, error: String(llmFailure.error) };
|
|
763
|
+
const errKey = attempts > 1
|
|
764
|
+
? 'task.subagent_exec_error_after_retries'
|
|
765
|
+
: 'task.subagent_exec_error';
|
|
766
|
+
const errText = attempts > 1
|
|
767
|
+
? sm(errKey, { ...errParams, attempts: String(attempts) })
|
|
768
|
+
: sm(errKey, errParams);
|
|
769
|
+
await addChildMessage({
|
|
770
|
+
id: generateId(),
|
|
771
|
+
role: MessageRole.ERROR,
|
|
772
|
+
seq: 0,
|
|
773
|
+
origin: 'local',
|
|
774
|
+
parts: [makeTextPart(errText)],
|
|
775
|
+
content: errText,
|
|
776
|
+
createdAt: nowISO(),
|
|
777
|
+
disabled: false,
|
|
778
|
+
pinned: false,
|
|
779
|
+
hidden: false,
|
|
780
|
+
agentRole: subagentType,
|
|
781
|
+
metadata: {
|
|
782
|
+
stream_id: extra.streamId,
|
|
783
|
+
error: true,
|
|
784
|
+
attempts,
|
|
785
|
+
max_retries: retryMaxAttempts,
|
|
786
|
+
error_type: llmFailure.errorType,
|
|
787
|
+
i18n: i18nMeta(errKey, attempts > 1 ? { ...errParams, attempts: String(attempts) } : errParams),
|
|
788
|
+
},
|
|
789
|
+
});
|
|
790
|
+
await finalizeChildSession();
|
|
791
|
+
return {
|
|
792
|
+
content: [
|
|
793
|
+
'<task_result>',
|
|
794
|
+
`<summary>${description}</summary>`,
|
|
795
|
+
'<status>error</status>',
|
|
796
|
+
...(childSessionId ? [`<child_session_id>${childSessionId}</child_session_id>`] : []),
|
|
797
|
+
`<attempts>${attempts}</attempts>`,
|
|
798
|
+
errText,
|
|
799
|
+
'</task_result>',
|
|
800
|
+
].join('\n'),
|
|
801
|
+
isError: true,
|
|
802
|
+
metadata: {
|
|
803
|
+
subagent_type: subagentType,
|
|
804
|
+
description: description,
|
|
805
|
+
context_mode: contextMode,
|
|
806
|
+
steps: iteration,
|
|
807
|
+
child_session_id: childSessionId,
|
|
808
|
+
error: true,
|
|
809
|
+
attempts,
|
|
810
|
+
max_retries: retryMaxAttempts,
|
|
811
|
+
error_type: llmFailure.errorType,
|
|
812
|
+
tool_calls: allSubagentToolCalls.length > 0 ? allSubagentToolCalls : undefined,
|
|
813
|
+
},
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
// Отмена (Стоп в родительской сессии): сохраняем частичный текст
|
|
817
|
+
// ТЕКУЩЕЙ итерации, ставим маркер прерывания в историю дочерней
|
|
818
|
+
// сессии, финализируем её (без статуса completed) и возвращаем
|
|
819
|
+
// родителю tool_result с маркером остановки, частичным ответом и
|
|
820
|
+
// списком выполненных шагов.
|
|
821
|
+
if (isAborted()) {
|
|
822
|
+
return await finishAborted(accumulatedContent, reasoning);
|
|
823
|
+
}
|
|
824
|
+
// Единая итерация для размышлений, промежуточного текста и вызовов
|
|
825
|
+
// инструментов этого шага — иначе в UI (и в дочерней сессии) ломается
|
|
826
|
+
// порядок: размышления идут на step N, а вызовы — на N+1.
|
|
827
|
+
const stepIteration = iteration;
|
|
828
|
+
if (reasoning) {
|
|
829
|
+
allSubagentReasoning.push({ text: reasoning, iteration: stepIteration });
|
|
830
|
+
}
|
|
831
|
+
if (!toolCalls || toolCalls.length === 0) {
|
|
832
|
+
finalContent = accumulatedContent;
|
|
833
|
+
if (reasoning)
|
|
834
|
+
subagentReasoning = reasoning;
|
|
835
|
+
// Сохранить финальный ответ ассистента в дочернюю сессию
|
|
491
836
|
if (childSessionId && extra.sessionManager) {
|
|
492
837
|
try {
|
|
493
838
|
const assistantMsg = {
|
|
@@ -495,215 +840,237 @@ export const taskTool = {
|
|
|
495
840
|
role: MessageRole.ASSISTANT,
|
|
496
841
|
seq: 0,
|
|
497
842
|
origin: 'local',
|
|
498
|
-
parts: [makeTextPart(accumulatedContent
|
|
499
|
-
content: accumulatedContent
|
|
843
|
+
parts: [makeTextPart(accumulatedContent)],
|
|
844
|
+
content: accumulatedContent,
|
|
500
845
|
createdAt: nowISO(),
|
|
501
846
|
disabled: false,
|
|
502
847
|
pinned: false,
|
|
503
848
|
hidden: false,
|
|
504
|
-
agentRole:
|
|
505
|
-
|
|
849
|
+
agentRole: subagentType,
|
|
850
|
+
// Все размышления сабагента (по итерациям), склеенные в поле
|
|
851
|
+
// reasoning — UI дочерней сессии показывает их блоками
|
|
852
|
+
// (ReasoningBlock разбивает по «\n\n---\n\n»). Без этого размышления
|
|
853
|
+
// остаются только в скрытых tool_chain-сообщениях и теряются.
|
|
854
|
+
reasoning: allSubagentReasoning.length > 0
|
|
855
|
+
? allSubagentReasoning.map((r) => r.text).join('\n\n---\n\n')
|
|
856
|
+
: undefined,
|
|
857
|
+
// Как в _persistToolChain родителя: финальное сообщение несёт
|
|
858
|
+
// свёрнутую цепочку тулов, чтобы UI дочерней сессии отрисовал её
|
|
859
|
+
// так же аккуратно, как финал родительской.
|
|
860
|
+
metadata: {
|
|
861
|
+
stream_id: extra.streamId,
|
|
862
|
+
...(allSubagentToolCalls.length > 0 ? { tool_results: allSubagentToolCalls } : {}),
|
|
863
|
+
...(allSubagentIntermediateTexts.length > 0 ? { intermediate_text_blocks: allSubagentIntermediateTexts } : {}),
|
|
864
|
+
},
|
|
506
865
|
};
|
|
507
866
|
const updated = await extra.sessionManager.addMessage(childSessionId, assistantMsg);
|
|
508
867
|
if (updated && extra.eventBus) {
|
|
509
868
|
const idx = updated.messages.length - 1;
|
|
510
|
-
await publishMessageAdded(extra.eventBus,
|
|
869
|
+
await publishMessageAdded(extra.eventBus, parentSessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
511
870
|
}
|
|
512
871
|
}
|
|
513
872
|
catch {
|
|
514
873
|
// не фатально
|
|
515
874
|
}
|
|
516
875
|
}
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
876
|
+
break;
|
|
877
|
+
}
|
|
878
|
+
if (accumulatedContent) {
|
|
879
|
+
allSubagentIntermediateTexts.push({ text: accumulatedContent, iteration });
|
|
880
|
+
}
|
|
881
|
+
iteration++;
|
|
882
|
+
// Сохранить ответ ассистента с tool calls в дочернюю сессию
|
|
883
|
+
if (childSessionId && extra.sessionManager) {
|
|
884
|
+
try {
|
|
885
|
+
const assistantMsg = {
|
|
886
|
+
id: generateId(),
|
|
887
|
+
role: MessageRole.ASSISTANT,
|
|
888
|
+
seq: 0,
|
|
889
|
+
origin: 'local',
|
|
890
|
+
parts: [makeTextPart(accumulatedContent || '')],
|
|
891
|
+
content: accumulatedContent || '',
|
|
892
|
+
createdAt: nowISO(),
|
|
893
|
+
disabled: false,
|
|
894
|
+
pinned: false,
|
|
895
|
+
hidden: false,
|
|
896
|
+
agentRole: subagentType,
|
|
897
|
+
reasoning: reasoning || undefined,
|
|
898
|
+
// OpenAI-совместимая цепочка: assistant(toolCalls) → tool.
|
|
899
|
+
// tool_chain=true — UI дочерней сессии скрывает промежуточные
|
|
900
|
+
// сообщения (визуализация уже в финальном с tool_results).
|
|
901
|
+
toolCalls,
|
|
902
|
+
metadata: { stream_id: extra.streamId, tool_chain: true },
|
|
903
|
+
};
|
|
904
|
+
const updated = await extra.sessionManager.addMessage(childSessionId, assistantMsg);
|
|
905
|
+
if (updated && extra.eventBus) {
|
|
906
|
+
const idx = updated.messages.length - 1;
|
|
907
|
+
await publishMessageAdded(extra.eventBus, parentSessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
541
908
|
}
|
|
542
|
-
|
|
543
|
-
|
|
909
|
+
}
|
|
910
|
+
catch {
|
|
911
|
+
// не фатально
|
|
912
|
+
}
|
|
913
|
+
}
|
|
914
|
+
messages.push({
|
|
915
|
+
id: '',
|
|
916
|
+
role: 'assistant',
|
|
917
|
+
content: accumulatedContent || '',
|
|
918
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
919
|
+
disabled: false,
|
|
920
|
+
pinned: false,
|
|
921
|
+
branchId: '',
|
|
922
|
+
toolUse: toolCalls,
|
|
923
|
+
});
|
|
924
|
+
for (const tc of toolCalls) {
|
|
925
|
+
const tcId = tc.id || `subcall_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
926
|
+
const func = tc.function;
|
|
927
|
+
if (!func?.name)
|
|
928
|
+
continue;
|
|
929
|
+
const toolName = func.name;
|
|
930
|
+
let toolArgs;
|
|
931
|
+
if (typeof func.arguments === 'string') {
|
|
932
|
+
try {
|
|
933
|
+
toolArgs = JSON.parse(func.arguments);
|
|
544
934
|
}
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
935
|
+
catch {
|
|
936
|
+
toolArgs = {};
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
toolArgs = func.arguments || {};
|
|
941
|
+
}
|
|
942
|
+
const tcStartedAt = new Date().toISOString();
|
|
943
|
+
const doomKey = `${toolName}:${JSON.stringify(toolArgs)}`;
|
|
944
|
+
const doomCount = (doomTracker.get(doomKey) || 0) + 1;
|
|
945
|
+
doomTracker.set(doomKey, doomCount);
|
|
946
|
+
if (doomCount >= 3) {
|
|
947
|
+
const doomMsg = {
|
|
948
|
+
id: '', role: 'tool',
|
|
949
|
+
content: sm('tool.doom_loop', { tool: toolName, count: String(doomCount) }),
|
|
950
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
951
|
+
disabled: false, pinned: false, branchId: '',
|
|
952
|
+
toolCallId: tcId,
|
|
953
|
+
};
|
|
954
|
+
messages.push(doomMsg);
|
|
955
|
+
if (childSessionId && extra.sessionManager) {
|
|
956
|
+
try {
|
|
957
|
+
const toolResultMsg = {
|
|
958
|
+
id: generateId(),
|
|
959
|
+
role: MessageRole.TOOL,
|
|
960
|
+
seq: 0,
|
|
961
|
+
origin: 'local',
|
|
962
|
+
parts: [makeTextPart(doomMsg.content)],
|
|
963
|
+
content: doomMsg.content,
|
|
964
|
+
createdAt: nowISO(),
|
|
965
|
+
disabled: false,
|
|
966
|
+
pinned: false,
|
|
967
|
+
hidden: false,
|
|
968
|
+
toolCallId: tcId,
|
|
969
|
+
metadata: {
|
|
970
|
+
stream_id: extra.streamId,
|
|
971
|
+
tool_chain: true,
|
|
972
|
+
tool_name: toolName,
|
|
973
|
+
args: toolArgs,
|
|
974
|
+
},
|
|
975
|
+
};
|
|
976
|
+
const updated = await extra.sessionManager.addMessage(childSessionId, toolResultMsg);
|
|
977
|
+
if (updated && extra.eventBus) {
|
|
978
|
+
const idx = updated.messages.length - 1;
|
|
979
|
+
await publishMessageAdded(extra.eventBus, parentSessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
581
980
|
}
|
|
582
981
|
}
|
|
583
|
-
|
|
982
|
+
catch {
|
|
983
|
+
// не фатально
|
|
984
|
+
}
|
|
584
985
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
986
|
+
continue;
|
|
987
|
+
}
|
|
988
|
+
publish?.('tool_call.started', {
|
|
989
|
+
stream_id: extra.streamId,
|
|
990
|
+
session_id: extra.sessionId,
|
|
991
|
+
call_id: tcId,
|
|
992
|
+
name: toolName,
|
|
993
|
+
arguments: toolArgs,
|
|
994
|
+
iteration: stepIteration,
|
|
995
|
+
// Вложенность внутренних вызовов саб-агента под блоком `task`
|
|
996
|
+
// в родительском стриме (UI строит дерево по parent_call_id).
|
|
997
|
+
parent_call_id: extra.callId,
|
|
998
|
+
});
|
|
999
|
+
const toolDef = extra.toolRegistry?.get(toolName);
|
|
1000
|
+
let toolResult;
|
|
1001
|
+
let subagentUserDenied = false;
|
|
1002
|
+
// AD-029: permission-check саб-агента — permissions дочерней сессии
|
|
1003
|
+
// (родитель + deny-дополнения) применяются к каждому tool_call.
|
|
1004
|
+
const permissionDecision = childEvaluator.check({
|
|
1005
|
+
toolName,
|
|
1006
|
+
params: toolArgs,
|
|
1007
|
+
workingDir: ctx.workingDir,
|
|
1008
|
+
capabilities: toolDef?.capabilities,
|
|
1009
|
+
sessionMode: childSessionMode,
|
|
1010
|
+
planMode: childPlanMode,
|
|
1011
|
+
planApproved: childPlanApproved,
|
|
1012
|
+
mcpToolSettings: childMcpToolSettings,
|
|
1013
|
+
shellPolicy: extra.shellPolicy ?? undefined,
|
|
1014
|
+
protectedPaths: extra.protectedPaths ?? undefined,
|
|
1015
|
+
protectedPathsEnabled: extra.protectedPathsEnabled,
|
|
1016
|
+
});
|
|
1017
|
+
if (permissionDecision.action === 'deny') {
|
|
1018
|
+
toolResult = {
|
|
1019
|
+
content: extra.contextConfig && permissionDecision.messageId
|
|
1020
|
+
? (extra.contextConfig.getSecurityMessage(permissionDecision.messageId, 'en', permissionDecision.params)
|
|
1021
|
+
?? `Permission denied: ${permissionDecision.reason}`)
|
|
1022
|
+
: `Permission denied: ${permissionDecision.reason}`,
|
|
1023
|
+
isError: true,
|
|
1024
|
+
metadata: {
|
|
1025
|
+
...(permissionDecision.messageId
|
|
1026
|
+
? { i18n: i18nMeta(`security.${permissionDecision.messageId.replaceAll('-', '_')}`, permissionDecision.params) }
|
|
1027
|
+
: { i18n: i18nMeta('tool.permission_denied_default') }),
|
|
1028
|
+
permission: {
|
|
1029
|
+
action: 'deny',
|
|
1030
|
+
reason: permissionDecision.reason,
|
|
1031
|
+
matched_rule: permissionDecision.matchedRule,
|
|
618
1032
|
},
|
|
619
|
-
}
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
1033
|
+
},
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
else if (permissionDecision.action === 'ask') {
|
|
1037
|
+
// ask публикуется в родительскую сессию (extra.sessionId) —
|
|
1038
|
+
// пользователь основной сессии видит запрос и отвечает.
|
|
1039
|
+
const approvalAskReason = extra.contextConfig && permissionDecision.messageId
|
|
1040
|
+
? (extra.contextConfig.getSecurityMessage(permissionDecision.messageId, 'en', permissionDecision.params)
|
|
1041
|
+
?? permissionDecision.reason)
|
|
1042
|
+
: permissionDecision.reason;
|
|
1043
|
+
const approval = await childApprovalManager.waitForDecision(extra.sessionId, {
|
|
1044
|
+
approvalId: `approval_${tcId}`,
|
|
1045
|
+
callId: tcId,
|
|
1046
|
+
toolName,
|
|
1047
|
+
arguments: toolArgs,
|
|
1048
|
+
reason: approvalAskReason,
|
|
1049
|
+
}, derivedPermission.askTimeoutMs);
|
|
1050
|
+
if (approval.approved) {
|
|
1051
|
+
if (approval.once === false) {
|
|
1052
|
+
// «Разрешить в сессии» — allow-правило в permissions дочерней сессии
|
|
1053
|
+
derivedPermission.rules[toolName] = 'allow';
|
|
1054
|
+
if (childSessionId && extra.sessionManager) {
|
|
1055
|
+
try {
|
|
1056
|
+
const child = await extra.sessionManager.getSession(childSessionId);
|
|
1057
|
+
if (child) {
|
|
1058
|
+
child.settings.permission = { ...derivedPermission };
|
|
1059
|
+
await extra.sessionManager.updateSession(child);
|
|
645
1060
|
}
|
|
646
1061
|
}
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
const parsed2 = toolDef.parameters.safeParse(toolArgs);
|
|
650
|
-
if (!parsed2.success) {
|
|
651
|
-
toolResult = {
|
|
652
|
-
content: `Ошибка аргументов инструмента "${toolName}": ${parsed2.error.issues.map(i => `${i.path.join('.') || 'root'}: ${i.message}`).join('; ')}`,
|
|
653
|
-
isError: true,
|
|
654
|
-
};
|
|
655
|
-
}
|
|
656
|
-
else {
|
|
657
|
-
try {
|
|
658
|
-
toolResult = await toolDef.execute(parsed2.data, {
|
|
659
|
-
...ctx,
|
|
660
|
-
abortSignal: ctx.abortSignal,
|
|
661
|
-
extra: extra,
|
|
662
|
-
});
|
|
663
|
-
}
|
|
664
|
-
catch (execError) {
|
|
665
|
-
toolResult = {
|
|
666
|
-
content: `Ошибка исполнения инструмента "${toolName}": ${String(execError)}`,
|
|
667
|
-
isError: true,
|
|
668
|
-
};
|
|
669
|
-
}
|
|
1062
|
+
catch {
|
|
1063
|
+
// не фатально
|
|
670
1064
|
}
|
|
671
1065
|
}
|
|
672
|
-
else {
|
|
673
|
-
toolResult = {
|
|
674
|
-
content: `Инструмент "${toolName}" не найден`,
|
|
675
|
-
isError: true,
|
|
676
|
-
};
|
|
677
|
-
}
|
|
678
1066
|
}
|
|
679
|
-
else {
|
|
680
|
-
const why = approval.timeout
|
|
681
|
-
? 'истекло время ожидания подтверждения'
|
|
682
|
-
: approval.noSubscribers
|
|
683
|
-
? 'нет подключённого пользователя для подтверждения'
|
|
684
|
-
: 'отклонено пользователем';
|
|
685
|
-
toolResult = {
|
|
686
|
-
content: `Permission denied: ${permissionDecision.reason} (${why})`,
|
|
687
|
-
isError: true,
|
|
688
|
-
metadata: {
|
|
689
|
-
permission: {
|
|
690
|
-
action: 'deny',
|
|
691
|
-
reason: permissionDecision.reason,
|
|
692
|
-
matched_rule: permissionDecision.matchedRule,
|
|
693
|
-
},
|
|
694
|
-
},
|
|
695
|
-
};
|
|
696
|
-
subagentUserDenied = !approval.timeout && !approval.noSubscribers;
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
else {
|
|
700
|
-
// allow — обычное выполнение
|
|
701
1067
|
if (toolDef) {
|
|
702
1068
|
const parsed2 = toolDef.parameters.safeParse(toolArgs);
|
|
703
1069
|
if (!parsed2.success) {
|
|
704
1070
|
toolResult = {
|
|
705
|
-
content:
|
|
1071
|
+
content: sm('tool.args_error', { tool: toolName, issues: parsed2.error.issues.map(i => `${i.path.join('.') || 'root'}: ${i.message}`).join('; ') }),
|
|
706
1072
|
isError: true,
|
|
1073
|
+
metadata: { i18n: i18nMeta('tool.args_error', { tool: toolName }) },
|
|
707
1074
|
};
|
|
708
1075
|
}
|
|
709
1076
|
else {
|
|
@@ -716,229 +1083,289 @@ export const taskTool = {
|
|
|
716
1083
|
}
|
|
717
1084
|
catch (execError) {
|
|
718
1085
|
toolResult = {
|
|
719
|
-
content:
|
|
1086
|
+
content: sm('tool.exec_error', { tool: toolName, error: String(execError) }),
|
|
720
1087
|
isError: true,
|
|
1088
|
+
metadata: { i18n: i18nMeta('tool.exec_error', { tool: toolName }) },
|
|
721
1089
|
};
|
|
722
1090
|
}
|
|
723
1091
|
}
|
|
724
1092
|
}
|
|
725
1093
|
else {
|
|
726
1094
|
toolResult = {
|
|
727
|
-
content:
|
|
1095
|
+
content: sm('tool.not_found', { tool: toolName }),
|
|
728
1096
|
isError: true,
|
|
1097
|
+
metadata: { i18n: i18nMeta('tool.not_found', { tool: toolName }) },
|
|
729
1098
|
};
|
|
730
1099
|
}
|
|
731
1100
|
}
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
createdAt: nowISO(),
|
|
768
|
-
disabled: false,
|
|
769
|
-
pinned: false,
|
|
770
|
-
hidden: false,
|
|
771
|
-
toolCallId: tcId,
|
|
1101
|
+
else {
|
|
1102
|
+
const why = approval.timeout
|
|
1103
|
+
? sm('permission.ask_timeout')
|
|
1104
|
+
: approval.noSubscribers
|
|
1105
|
+
? sm('permission.ask_no_subscribers')
|
|
1106
|
+
: sm('permission.ask_denied');
|
|
1107
|
+
const baseDeny = extra.contextConfig && permissionDecision.messageId
|
|
1108
|
+
? (extra.contextConfig.getSecurityMessage(permissionDecision.messageId, 'en', permissionDecision.params)
|
|
1109
|
+
?? `Permission denied: ${permissionDecision.reason}`)
|
|
1110
|
+
: `Permission denied: ${permissionDecision.reason}`;
|
|
1111
|
+
toolResult = {
|
|
1112
|
+
content: `${baseDeny} (${why})`,
|
|
1113
|
+
isError: true,
|
|
1114
|
+
metadata: {
|
|
1115
|
+
...(permissionDecision.messageId
|
|
1116
|
+
? { i18n: i18nMeta(`security.${permissionDecision.messageId.replaceAll('-', '_')}`, permissionDecision.params) }
|
|
1117
|
+
: {}),
|
|
1118
|
+
permission: {
|
|
1119
|
+
action: 'deny',
|
|
1120
|
+
reason: permissionDecision.reason,
|
|
1121
|
+
matched_rule: permissionDecision.matchedRule,
|
|
1122
|
+
},
|
|
1123
|
+
},
|
|
1124
|
+
};
|
|
1125
|
+
subagentUserDenied = !approval.timeout && !approval.noSubscribers;
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
else {
|
|
1129
|
+
// allow — обычное выполнение
|
|
1130
|
+
if (toolDef) {
|
|
1131
|
+
const parsed2 = toolDef.parameters.safeParse(toolArgs);
|
|
1132
|
+
if (!parsed2.success) {
|
|
1133
|
+
toolResult = {
|
|
1134
|
+
content: sm('tool.args_error', { tool: toolName, issues: parsed2.error.issues.map(i => `${i.path.join('.') || 'root'}: ${i.message}`).join('; ') }),
|
|
1135
|
+
isError: true,
|
|
772
1136
|
};
|
|
773
|
-
const updated = await extra.sessionManager.addMessage(childSessionId, toolResultMsg);
|
|
774
|
-
if (updated && extra.eventBus) {
|
|
775
|
-
const idx = updated.messages.length - 1;
|
|
776
|
-
await publishMessageAdded(extra.eventBus, extra.sessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
777
|
-
}
|
|
778
1137
|
}
|
|
779
|
-
|
|
780
|
-
|
|
1138
|
+
else {
|
|
1139
|
+
try {
|
|
1140
|
+
toolResult = await toolDef.execute(parsed2.data, {
|
|
1141
|
+
...ctx,
|
|
1142
|
+
abortSignal: ctx.abortSignal,
|
|
1143
|
+
extra: extra,
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
catch (execError) {
|
|
1147
|
+
toolResult = {
|
|
1148
|
+
content: sm('tool.exec_error', { tool: toolName, error: String(execError) }),
|
|
1149
|
+
isError: true,
|
|
1150
|
+
metadata: { i18n: i18nMeta('tool.exec_error', { tool: toolName }) },
|
|
1151
|
+
};
|
|
1152
|
+
}
|
|
781
1153
|
}
|
|
782
1154
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
1155
|
+
else {
|
|
1156
|
+
toolResult = {
|
|
1157
|
+
content: sm('tool.not_found', { tool: toolName }),
|
|
1158
|
+
isError: true,
|
|
1159
|
+
metadata: { i18n: i18nMeta('tool.not_found', { tool: toolName }) },
|
|
1160
|
+
};
|
|
787
1161
|
}
|
|
788
1162
|
}
|
|
789
|
-
publish?.('tool_call.
|
|
1163
|
+
publish?.('tool_call.result', {
|
|
790
1164
|
stream_id: extra.streamId,
|
|
791
1165
|
session_id: extra.sessionId,
|
|
792
|
-
|
|
793
|
-
|
|
1166
|
+
call_id: tcId,
|
|
1167
|
+
name: toolName,
|
|
1168
|
+
result: toolResult,
|
|
1169
|
+
iteration: stepIteration,
|
|
1170
|
+
parent_call_id: extra.callId,
|
|
1171
|
+
});
|
|
1172
|
+
allSubagentToolCalls.push({
|
|
1173
|
+
name: toolName,
|
|
1174
|
+
args: toolArgs,
|
|
1175
|
+
id: tcId,
|
|
1176
|
+
result: { content: toolResult.content, isError: toolResult.isError },
|
|
1177
|
+
started_at: tcStartedAt,
|
|
1178
|
+
completed_at: new Date().toISOString(),
|
|
1179
|
+
iteration: stepIteration,
|
|
794
1180
|
});
|
|
795
|
-
|
|
1181
|
+
const toolResultLLMMsg = {
|
|
1182
|
+
id: '', role: 'tool',
|
|
1183
|
+
content: toolResult.content,
|
|
1184
|
+
usage: { inputTokens: 0, outputTokens: 0, totalTokens: 0 },
|
|
1185
|
+
disabled: false, pinned: false, branchId: '',
|
|
1186
|
+
toolCallId: tcId,
|
|
1187
|
+
};
|
|
1188
|
+
messages.push(toolResultLLMMsg);
|
|
1189
|
+
// Сохранить tool_result в дочернюю сессию
|
|
1190
|
+
if (childSessionId && extra.sessionManager) {
|
|
1191
|
+
try {
|
|
1192
|
+
const toolResultMsg = {
|
|
1193
|
+
id: generateId(),
|
|
1194
|
+
role: MessageRole.TOOL,
|
|
1195
|
+
seq: 0,
|
|
1196
|
+
origin: 'local',
|
|
1197
|
+
parts: [makeTextPart(toolResult.content)],
|
|
1198
|
+
content: toolResult.content,
|
|
1199
|
+
createdAt: nowISO(),
|
|
1200
|
+
disabled: false,
|
|
1201
|
+
pinned: false,
|
|
1202
|
+
hidden: false,
|
|
1203
|
+
toolCallId: tcId,
|
|
1204
|
+
metadata: {
|
|
1205
|
+
stream_id: extra.streamId,
|
|
1206
|
+
tool_chain: true,
|
|
1207
|
+
tool_name: toolName,
|
|
1208
|
+
args: toolArgs,
|
|
1209
|
+
},
|
|
1210
|
+
};
|
|
1211
|
+
const updated = await extra.sessionManager.addMessage(childSessionId, toolResultMsg);
|
|
1212
|
+
if (updated && extra.eventBus) {
|
|
1213
|
+
const idx = updated.messages.length - 1;
|
|
1214
|
+
await publishMessageAdded(extra.eventBus, parentSessionId, childSessionId, updated.messages[idx], idx, updated);
|
|
1215
|
+
}
|
|
1216
|
+
}
|
|
1217
|
+
catch {
|
|
1218
|
+
// не фатально
|
|
1219
|
+
}
|
|
1220
|
+
}
|
|
1221
|
+
// AD-029: пользователь отклонил ask саб-агента — прекращаем выполнение.
|
|
1222
|
+
if (subagentUserDenied) {
|
|
1223
|
+
subagentDenied = true;
|
|
796
1224
|
break;
|
|
1225
|
+
}
|
|
797
1226
|
}
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
1227
|
+
publish?.('tool_call.loop', {
|
|
1228
|
+
stream_id: extra.streamId,
|
|
1229
|
+
session_id: extra.sessionId,
|
|
1230
|
+
iteration: stepIteration,
|
|
1231
|
+
total_tool_calls: toolCalls.length,
|
|
1232
|
+
});
|
|
1233
|
+
if (subagentDenied)
|
|
1234
|
+
break;
|
|
1235
|
+
}
|
|
1236
|
+
// Отмена до/после цикла (например сигнал уже абортирован на входе или
|
|
1237
|
+
// пришёл во время исполнения тулов саб-агента) — тот же протокол
|
|
1238
|
+
// прерывания, что и при отмене во время стрима.
|
|
1239
|
+
if (isAborted()) {
|
|
1240
|
+
return await finishAborted('', '');
|
|
1241
|
+
}
|
|
1242
|
+
if (subagentDenied && !finalContent) {
|
|
1243
|
+
finalContent = sm('task.stopped_by_deny');
|
|
1244
|
+
}
|
|
1245
|
+
const output = finalContent || sm('task.empty_response');
|
|
1246
|
+
// ─── Quality check результата саб-агента (AD-034 Фаза 4) ─────
|
|
1247
|
+
let qaPass;
|
|
1248
|
+
let qaReason;
|
|
1249
|
+
let qualityOutput = output;
|
|
1250
|
+
const escalationCfg = extra.routerConfig?.escalation;
|
|
1251
|
+
const sessionEscalation = extra.parentSessionSettings?.routingEscalation;
|
|
1252
|
+
const escalationEnabled = sessionEscalation?.enabled ?? escalationCfg?.enabled ?? false;
|
|
1253
|
+
if (extra.modelRouter && escalationEnabled && finalContent && routingDecisionInfo) {
|
|
1254
|
+
try {
|
|
1255
|
+
const qaResult = await extra.modelRouter.checkQuality(finalContent, {
|
|
1256
|
+
providerName: routingDecisionInfo.providerName,
|
|
1257
|
+
modelName: routingDecisionInfo.modelName,
|
|
1258
|
+
reason: routingDecisionInfo.strategy,
|
|
1259
|
+
strategy: routingDecisionInfo.strategy,
|
|
1260
|
+
}, extra.parentSessionSettings);
|
|
1261
|
+
qaPass = qaResult.pass;
|
|
1262
|
+
qaReason = qaResult.reason;
|
|
1263
|
+
// Пометить QA-информацию в дочерней сессии
|
|
1264
|
+
if (childSessionId && extra.sessionManager) {
|
|
1265
|
+
try {
|
|
1266
|
+
const childSession = await extra.sessionManager.getSession(childSessionId);
|
|
1267
|
+
if (childSession) {
|
|
1268
|
+
const lastAssistantMsg = [...childSession.messages].reverse()
|
|
1269
|
+
.find(m => m.role === MessageRole.ASSISTANT);
|
|
1270
|
+
if (lastAssistantMsg) {
|
|
1271
|
+
lastAssistantMsg.qa_pass = qaResult.pass;
|
|
1272
|
+
lastAssistantMsg.qa_reason = qaResult.reason;
|
|
1273
|
+
await extra.sessionManager.updateSession(childSession);
|
|
831
1274
|
}
|
|
832
1275
|
}
|
|
833
|
-
catch {
|
|
834
|
-
// не фатально
|
|
835
|
-
}
|
|
836
1276
|
}
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
1277
|
+
catch {
|
|
1278
|
+
// не фатально
|
|
1279
|
+
}
|
|
1280
|
+
}
|
|
1281
|
+
// Эскалация на fallback-модель при FAIL
|
|
1282
|
+
if (!qaResult.pass) {
|
|
1283
|
+
const fallbackProvider = sessionEscalation?.fallbackProvider || escalationCfg?.fallbackProvider;
|
|
1284
|
+
const fallbackModel = sessionEscalation?.fallbackModel || escalationCfg?.fallbackModel;
|
|
1285
|
+
if (fallbackProvider && fallbackModel && extra.modelRouter) {
|
|
1286
|
+
const fbDecision = {
|
|
1287
|
+
providerName: fallbackProvider,
|
|
1288
|
+
modelName: fallbackModel,
|
|
1289
|
+
reason: 'escalation_fallback',
|
|
1290
|
+
strategy: 'default',
|
|
1291
|
+
};
|
|
1292
|
+
const fbEffectiveProvider = extra.modelRouter.getProvider(fbDecision);
|
|
1293
|
+
if (fbEffectiveProvider) {
|
|
1294
|
+
try {
|
|
1295
|
+
// Перевызываем с fallback-моделью (только последний user-запрос)
|
|
1296
|
+
const fbMessages = [messages[0]];
|
|
1297
|
+
// Добавляем только user-сообщение без tool-результатов
|
|
1298
|
+
const userMsg = messages.find(m => m.role === 'user');
|
|
1299
|
+
if (userMsg)
|
|
1300
|
+
fbMessages.push(userMsg);
|
|
1301
|
+
const fbResponse = await fbEffectiveProvider.chat(fbMessages, systemPrompt || undefined, undefined, false);
|
|
1302
|
+
if (fbResponse.content) {
|
|
1303
|
+
finalContent = fbResponse.content;
|
|
1304
|
+
qualityOutput = fbResponse.content;
|
|
1305
|
+
qaPass = true;
|
|
1306
|
+
qaReason = sm('router.escalation', { provider: fallbackProvider, model: fallbackModel, reason: qaResult.reason });
|
|
1307
|
+
routingDecisionInfo = {
|
|
1308
|
+
providerName: fallbackProvider,
|
|
1309
|
+
modelName: fallbackModel,
|
|
1310
|
+
strategy: 'escalation_fallback',
|
|
1311
|
+
};
|
|
872
1312
|
}
|
|
873
1313
|
}
|
|
1314
|
+
catch {
|
|
1315
|
+
// fallback не удался, оставляем оригинальный ответ
|
|
1316
|
+
}
|
|
874
1317
|
}
|
|
875
1318
|
}
|
|
876
1319
|
}
|
|
877
|
-
catch {
|
|
878
|
-
// QA не удался, не блокируем
|
|
879
|
-
}
|
|
880
1320
|
}
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
try {
|
|
884
|
-
const childSession = await extra.sessionManager.getSession(childSessionId);
|
|
885
|
-
if (childSession) {
|
|
886
|
-
childSession.status.state = TsmState.DONE;
|
|
887
|
-
childSession.updatedAt = nowISO();
|
|
888
|
-
await extra.sessionManager.updateSession(childSession);
|
|
889
|
-
if (extra.eventBus) {
|
|
890
|
-
extra.eventBus.publish(childSessionId, 'session.updated', {
|
|
891
|
-
session_id: childSessionId,
|
|
892
|
-
status: { state: TsmState.DONE },
|
|
893
|
-
});
|
|
894
|
-
extra.eventBus.publish(extra.sessionId, 'child.session.updated', {
|
|
895
|
-
session: serializeSession(childSession),
|
|
896
|
-
});
|
|
897
|
-
}
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
catch {
|
|
901
|
-
// не фатально
|
|
902
|
-
}
|
|
1321
|
+
catch {
|
|
1322
|
+
// QA не удался, не блокируем
|
|
903
1323
|
}
|
|
904
|
-
// ─── Формирование результата tool_result ──────────────────────
|
|
905
|
-
const qualityBlock = qaPass !== undefined
|
|
906
|
-
? `<quality pass="${qaPass}" reason="${qaReason || ''}"/>\n`
|
|
907
|
-
: '';
|
|
908
|
-
const routedByBlock = routingDecisionInfo && routingDecisionInfo.strategy !== 'default'
|
|
909
|
-
? `<routed_by strategy="${routingDecisionInfo.strategy}" provider="${routingDecisionInfo.providerName}" model="${routingDecisionInfo.modelName}"/>\n`
|
|
910
|
-
: '';
|
|
911
|
-
const qaWarningText = qaPass === false
|
|
912
|
-
? `\n\n⚠️ Ответ не прошёл контроль качества: ${qaReason || 'неизвестная причина'}`
|
|
913
|
-
: '';
|
|
914
|
-
return {
|
|
915
|
-
content: `<task_result>\n<summary>${params.description}</summary>\n${qualityBlock}${routedByBlock}\n${qualityOutput}${qaWarningText}\n</task_result>`,
|
|
916
|
-
metadata: {
|
|
917
|
-
subagent_type: params.subagent_type,
|
|
918
|
-
description: params.description,
|
|
919
|
-
context_mode: contextMode,
|
|
920
|
-
steps: iteration,
|
|
921
|
-
child_session_id: childSessionId,
|
|
922
|
-
reasoning: subagentReasoning || undefined,
|
|
923
|
-
reasoning_blocks: allSubagentReasoning.length > 0 ? allSubagentReasoning : undefined,
|
|
924
|
-
intermediate_text_blocks: allSubagentIntermediateTexts.length > 0 ? allSubagentIntermediateTexts : undefined,
|
|
925
|
-
tool_calls: allSubagentToolCalls.length > 0 ? allSubagentToolCalls : undefined,
|
|
926
|
-
final_content: finalContent || undefined,
|
|
927
|
-
qa_pass: qaPass,
|
|
928
|
-
qa_reason: qaReason || undefined,
|
|
929
|
-
routing_strategy: routingDecisionInfo?.strategy,
|
|
930
|
-
routing_provider: routingDecisionInfo?.providerName,
|
|
931
|
-
routing_model: routingDecisionInfo?.modelName,
|
|
932
|
-
},
|
|
933
|
-
};
|
|
934
1324
|
}
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1325
|
+
// Финализировать дочернюю сессию
|
|
1326
|
+
await finalizeChildSession();
|
|
1327
|
+
// ─── Формирование результата tool_result ──────────────────────
|
|
1328
|
+
const qualityBlock = qaPass !== undefined
|
|
1329
|
+
? `<quality pass="${qaPass}" reason="${qaReason || ''}"/>\n`
|
|
1330
|
+
: '';
|
|
1331
|
+
const routedByBlock = routingDecisionInfo && routingDecisionInfo.strategy !== 'default'
|
|
1332
|
+
? `<routed_by strategy="${routingDecisionInfo.strategy}" provider="${routingDecisionInfo.providerName}" model="${routingDecisionInfo.modelName}"/>\n`
|
|
1333
|
+
: '';
|
|
1334
|
+
const qaWarningText = qaPass === false
|
|
1335
|
+
? `\n\n⚠️ Response failed the quality check: ${qaReason || 'unknown reason'}`
|
|
1336
|
+
: '';
|
|
1337
|
+
// ID дочерней сессии в content — родительская модель может прочитать
|
|
1338
|
+
// историю саб-агента тулом read_session_reference.
|
|
1339
|
+
const childSessionBlock = childSessionId
|
|
1340
|
+
? `<child_session_id>${childSessionId}</child_session_id>\n`
|
|
1341
|
+
: '';
|
|
1342
|
+
return {
|
|
1343
|
+
content: `<task_result>\n<summary>${description}</summary>\n${qualityBlock}${routedByBlock}${childSessionBlock}\n${qualityOutput}${qaWarningText}\n</task_result>`,
|
|
1344
|
+
metadata: {
|
|
1345
|
+
subagent_type: subagentType,
|
|
1346
|
+
description: description,
|
|
1347
|
+
context_mode: contextMode,
|
|
1348
|
+
steps: iteration,
|
|
1349
|
+
child_session_id: childSessionId,
|
|
1350
|
+
reasoning: subagentReasoning || undefined,
|
|
1351
|
+
reasoning_blocks: allSubagentReasoning.length > 0 ? allSubagentReasoning : undefined,
|
|
1352
|
+
intermediate_text_blocks: allSubagentIntermediateTexts.length > 0 ? allSubagentIntermediateTexts : undefined,
|
|
1353
|
+
tool_calls: allSubagentToolCalls.length > 0 ? allSubagentToolCalls : undefined,
|
|
1354
|
+
final_content: finalContent || undefined,
|
|
1355
|
+
qa_pass: qaPass,
|
|
1356
|
+
qa_reason: qaReason || undefined,
|
|
1357
|
+
routing_strategy: routingDecisionInfo?.strategy,
|
|
1358
|
+
routing_provider: routingDecisionInfo?.providerName,
|
|
1359
|
+
routing_model: routingDecisionInfo?.modelName,
|
|
1360
|
+
},
|
|
1361
|
+
};
|
|
1362
|
+
}
|
|
1363
|
+
catch (err) {
|
|
1364
|
+
return {
|
|
1365
|
+
content: sm('task.subagent_exec_error', { type: subagentType, error: String(err) }),
|
|
1366
|
+
isError: true,
|
|
1367
|
+
metadata: { subagent_type: subagentType },
|
|
1368
|
+
};
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
944
1371
|
//# sourceMappingURL=task.js.map
|