crewly 1.20.143 → 1.20.145
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/config/constants.ts +59 -0
- package/config/index.ts +2 -0
- package/config/roles/orchestrator/prompt.md +9 -0
- package/config/skills/orchestrator/delegate-task/execute.sh +11 -0
- package/config/skills/orchestrator/delegate-task/execute.test.sh +38 -0
- package/config/skills/orchestrator/harness-login/SKILL.md +88 -0
- package/config/skills/orchestrator/harness-login/execute.sh +75 -0
- package/config/skills/orchestrator/harness-login/execute.test.sh +72 -0
- package/config/skills/orchestrator/reply-chat/SKILL.md +11 -1
- package/config/skills/orchestrator/reply-chat/execute.sh +13 -1
- package/config/skills/orchestrator/reply-slack/SKILL.md +1 -0
- package/config/skills/orchestrator/reply-slack/execute.sh +11 -2
- package/dist/backend/backend/src/constants.d.ts +55 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +36 -1
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +36 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts +1 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/harness/harness.routes.js +3 -0
- package/dist/backend/backend/src/controllers/harness/harness.routes.js.map +1 -1
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.d.ts +61 -0
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js +133 -0
- package/dist/backend/backend/src/controllers/harness/owner-login.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/slack/slack.controller.js +69 -7
- package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts +4 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js +9 -2
- package/dist/backend/backend/src/controllers/task-pool/task-pool.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts +8 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +75 -3
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js +28 -1
- package/dist/backend/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/codex-runtime.service.d.ts +11 -1
- package/dist/backend/backend/src/services/agent/codex-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/codex-runtime.service.js +18 -0
- package/dist/backend/backend/src/services/agent/codex-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +12 -0
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +18 -3
- package/dist/backend/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts +29 -0
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js +48 -0
- package/dist/backend/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -1
- package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +15 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +20 -0
- package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts +147 -5
- package/dist/backend/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js +210 -20
- package/dist/backend/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts +87 -0
- package/dist/backend/backend/src/services/harness/owner-login-request.d.ts.map +1 -0
- package/dist/backend/backend/src/services/harness/owner-login-request.js +191 -0
- package/dist/backend/backend/src/services/harness/owner-login-request.js.map +1 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts +217 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.js +300 -0
- package/dist/backend/backend/src/services/orc/orc-reply-route.service.js.map +1 -0
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts +32 -2
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js +59 -5
- package/dist/backend/backend/src/services/reconciler/reconcile-rules.js.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts +4 -2
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.d.ts.map +1 -1
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js +6 -3
- package/dist/backend/backend/src/services/reconciler/reconciler-data-provider.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts +68 -9
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.js +121 -11
- package/dist/backend/backend/src/services/slack/slack-relogin-dm.service.js.map +1 -1
- package/dist/backend/backend/src/services/system/auto-update.service.d.ts +292 -0
- package/dist/backend/backend/src/services/system/auto-update.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/system/auto-update.service.js +590 -0
- package/dist/backend/backend/src/services/system/auto-update.service.js.map +1 -0
- package/dist/backend/backend/src/services/system/auto-update.utils.d.ts +265 -0
- package/dist/backend/backend/src/services/system/auto-update.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/services/system/auto-update.utils.js +397 -0
- package/dist/backend/backend/src/services/system/auto-update.utils.js.map +1 -0
- package/dist/backend/backend/src/services/system/version-check.service.d.ts +15 -1
- package/dist/backend/backend/src/services/system/version-check.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/system/version-check.service.js +21 -2
- package/dist/backend/backend/src/services/system/version-check.service.js.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts +7 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js +14 -2
- package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/backend/backend/src/services/v3/cascade-request-status.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/cascade-request-status.js +16 -1
- package/dist/backend/backend/src/services/v3/cascade-request-status.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request-completion.d.ts +128 -0
- package/dist/backend/backend/src/services/v3/request-completion.d.ts.map +1 -0
- package/dist/backend/backend/src/services/v3/request-completion.js +311 -0
- package/dist/backend/backend/src/services/v3/request-completion.js.map +1 -0
- package/dist/backend/backend/src/services/v3/request-decompose.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js +3 -0
- package/dist/backend/backend/src/services/v3/request-decompose.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/v3/request-status-update.subscriber.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/request-status-update.subscriber.js +17 -3
- package/dist/backend/backend/src/services/v3/request-status-update.subscriber.js.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts +8 -0
- package/dist/backend/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.js +11 -1
- package/dist/backend/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/backend/backend/src/types/settings.types.d.ts +8 -0
- package/dist/backend/backend/src/types/settings.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/settings.types.js +4 -0
- package/dist/backend/backend/src/types/settings.types.js.map +1 -1
- package/dist/backend/backend/src/utils/agent-reply-filter.utils.d.ts +75 -0
- package/dist/backend/backend/src/utils/agent-reply-filter.utils.d.ts.map +1 -0
- package/dist/backend/backend/src/utils/agent-reply-filter.utils.js +127 -0
- package/dist/backend/backend/src/utils/agent-reply-filter.utils.js.map +1 -0
- package/dist/backend/build-info.json +2 -2
- package/dist/backend/config/constants.d.ts +56 -0
- package/dist/backend/config/constants.d.ts.map +1 -1
- package/dist/backend/config/constants.js +57 -0
- package/dist/backend/config/constants.js.map +1 -1
- package/dist/backend/config/index.d.ts +2 -2
- package/dist/backend/config/index.d.ts.map +1 -1
- package/dist/backend/config/index.js +2 -2
- package/dist/backend/config/index.js.map +1 -1
- package/dist/cli/backend/src/constants.d.ts +55 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +36 -1
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js +28 -1
- package/dist/cli/backend/src/services/agent/agent-registration.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts +11 -1
- package/dist/cli/backend/src/services/agent/codex-runtime.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/codex-runtime.service.js +18 -0
- package/dist/cli/backend/src/services/agent/codex-runtime.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts +12 -0
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js +18 -3
- package/dist/cli/backend/src/services/agent/crewly-agent/crewly-agent-external-runtime.service.js.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts +29 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.d.ts.map +1 -1
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js +48 -0
- package/dist/cli/backend/src/services/agent/runtime-agent.service.abstract.js.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +1 -1
- package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +15 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +20 -0
- package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts +147 -5
- package/dist/cli/backend/src/services/harness/harness-relogin.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js +210 -20
- package/dist/cli/backend/src/services/harness/harness-relogin.service.js.map +1 -1
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts +87 -0
- package/dist/cli/backend/src/services/harness/owner-login-request.d.ts.map +1 -0
- package/dist/cli/backend/src/services/harness/owner-login-request.js +191 -0
- package/dist/cli/backend/src/services/harness/owner-login-request.js.map +1 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts +217 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.js +300 -0
- package/dist/cli/backend/src/services/orc/orc-reply-route.service.js.map +1 -0
- package/dist/cli/backend/src/services/system/auto-update.utils.d.ts +265 -0
- package/dist/cli/backend/src/services/system/auto-update.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/services/system/auto-update.utils.js +397 -0
- package/dist/cli/backend/src/services/system/auto-update.utils.js.map +1 -0
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts +7 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js +14 -2
- package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
- package/dist/cli/backend/src/services/v3/request-completion.d.ts +128 -0
- package/dist/cli/backend/src/services/v3/request-completion.d.ts.map +1 -0
- package/dist/cli/backend/src/services/v3/request-completion.js +311 -0
- package/dist/cli/backend/src/services/v3/request-completion.js.map +1 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.d.ts +8 -0
- package/dist/cli/backend/src/services/v3/v3-data.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/v3/v3-data.service.js +11 -1
- package/dist/cli/backend/src/services/v3/v3-data.service.js.map +1 -1
- package/dist/cli/backend/src/types/settings.types.d.ts +8 -0
- package/dist/cli/backend/src/types/settings.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/settings.types.js +4 -0
- package/dist/cli/backend/src/types/settings.types.js.map +1 -1
- package/dist/cli/backend/src/utils/agent-reply-filter.utils.d.ts +75 -0
- package/dist/cli/backend/src/utils/agent-reply-filter.utils.d.ts.map +1 -0
- package/dist/cli/backend/src/utils/agent-reply-filter.utils.js +127 -0
- package/dist/cli/backend/src/utils/agent-reply-filter.utils.js.map +1 -0
- package/dist/cli/cli/src/commands/start.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/start.js +14 -3
- package/dist/cli/cli/src/commands/start.js.map +1 -1
- package/dist/cli/cli/src/commands/update-status.d.ts +85 -0
- package/dist/cli/cli/src/commands/update-status.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/update-status.js +162 -0
- package/dist/cli/cli/src/commands/update-status.js.map +1 -0
- package/dist/cli/cli/src/constants.d.ts +1 -1
- package/dist/cli/cli/src/constants.d.ts.map +1 -1
- package/dist/cli/cli/src/constants.js +1 -1
- package/dist/cli/cli/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +7 -0
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/backend-respawn.d.ts +50 -0
- package/dist/cli/cli/src/utils/backend-respawn.d.ts.map +1 -0
- package/dist/cli/cli/src/utils/backend-respawn.js +59 -0
- package/dist/cli/cli/src/utils/backend-respawn.js.map +1 -0
- package/dist/cli/config/constants.d.ts +56 -0
- package/dist/cli/config/constants.d.ts.map +1 -1
- package/dist/cli/config/constants.js +57 -0
- package/dist/cli/config/constants.js.map +1 -1
- package/dist/cli/config/index.d.ts +2 -2
- package/dist/cli/config/index.d.ts.map +1 -1
- package/dist/cli/config/index.js +2 -2
- package/dist/cli/config/index.js.map +1 -1
- package/frontend/dist/assets/{index-e05af897.js → index-71670b91.js} +22 -22
- package/frontend/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/crewly-agent/src/runtime/agent-runner.service.test.ts +39 -0
- package/packages/crewly-agent/src/runtime/agent-runner.service.ts +17 -17
- package/packages/crewly-agent/src/runtime/interactive-login-guard.test.ts +60 -0
- package/packages/crewly-agent/src/runtime/interactive-login-guard.ts +76 -0
- package/packages/crewly-agent/src/runtime/reply-tool-calls.test.ts +53 -0
- package/packages/crewly-agent/src/runtime/reply-tool-calls.ts +76 -0
- package/packages/crewly-agent/src/runtime/tool-registry.test.ts +8 -0
- package/packages/crewly-agent/src/runtime/tool-registry.ts +14 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Owner login requests — recognising "log harness X in" in plain words.
|
|
3
|
+
*
|
|
4
|
+
* Two consumers:
|
|
5
|
+
* - {@link parseOwnerLoginRequest}: the Slack DM interceptor. An owner who
|
|
6
|
+
* writes 「重新登录 claude」, 「换个账号登录 claude」 or "relogin codex" in the
|
|
7
|
+
* orchestrator's DM gets the login flow directly, without the LLM. The
|
|
8
|
+
* match is deliberately strict — the whole message must be the request —
|
|
9
|
+
* so a sentence that merely mentions a login still goes to the orc.
|
|
10
|
+
* - {@link isOwnerLoginRequestEvidence}: the orchestrator's `harness-login`
|
|
11
|
+
* skill. The orc may start a login only when a real owner message asked for
|
|
12
|
+
* one; this is the evidence check over the owner's recent messages.
|
|
13
|
+
*
|
|
14
|
+
* Incident 2026-09-26: the orc ran `claude setup-token` in its one-shot bash
|
|
15
|
+
* tool (the process died with the call, every pasted code went stale) and
|
|
16
|
+
* then claimed several times that it had sent a new link. The broker-backed
|
|
17
|
+
* flow started from here keeps the login alive in its own PTY.
|
|
18
|
+
*
|
|
19
|
+
* @module services/harness/owner-login-request
|
|
20
|
+
*/
|
|
21
|
+
import { HARNESS_CONSTANTS } from '../../constants.js';
|
|
22
|
+
/** Harness names and aliases → id, longest first so "claude code" wins over "claude". */
|
|
23
|
+
const HARNESS_NAME_PATTERNS = [
|
|
24
|
+
{ re: /^claude[\s_-]*code$/, id: HARNESS_CONSTANTS.IDS.CLAUDE_CODE },
|
|
25
|
+
{ re: /^claude$/, id: HARNESS_CONSTANTS.IDS.CLAUDE_CODE },
|
|
26
|
+
{ re: /^codex(?:[\s_-]*cli)?$/, id: HARNESS_CONSTANTS.IDS.CODEX_CLI },
|
|
27
|
+
{ re: /^antigravity(?:[\s_-]*cli)?$/, id: HARNESS_CONSTANTS.IDS.ANTIGRAVITY_CLI },
|
|
28
|
+
{ re: /^agy$/, id: HARNESS_CONSTANTS.IDS.ANTIGRAVITY_CLI },
|
|
29
|
+
{ re: /^gemini(?:[\s_-]*cli)?$/, id: HARNESS_CONSTANTS.IDS.GEMINI_CLI },
|
|
30
|
+
];
|
|
31
|
+
/** Any harness mention inside a longer message (evidence check). */
|
|
32
|
+
const HARNESS_MENTIONS = [
|
|
33
|
+
{ re: /claude/i, id: HARNESS_CONSTANTS.IDS.CLAUDE_CODE },
|
|
34
|
+
{ re: /codex/i, id: HARNESS_CONSTANTS.IDS.CODEX_CLI },
|
|
35
|
+
{ re: /antigravity|\bagy\b/i, id: HARNESS_CONSTANTS.IDS.ANTIGRAVITY_CLI },
|
|
36
|
+
{ re: /gemini/i, id: HARNESS_CONSTANTS.IDS.GEMINI_CLI },
|
|
37
|
+
];
|
|
38
|
+
/**
|
|
39
|
+
* Names that are coding assistants Crewly does not run. "登录 cursor" is
|
|
40
|
+
* answered with the supported list; any other unknown word after a login
|
|
41
|
+
* verb ("登录 gmail") is not a harness request and goes to the orc.
|
|
42
|
+
*/
|
|
43
|
+
const OTHER_CODING_TOOLS = /^(?:cursor|copilot|github\s*copilot|aider|opencode|cline|windsurf|kimi(?:\s*cli)?|qwen(?:\s*code)?|amp|goose|kiro|trae)$/;
|
|
44
|
+
/** Generic words for "the coding assistant" — a request for a harness without naming one. */
|
|
45
|
+
const GENERIC_HARNESS_WORDS = /^(?:harness|编程助手|编码助手|代码助手|ai\s*harness|cli)$/;
|
|
46
|
+
/** Chinese login verbs. The account-switch forms come first so they win. */
|
|
47
|
+
const ZH_VERB = '(?:换(?:一)?个(?:新)?账号(?:重新)?登[录陆]|换(?:一)?个号(?:重新)?登[录陆]|换账号(?:重新)?登[录陆]|换号(?:重新)?登[录陆]|用(?:另|别)(?:一)?个账号(?:重新)?登[录陆]|切换账号|换(?:一)?个(?:新)?账号|换账号|换号|重新登[录陆入]|重登[录陆]?|再登[录陆]|登[录陆入])';
|
|
48
|
+
/** English login verbs. */
|
|
49
|
+
const EN_VERB = '(?:re-?log\\s*in(?:\\s+to)?|re-?login(?:\\s+to)?|log\\s*in(?:\\s+to)?|login(?:\\s+to)?|sign\\s*in(?:\\s+to)?|re-?auth(?:enticate)?|switch\\s+(?:the\\s+)?accounts?(?:\\s+(?:for|of|on))?)';
|
|
50
|
+
/** Polite lead-ins that do not change the request. */
|
|
51
|
+
const PREFIX = '(?:(?:please|pls|can\\s+you|could\\s+you)\\s+)?(?:帮我|帮忙|麻烦(?:你)?|请(?:你)?|给我|你)?\\s*(?:(?:把|给|帮)\\s*)?';
|
|
52
|
+
/** Harmless endings. No 吗/了: "登录 claude 了吗" asks about a login, it does not request one. */
|
|
53
|
+
const SUFFIX = '\\s*(?:一下|下|吧)?\\s*[.。!!~~]*';
|
|
54
|
+
/** A name after or before the verb: up to three ASCII words, fewest first ("claude code", not "claude account"). */
|
|
55
|
+
const NAME = '([a-z][a-z0-9_-]*(?:\\s+[a-z][a-z0-9_-]*){0,2}?|编程助手|编码助手|代码助手)';
|
|
56
|
+
/** Optional "account" noun after the name ("claude 的账号", "claude account"). */
|
|
57
|
+
const ACCOUNT_NOUN = '(?:\\s*(?:的)?(?:账号|帐号|account))?';
|
|
58
|
+
/** "登录 claude" / "relogin to codex" / "换个账号登录 claude code". */
|
|
59
|
+
const VERB_FIRST = new RegExp(`^${PREFIX}(${ZH_VERB}|${EN_VERB})\\s*(?:到\\s*)?${NAME}${ACCOUNT_NOUN}${SUFFIX}$`, 'i');
|
|
60
|
+
/** "claude 重新登录" / "codex login" / "把 claude 换个账号登录". */
|
|
61
|
+
const NAME_FIRST = new RegExp(`^${PREFIX}${NAME}${ACCOUNT_NOUN}\\s*(?:重新)?(${ZH_VERB}|${EN_VERB})${SUFFIX}$`, 'i');
|
|
62
|
+
/** "给 claude 换个账号" / "switch claude account" / "switch claude to another account". */
|
|
63
|
+
const SWITCH_NAME = new RegExp(`^${PREFIX}(?:switch|change)\\s+${NAME}\\s+(?:to\\s+(?:another|a\\s+different|a\\s+new)\\s+)?accounts?${SUFFIX}$`, 'i');
|
|
64
|
+
/** A bare verb ("重新登录", "login") — a request with no harness named. */
|
|
65
|
+
const BARE_VERB = new RegExp(`^${PREFIX}(${ZH_VERB}|${EN_VERB})${SUFFIX}$`, 'i');
|
|
66
|
+
/** Words that mark an account switch. */
|
|
67
|
+
const SWITCH_WORDS = /换|切换|switch|another\s+account|different\s+account|other\s+account|另一个账号|别的账号|其他账号/i;
|
|
68
|
+
/**
|
|
69
|
+
* Normalise a DM for matching: drop Slack mention/link markup, collapse
|
|
70
|
+
* whitespace, lower-case, trim.
|
|
71
|
+
*
|
|
72
|
+
* @param text - Raw message text
|
|
73
|
+
* @returns Normalised text
|
|
74
|
+
*/
|
|
75
|
+
export function normaliseLoginText(text) {
|
|
76
|
+
return text
|
|
77
|
+
.replace(/<@[A-Z0-9]+>/g, ' ')
|
|
78
|
+
.replace(/<([^|>]+)\|([^>]+)>/g, '$2')
|
|
79
|
+
.replace(/[「」“”"'`]/g, ' ')
|
|
80
|
+
.replace(/\s+/g, ' ')
|
|
81
|
+
.trim()
|
|
82
|
+
.toLowerCase();
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve a harness name or alias as written by a person.
|
|
86
|
+
*
|
|
87
|
+
* @param name - e.g. "claude code", "Claude", "agy", "codex cli"
|
|
88
|
+
* @returns The harness id, or null
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* resolveHarnessName('claude code'); // 'claude-code'
|
|
93
|
+
* ```
|
|
94
|
+
*/
|
|
95
|
+
export function resolveHarnessName(name) {
|
|
96
|
+
const key = name.trim().toLowerCase().replace(/\s+/g, ' ');
|
|
97
|
+
for (const { re, id } of HARNESS_NAME_PATTERNS) {
|
|
98
|
+
if (re.test(key))
|
|
99
|
+
return id;
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Turn a matched name into a request, or null when the name is not about a
|
|
105
|
+
* coding assistant at all ("登录 gmail" is for the orc, not for us).
|
|
106
|
+
*
|
|
107
|
+
* @param rawName - Name as matched
|
|
108
|
+
* @param switchAccount - Whether the owner asked for a different account
|
|
109
|
+
* @returns The request or null
|
|
110
|
+
*/
|
|
111
|
+
function requestForName(rawName, switchAccount) {
|
|
112
|
+
const name = rawName.trim();
|
|
113
|
+
const harnessId = resolveHarnessName(name);
|
|
114
|
+
if (harnessId)
|
|
115
|
+
return { kind: 'harness', harnessId, switchAccount };
|
|
116
|
+
if (GENERIC_HARNESS_WORDS.test(name))
|
|
117
|
+
return { kind: 'unknown', name: null, switchAccount };
|
|
118
|
+
if (OTHER_CODING_TOOLS.test(name))
|
|
119
|
+
return { kind: 'unknown', name, switchAccount };
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Recognise an owner's DM that asks Crewly to log a harness in (or switch
|
|
124
|
+
* its account). The whole message must be the request; anything longer or
|
|
125
|
+
* different returns null and is handled by the orchestrator as usual.
|
|
126
|
+
*
|
|
127
|
+
* @param text - Owner DM text
|
|
128
|
+
* @returns The request, or null when the message is not a login request
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```ts
|
|
132
|
+
* parseOwnerLoginRequest('换个账号登录 claude');
|
|
133
|
+
* // { kind: 'harness', harnessId: 'claude-code', switchAccount: true }
|
|
134
|
+
* parseOwnerLoginRequest('重新登录');
|
|
135
|
+
* // { kind: 'unknown', name: null, switchAccount: false }
|
|
136
|
+
* ```
|
|
137
|
+
*/
|
|
138
|
+
export function parseOwnerLoginRequest(text) {
|
|
139
|
+
if (typeof text !== 'string')
|
|
140
|
+
return null;
|
|
141
|
+
const normalised = normaliseLoginText(text);
|
|
142
|
+
if (!normalised || normalised.length > HARNESS_CONSTANTS.OWNER_LOGIN.MAX_TRIGGER_LENGTH)
|
|
143
|
+
return null;
|
|
144
|
+
const switchAccount = SWITCH_WORDS.test(normalised);
|
|
145
|
+
// Each form in turn; a form whose "name" is not a harness ("relogin" read
|
|
146
|
+
// as name "re" + verb "login") does not end the search.
|
|
147
|
+
const verbFirst = VERB_FIRST.exec(normalised);
|
|
148
|
+
const fromVerbFirst = verbFirst ? requestForName(verbFirst[2], switchAccount) : null;
|
|
149
|
+
if (fromVerbFirst)
|
|
150
|
+
return fromVerbFirst;
|
|
151
|
+
const nameFirst = NAME_FIRST.exec(normalised);
|
|
152
|
+
const fromNameFirst = nameFirst ? requestForName(nameFirst[1], switchAccount) : null;
|
|
153
|
+
if (fromNameFirst)
|
|
154
|
+
return fromNameFirst;
|
|
155
|
+
const switchName = SWITCH_NAME.exec(normalised);
|
|
156
|
+
const fromSwitch = switchName ? requestForName(switchName[1], true) : null;
|
|
157
|
+
if (fromSwitch)
|
|
158
|
+
return fromSwitch;
|
|
159
|
+
if (BARE_VERB.test(normalised))
|
|
160
|
+
return { kind: 'unknown', name: null, switchAccount };
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
/** A login verb anywhere in a message (evidence check; broader than the trigger). */
|
|
164
|
+
const LOGIN_MENTION = /登[录陆入]|重登|换(?:一)?个?账号|切换账号|换号|re-?log\s*in|re-?login|\blog\s*in\b|\blog\s+(?:\S+\s+){1,2}in\b|\blogin\b|sign\s*in|setup-token|\/login|switch\s+(?:the\s+)?accounts?|login\s+link|登[录陆]链接/i;
|
|
165
|
+
/** Status questions — asking whether it is logged in is not asking to log in. */
|
|
166
|
+
const STATUS_QUESTION = /登[录陆]了吗|登[录陆]状态|是否(?:已经)?登[录陆]|有没有登[录陆]|登[录陆]过期了吗|(?:is|are)\s+\S+\s+logged\s+in|login\s+status|still\s+logged\s+in/i;
|
|
167
|
+
/**
|
|
168
|
+
* Whether one owner message asks for a (re-)login of a harness. Mirrors the
|
|
169
|
+
* install-skill approval check: the orchestrator's claim is not trusted, the
|
|
170
|
+
* owner's own words are.
|
|
171
|
+
*
|
|
172
|
+
* Counts a message with a login verb that either names this harness or names
|
|
173
|
+
* none (「不 我要重新登陆一个账号」 in a conversation about Claude). A message
|
|
174
|
+
* naming only other harnesses, or a status question, does not count.
|
|
175
|
+
*
|
|
176
|
+
* @param message - Owner message text
|
|
177
|
+
* @param harnessId - Harness the orchestrator wants to log in
|
|
178
|
+
* @returns True when the message is evidence for that login
|
|
179
|
+
*/
|
|
180
|
+
export function isOwnerLoginRequestEvidence(message, harnessId) {
|
|
181
|
+
if (typeof message !== 'string' || !message.trim())
|
|
182
|
+
return false;
|
|
183
|
+
const parsed = parseOwnerLoginRequest(message);
|
|
184
|
+
if (parsed?.kind === 'harness')
|
|
185
|
+
return parsed.harnessId === harnessId;
|
|
186
|
+
if (!LOGIN_MENTION.test(message) || STATUS_QUESTION.test(message))
|
|
187
|
+
return false;
|
|
188
|
+
const named = HARNESS_MENTIONS.filter(({ re }) => re.test(message)).map(({ id }) => id);
|
|
189
|
+
return named.length === 0 || named.includes(harnessId);
|
|
190
|
+
}
|
|
191
|
+
//# sourceMappingURL=owner-login-request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owner-login-request.js","sourceRoot":"","sources":["../../../../../../backend/src/services/harness/owner-login-request.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orchestrator reply routing — "answer where you were asked".
|
|
3
|
+
*
|
|
4
|
+
* Tracks, per agent session, the conversation its latest user-originated
|
|
5
|
+
* message came from (the *turn origin*), and decides where a reply the
|
|
6
|
+
* orchestrator posts during or right after that turn should land.
|
|
7
|
+
*
|
|
8
|
+
* Incident 2026-09-26 03:23–03:34 UTC: the owner was talking to the orc in a
|
|
9
|
+
* Slack DM (D0C381XPD3L → chat-v2 channel a721f48d). A reconciler WorkItem
|
|
10
|
+
* redispatch then started a system turn with no `[CHAT:…]` prefix. In it the
|
|
11
|
+
* orc:
|
|
12
|
+
* - filed `report-status [BLOCKED]` and `reply-chat` without a
|
|
13
|
+
* conversationId; `/api/chat/agent-response` fell back to
|
|
14
|
+
* `ChatService.getCurrentConversation()`, which only sees system-owned
|
|
15
|
+
* channels — never the owner's orchestrator DM — and returned #think-tank
|
|
16
|
+
* (b79a6e4d), so the summary was mirrored into Slack #pro-think-tank;
|
|
17
|
+
* - called `reply-slack` on D0AC7NF5N7L, the owner's DM with the *master*
|
|
18
|
+
* Crewly bot, not the orc-bot DM the conversation was in.
|
|
19
|
+
* The question in that summary ("reply start Ella") never reached the owner.
|
|
20
|
+
*
|
|
21
|
+
* What counts as "the reply": anything the orchestrator posts to a
|
|
22
|
+
* user-facing conversation through `/api/chat/agent-response` (reply-chat,
|
|
23
|
+
* report-status) or to a Slack DM through `/api/slack/send` (reply-slack).
|
|
24
|
+
* It is re-routed to the turn origin when it targets a conversation the orc
|
|
25
|
+
* has not received a user message from recently, unless the caller marked it
|
|
26
|
+
* as a deliberate cross-post. Posts to Slack channels (team notifications,
|
|
27
|
+
* delegation) and `reply-channel` writes are not replies and are untouched.
|
|
28
|
+
*
|
|
29
|
+
* @module services/orc/orc-reply-route.service
|
|
30
|
+
*/
|
|
31
|
+
/** Where an agent's current turn came from. */
|
|
32
|
+
export interface TurnOrigin {
|
|
33
|
+
/** chat-v2 channel / conversation id the user message was recorded in. */
|
|
34
|
+
conversationId: string;
|
|
35
|
+
/** Slack channel, when the delivered message carried a `[SLACK:…]` marker. */
|
|
36
|
+
slackChannelId?: string;
|
|
37
|
+
/** Slack thread, when the marker named one. */
|
|
38
|
+
slackThreadTs?: string;
|
|
39
|
+
/** Epoch ms the message was delivered to the agent. */
|
|
40
|
+
receivedAt: number;
|
|
41
|
+
}
|
|
42
|
+
/** Parsed routing header of a delivered message. */
|
|
43
|
+
export type InboundOrigin = Omit<TurnOrigin, 'receivedAt'>;
|
|
44
|
+
/** How {@link OrcReplyRouteService.resolveConversationReply} decided. */
|
|
45
|
+
export type ReplyRouteAction =
|
|
46
|
+
/** Post where the caller asked. */
|
|
47
|
+
'as-requested'
|
|
48
|
+
/** Caller named no conversation; the turn origin was used. */
|
|
49
|
+
| 'defaulted-to-origin'
|
|
50
|
+
/** Caller named a stale conversation; the turn origin was used instead. */
|
|
51
|
+
| 'rerouted-to-origin'
|
|
52
|
+
/** Caller named nothing and no origin is known; caller keeps its fallback. */
|
|
53
|
+
| 'no-origin';
|
|
54
|
+
/** Result of a reply-target decision. */
|
|
55
|
+
export interface ReplyRouteDecision {
|
|
56
|
+
action: ReplyRouteAction;
|
|
57
|
+
/** Target to use; undefined only for `no-origin`. */
|
|
58
|
+
conversationId?: string;
|
|
59
|
+
/** Why, for logs. */
|
|
60
|
+
reason: string;
|
|
61
|
+
/** The origin consulted, if any. */
|
|
62
|
+
origin?: TurnOrigin;
|
|
63
|
+
}
|
|
64
|
+
/** Result of a Slack reply-target decision. */
|
|
65
|
+
export interface SlackReplyRouteDecision {
|
|
66
|
+
action: 'as-requested' | 'rerouted-to-origin';
|
|
67
|
+
reason: string;
|
|
68
|
+
origin?: TurnOrigin;
|
|
69
|
+
}
|
|
70
|
+
/** Where a Slack post should actually go. */
|
|
71
|
+
export type SlackReplyPlan = {
|
|
72
|
+
kind: 'slack';
|
|
73
|
+
channelId: string;
|
|
74
|
+
threadTs?: string;
|
|
75
|
+
} | {
|
|
76
|
+
kind: 'conversation';
|
|
77
|
+
conversationId: string;
|
|
78
|
+
};
|
|
79
|
+
/** Options shared by the resolve methods. */
|
|
80
|
+
export interface ResolveOptions {
|
|
81
|
+
/** Caller explicitly marked the post as a deliberate cross-post. */
|
|
82
|
+
crossPost?: boolean;
|
|
83
|
+
/** Clock override for tests. */
|
|
84
|
+
now?: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Parses the routing header of a message delivered to an agent.
|
|
88
|
+
*
|
|
89
|
+
* @param message - The exact text delivered to the agent
|
|
90
|
+
* @returns The origin, or null for system-originated deliveries
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* parseInboundOrigin('[CHAT:a721f48d] <owner@Orchestrator>\n\nhi');
|
|
95
|
+
* // → { conversationId: 'a721f48d' }
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export declare function parseInboundOrigin(message: string): InboundOrigin | null;
|
|
99
|
+
/**
|
|
100
|
+
* Whether a Slack channel id is a direct-message conversation.
|
|
101
|
+
*
|
|
102
|
+
* @param slackChannelId - Slack channel id
|
|
103
|
+
* @returns True for `D…` ids
|
|
104
|
+
*/
|
|
105
|
+
export declare function isSlackDm(slackChannelId: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Tracks turn origins and decides reply targets. Process-wide singleton; all
|
|
108
|
+
* state is in memory (a restart starts every agent on a fresh turn anyway).
|
|
109
|
+
*/
|
|
110
|
+
export declare class OrcReplyRouteService {
|
|
111
|
+
private static instance;
|
|
112
|
+
private readonly sessions;
|
|
113
|
+
/**
|
|
114
|
+
* @returns The shared instance
|
|
115
|
+
*/
|
|
116
|
+
static getInstance(): OrcReplyRouteService;
|
|
117
|
+
/** Drops the shared instance (tests). */
|
|
118
|
+
static resetInstance(): void;
|
|
119
|
+
/**
|
|
120
|
+
* Records a message delivered to an agent. User-originated messages (those
|
|
121
|
+
* with a `[CHAT:…]` header) become the session's turn origin; system
|
|
122
|
+
* deliveries leave the origin alone, so a system turn that follows a user
|
|
123
|
+
* turn still answers the user where they asked.
|
|
124
|
+
*
|
|
125
|
+
* @param sessionName - Receiving agent session
|
|
126
|
+
* @param message - Exact delivered text
|
|
127
|
+
* @param now - Clock override for tests
|
|
128
|
+
* @returns The new origin, or null when the message was system-originated
|
|
129
|
+
*/
|
|
130
|
+
noteDelivery(sessionName: string, message: string, now?: number): TurnOrigin | null;
|
|
131
|
+
/**
|
|
132
|
+
* The session's turn origin, however old.
|
|
133
|
+
*
|
|
134
|
+
* @param sessionName - Agent session
|
|
135
|
+
* @returns The last user-originated origin, or undefined
|
|
136
|
+
*/
|
|
137
|
+
getLastOrigin(sessionName: string): TurnOrigin | undefined;
|
|
138
|
+
/**
|
|
139
|
+
* The session's turn origin if it is still fresh.
|
|
140
|
+
*
|
|
141
|
+
* @param sessionName - Agent session
|
|
142
|
+
* @param now - Clock override for tests
|
|
143
|
+
* @returns The origin within {@link ORC_REPLY_ROUTE_CONSTANTS.ORIGIN_TTL_MS}
|
|
144
|
+
*/
|
|
145
|
+
getFreshOrigin(sessionName: string, now?: number): TurnOrigin | undefined;
|
|
146
|
+
/**
|
|
147
|
+
* Decides which conversation a chat reply (reply-chat, report-status)
|
|
148
|
+
* belongs in.
|
|
149
|
+
*
|
|
150
|
+
* - No conversation named → the turn origin (any age: it is still a better
|
|
151
|
+
* guess than "the newest channel in the system"); none known → caller's
|
|
152
|
+
* own fallback.
|
|
153
|
+
* - A conversation named → kept when it is the origin, when the session
|
|
154
|
+
* received a user message there recently, when the caller marked a
|
|
155
|
+
* cross-post, or when there is no fresh origin to prefer. Otherwise the
|
|
156
|
+
* reply goes to the origin.
|
|
157
|
+
*
|
|
158
|
+
* @param sessionName - Replying agent session
|
|
159
|
+
* @param requested - Conversation the caller named, if any
|
|
160
|
+
* @param options - Cross-post flag and clock
|
|
161
|
+
* @returns The decision
|
|
162
|
+
*/
|
|
163
|
+
resolveConversationReply(sessionName: string, requested: string | undefined, options?: ResolveOptions): ReplyRouteDecision;
|
|
164
|
+
/**
|
|
165
|
+
* Decides whether a Slack post is a misdirected reply. Only DMs are
|
|
166
|
+
* candidates — posting in a channel is how the orchestrator notifies teams
|
|
167
|
+
* and delegates, so channel posts are always sent as asked.
|
|
168
|
+
*
|
|
169
|
+
* @param sessionName - Posting agent session
|
|
170
|
+
* @param slackChannelId - Slack channel the caller named
|
|
171
|
+
* @param options - Cross-post flag, clock, and the Slack DM the origin
|
|
172
|
+
* conversation is bridged to (when the delivered message had no marker)
|
|
173
|
+
* @returns The decision
|
|
174
|
+
*/
|
|
175
|
+
resolveSlackReply(sessionName: string, slackChannelId: string, options?: ResolveOptions & {
|
|
176
|
+
originSlackChannelId?: string;
|
|
177
|
+
}): SlackReplyRouteDecision;
|
|
178
|
+
/**
|
|
179
|
+
* Plans where a Slack post by `sessionName` should go.
|
|
180
|
+
*
|
|
181
|
+
* When {@link resolveSlackReply} re-routes, the destination is the origin's
|
|
182
|
+
* own Slack conversation if the delivered message carried a `[SLACK:…]`
|
|
183
|
+
* marker (the master-bot bridge), else the origin chat-v2 conversation —
|
|
184
|
+
* which the Slack DM bridge mirrors into the agent-bot DM the owner wrote
|
|
185
|
+
* in, under the right bot.
|
|
186
|
+
*
|
|
187
|
+
* @param sessionName - Posting agent session
|
|
188
|
+
* @param target - Slack channel/thread the caller named, and its cross-post flag
|
|
189
|
+
* @param findDmSlackChannel - Maps a chat-v2 conversation to the Slack DM it
|
|
190
|
+
* is bridged to, when it is
|
|
191
|
+
* @param now - Clock override for tests
|
|
192
|
+
* @returns The plan and the decision behind it
|
|
193
|
+
*/
|
|
194
|
+
planSlackReply(sessionName: string, target: {
|
|
195
|
+
channelId: string;
|
|
196
|
+
threadTs?: string;
|
|
197
|
+
crossPost?: boolean;
|
|
198
|
+
}, findDmSlackChannel: (conversationId: string) => string | undefined, now?: number): {
|
|
199
|
+
plan: SlackReplyPlan;
|
|
200
|
+
decision: SlackReplyRouteDecision;
|
|
201
|
+
};
|
|
202
|
+
/**
|
|
203
|
+
* Whether an inbound map saw `key` within the recent-inbound window.
|
|
204
|
+
*
|
|
205
|
+
* @param seen - Inbound map
|
|
206
|
+
* @param key - Conversation or Slack channel id
|
|
207
|
+
* @param now - Epoch ms
|
|
208
|
+
* @returns True when recent
|
|
209
|
+
*/
|
|
210
|
+
private receivedRecently;
|
|
211
|
+
/**
|
|
212
|
+
* @param sessionName - Agent session
|
|
213
|
+
* @returns Its state, created on first use
|
|
214
|
+
*/
|
|
215
|
+
private stateFor;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=orc-reply-route.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orc-reply-route.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/orc/orc-reply-route.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,+CAA+C;AAC/C,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,cAAc,EAAE,MAAM,CAAC;IACvB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,oDAAoD;AACpD,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAE3D,yEAAyE;AACzE,MAAM,MAAM,gBAAgB;AAC1B,mCAAmC;AACjC,cAAc;AAChB,8DAA8D;GAC5D,qBAAqB;AACvB,2EAA2E;GACzE,oBAAoB;AACtB,8EAA8E;GAC5E,WAAW,CAAC;AAEhB,yCAAyC;AACzC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,gBAAgB,CAAC;IACzB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qBAAqB;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,+CAA+C;AAC/C,MAAM,WAAW,uBAAuB;IACtC,MAAM,EAAE,cAAc,GAAG,oBAAoB,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED,6CAA6C;AAC7C,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GACvD;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,cAAc,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD,6CAA6C;AAC7C,MAAM,WAAW,cAAc;IAC7B,oEAAoE;IACpE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,gCAAgC;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAYxE;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEzD;AAWD;;;GAGG;AACH,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAqC;IAE5D,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAwC;IAEjE;;OAEG;IACH,MAAM,CAAC,WAAW,IAAI,oBAAoB;IAK1C,yCAAyC;IACzC,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B;;;;;;;;;;OAUG;IACH,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,UAAU,GAAG,IAAI;IAW/F;;;;;OAKG;IACH,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IAI1D;;;;;;OAMG;IACH,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,UAAU,GAAG,SAAS;IAMrF;;;;;;;;;;;;;;;;OAgBG;IACH,wBAAwB,CACtB,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,OAAO,GAAE,cAAmB,GAC3B,kBAAkB;IA2BrB;;;;;;;;;;OAUG;IACH,iBAAiB,CACf,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,cAAc,GAAG;QAAE,oBAAoB,CAAC,EAAE,MAAM,CAAA;KAAO,GAC/D,uBAAuB;IAsB1B;;;;;;;;;;;;;;;OAeG;IACH,cAAc,CACZ,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,EACrE,kBAAkB,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAClE,GAAG,GAAE,MAAmB,GACvB;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,QAAQ,EAAE,uBAAuB,CAAA;KAAE;IAmB9D;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IAKxB;;;OAGG;IACH,OAAO,CAAC,QAAQ;CAQjB"}
|