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
package/config/constants.ts
CHANGED
|
@@ -1046,6 +1046,65 @@ export const VERSION_CHECK_CONSTANTS = {
|
|
|
1046
1046
|
REQUEST_TIMEOUT_MS: 5000,
|
|
1047
1047
|
} as const;
|
|
1048
1048
|
|
|
1049
|
+
// ========================= AUTO-UPDATE CONSTANTS =========================
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Automatic self-update (specs/auto-update.md).
|
|
1053
|
+
*
|
|
1054
|
+
* The backend's AutoUpdateService checks npm for a newer `crewly`, waits for
|
|
1055
|
+
* a quiet window, installs into the prefix the running copy lives in,
|
|
1056
|
+
* verifies the installed version and restarts gracefully. Shared with the
|
|
1057
|
+
* CLI (`crewly update-status`) and `crewly start` (which marks itself as the
|
|
1058
|
+
* restart supervisor for the backend it spawns).
|
|
1059
|
+
*/
|
|
1060
|
+
export const AUTO_UPDATE_CONSTANTS = {
|
|
1061
|
+
/** Interval between registry checks (ms) — 3 hours */
|
|
1062
|
+
CHECK_INTERVAL_MS: 3 * 60 * 60 * 1000,
|
|
1063
|
+
/** First check after boot (ms) — 10 minutes */
|
|
1064
|
+
FIRST_CHECK_DELAY_MS: 10 * 60 * 1000,
|
|
1065
|
+
/** A registry answer older than this is re-fetched for the auto-update decision (ms) */
|
|
1066
|
+
REGISTRY_MAX_AGE_MS: 30 * 60 * 1000,
|
|
1067
|
+
/** Gap between the two quiet-window probes (ms) */
|
|
1068
|
+
QUIET_CONFIRM_MS: 60 * 1000,
|
|
1069
|
+
/** Retry interval while agents are busy (ms) — 5 minutes */
|
|
1070
|
+
BUSY_RETRY_MS: 5 * 60 * 1000,
|
|
1071
|
+
/**
|
|
1072
|
+
* After deferring this long, an agent whose workingStatus is stuck at
|
|
1073
|
+
* in_progress no longer blocks the update; only turns actually in flight
|
|
1074
|
+
* do (the restart drain handles those anyway) (ms) — 24 hours
|
|
1075
|
+
*/
|
|
1076
|
+
MAX_BUSY_DEFER_MS: 24 * 60 * 60 * 1000,
|
|
1077
|
+
/** Back-off after a failed install or verify (ms) — 6 hours */
|
|
1078
|
+
FAILURE_BACKOFF_MS: 6 * 60 * 60 * 1000,
|
|
1079
|
+
/** Consecutive failures before the owner is told (once per target version) */
|
|
1080
|
+
FAILURE_NOTIFY_THRESHOLD: 2,
|
|
1081
|
+
/** Upper bound for one `npm install -g` (ms) — 10 minutes */
|
|
1082
|
+
INSTALL_TIMEOUT_MS: 10 * 60 * 1000,
|
|
1083
|
+
/** How long the post-restart notice waits for Slack to connect (ms) */
|
|
1084
|
+
NOTIFY_WAIT_MS: 10 * 60 * 1000,
|
|
1085
|
+
/** Poll interval while waiting for Slack (ms) */
|
|
1086
|
+
NOTIFY_POLL_MS: 15 * 1000,
|
|
1087
|
+
/** A pending-upgrade marker older than this is ignored at boot (ms) — 1 day */
|
|
1088
|
+
MARKER_MAX_AGE_MS: 24 * 60 * 60 * 1000,
|
|
1089
|
+
/** Env var: `0`/`false`/`off` forces auto-update off, `1`/`true`/`on` forces it on */
|
|
1090
|
+
ENV_VAR: 'CREWLY_AUTO_UPDATE',
|
|
1091
|
+
/**
|
|
1092
|
+
* Env var `crewly start` sets on the backend it spawns: the parent respawns
|
|
1093
|
+
* the backend when it exits with RESTART_REQUESTED, so an upgrade can come back.
|
|
1094
|
+
*/
|
|
1095
|
+
SUPERVISOR_ENV_VAR: 'CREWLY_RESTART_SUPERVISOR',
|
|
1096
|
+
/** Value of SUPERVISOR_ENV_VAR set by `crewly start` */
|
|
1097
|
+
SUPERVISOR_CLI_START: 'cli-start',
|
|
1098
|
+
/** Log file under `<crewlyHome>/logs/` */
|
|
1099
|
+
LOG_FILE: 'auto-update.log',
|
|
1100
|
+
/** Status file under CREWLY_HOME (read by `crewly update-status`) */
|
|
1101
|
+
STATE_FILE: 'auto-update-state.json',
|
|
1102
|
+
/** Marker written before an upgrade restart, read (and removed) on the next boot */
|
|
1103
|
+
MARKER_FILE: 'auto-update-pending.json',
|
|
1104
|
+
/** npm package name */
|
|
1105
|
+
PACKAGE_NAME: 'crewly',
|
|
1106
|
+
} as const;
|
|
1107
|
+
|
|
1049
1108
|
// ========================= MARKETPLACE CONSTANTS =========================
|
|
1050
1109
|
|
|
1051
1110
|
/**
|
package/config/index.ts
CHANGED
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
MEMORY_CONSTANTS,
|
|
34
34
|
CONTINUATION_CONSTANTS,
|
|
35
35
|
VERSION_CHECK_CONSTANTS,
|
|
36
|
+
AUTO_UPDATE_CONSTANTS,
|
|
36
37
|
MARKETPLACE_CONSTANTS,
|
|
37
38
|
TEMPLATE_MARKETPLACE_CONSTANTS,
|
|
38
39
|
PROCESS_EXIT_CODES,
|
|
@@ -63,6 +64,7 @@ export {
|
|
|
63
64
|
MEMORY_CONSTANTS,
|
|
64
65
|
CONTINUATION_CONSTANTS,
|
|
65
66
|
VERSION_CHECK_CONSTANTS,
|
|
67
|
+
AUTO_UPDATE_CONSTANTS,
|
|
66
68
|
MARKETPLACE_CONSTANTS,
|
|
67
69
|
TEMPLATE_MARKETPLACE_CONSTANTS,
|
|
68
70
|
PROCESS_EXIT_CODES,
|
|
@@ -1032,6 +1032,15 @@ Full-scope Google OAuth (Gmail read/write + Drive + Calendar + Photos + Docs tog
|
|
|
1032
1032
|
**Capability awareness (meta-rule):**
|
|
1033
1033
|
When teams ship new capabilities (new UI flows, new skills, new credential types), you need to be told explicitly. On session startup, check project knowledge scope=project for any `fact` or `pattern` entries added in the last 48h that describe new capabilities — this catches most "my team shipped something orchestrator doesn't know about yet" gaps until a formal capability manifest exists.
|
|
1034
1034
|
|
|
1035
|
+
### Harness Login (Claude Code / Codex) — use `harness-login`, never bash (MANDATORY)
|
|
1036
|
+
|
|
1037
|
+
When the owner asks to log Claude Code or Codex in again, switch its account, or send them a login link ("帮我重新登陆 claude code", "换个账号", "给我登录链接"):
|
|
1038
|
+
|
|
1039
|
+
- Run `bash config/skills/orchestrator/harness-login/execute.sh --harness claude` (or `codex`; add `--switch-account` for a different account). Crewly keeps the login alive in its own terminal, sends the owner the link in the thread they asked in, types the code they paste back into the login, and tells them itself when it worked.
|
|
1040
|
+
- **Never** run `claude setup-token`, `claude /login`, `claude auth login`, `codex login` or an `agy` login in bash. The process dies when your tool call returns, so every code the owner pastes goes stale (2026-09-26: the owner pasted two codes into a dead login). The bash tool refuses these commands.
|
|
1041
|
+
- After the skill succeeds, **say nothing more about the login** — no link, no "I've sent it", no status report. Never claim you sent something unless a reply tool actually sent it in this turn.
|
|
1042
|
+
- The owner can also type 「重新登录 claude」 / 「换个账号登录 codex」 / `relogin claude` in your DM; Crewly handles that without you.
|
|
1043
|
+
|
|
1035
1044
|
### Team Management
|
|
1036
1045
|
|
|
1037
1046
|
- Create and configure agent teams
|
|
@@ -99,6 +99,17 @@ fi
|
|
|
99
99
|
require_param "to (--to)" "$TO"
|
|
100
100
|
require_param "task (--task)" "$TASK"
|
|
101
101
|
|
|
102
|
+
# A WorkItem brief quotes its Request as "[Request <uuid> | WorkItem <uuid>]".
|
|
103
|
+
# When the delegator pastes that brief without --request-id, link the new
|
|
104
|
+
# WorkItem to that Request anyway; otherwise the Request's completion check
|
|
105
|
+
# cannot see the work (2026-09-26: WI 806dc528 carried Request d86b5faf only
|
|
106
|
+
# in its title and the Request closed while it was still running).
|
|
107
|
+
if [ -z "$REQUEST_ID" ]; then
|
|
108
|
+
REQUEST_ID=$(printf '%s\n%s' "$TASK" "$CONTEXT" \
|
|
109
|
+
| grep -oE '\[Request [0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}' \
|
|
110
|
+
| head -1 | sed 's/^\[Request //' || true)
|
|
111
|
+
fi
|
|
112
|
+
|
|
102
113
|
# Request Contract check (P0-3): non-fatal warning when the delegated brief
|
|
103
114
|
# is missing Goal / Expected Outcome / Eval Criteria markers. TLs and workers
|
|
104
115
|
# downstream are entitled to push back per the Brief Reception Protocol when
|
|
@@ -348,6 +348,44 @@ else
|
|
|
348
348
|
PASS=$((PASS + 1))
|
|
349
349
|
fi
|
|
350
350
|
|
|
351
|
+
# --- Test 8: a brief that quotes "[Request <uuid> | WorkItem …]" links the new
|
|
352
|
+
# WorkItem to that Request even without --request-id (2026-09-26, WI 806dc528
|
|
353
|
+
# carried Request d86b5faf only in its title; the Request then closed early).
|
|
354
|
+
REQ_ID="d86b5faf-4693-4941-aa9b-7216ffb90005"
|
|
355
|
+
> "$CALL_LOG"
|
|
356
|
+
OUT=$(CALL_LOG="$CALL_LOG" CREWLY_ROOT=/tmp/crewly-test \
|
|
357
|
+
bash "${SKILL_PARENT}/delegate-task/execute.sh" \
|
|
358
|
+
--to crewly-test-bob \
|
|
359
|
+
--task "[Request ${REQ_ID} | WorkItem 8249a788-1ea7-4687-ac1a-47d078a34afe] GOAL: plan it" \
|
|
360
|
+
2>&1 || true)
|
|
361
|
+
assert_log_contains "requestId parsed from the quoted brief" "\"requestId\": \"${REQ_ID}\""
|
|
362
|
+
|
|
363
|
+
# 8b: an explicit --request-id wins over the quoted one
|
|
364
|
+
> "$CALL_LOG"
|
|
365
|
+
OUT=$(CALL_LOG="$CALL_LOG" CREWLY_ROOT=/tmp/crewly-test \
|
|
366
|
+
bash "${SKILL_PARENT}/delegate-task/execute.sh" \
|
|
367
|
+
--to crewly-test-bob \
|
|
368
|
+
--request-id explicit-req \
|
|
369
|
+
--task "[Request ${REQ_ID} | WorkItem x] GOAL: plan it" \
|
|
370
|
+
2>&1 || true)
|
|
371
|
+
assert_log_contains "explicit --request-id is kept" '"requestId": "explicit-req"'
|
|
372
|
+
|
|
373
|
+
# 8c: no quoted Request and no flag → no requestId, and the skill still runs
|
|
374
|
+
> "$CALL_LOG"
|
|
375
|
+
OUT=$(CALL_LOG="$CALL_LOG" CREWLY_ROOT=/tmp/crewly-test \
|
|
376
|
+
bash "${SKILL_PARENT}/delegate-task/execute.sh" \
|
|
377
|
+
--to crewly-test-bob \
|
|
378
|
+
--task "plain task" \
|
|
379
|
+
2>&1 || true)
|
|
380
|
+
if grep -q '"requestId"' "$CALL_LOG"; then
|
|
381
|
+
echo " FAIL: requestId set without a quoted Request"
|
|
382
|
+
FAIL=$((FAIL + 1))
|
|
383
|
+
else
|
|
384
|
+
echo " PASS: no requestId without a quoted Request"
|
|
385
|
+
PASS=$((PASS + 1))
|
|
386
|
+
fi
|
|
387
|
+
assert_log_contains "add still fires without a quoted Request" "POST /task-pool/add"
|
|
388
|
+
|
|
351
389
|
# --- Summary ---
|
|
352
390
|
echo ""
|
|
353
391
|
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Harness Login
|
|
3
|
+
description: "Log a coding harness (Claude Code, Codex) in, or switch its account, when the owner asks. Crewly keeps the login alive in its own terminal, DMs the owner the link in the thread they asked in, types the code they paste back into the login, and reports success itself. Never run claude setup-token / claude /login / codex login in bash."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: management
|
|
6
|
+
skillType: claude-skill
|
|
7
|
+
assignableRoles:
|
|
8
|
+
- orchestrator
|
|
9
|
+
triggers:
|
|
10
|
+
- relogin claude
|
|
11
|
+
- login claude
|
|
12
|
+
- login codex
|
|
13
|
+
- switch claude account
|
|
14
|
+
- claude login link
|
|
15
|
+
- 重新登录
|
|
16
|
+
- 登录 claude
|
|
17
|
+
- 换个账号登录
|
|
18
|
+
- 登录链接
|
|
19
|
+
tags:
|
|
20
|
+
- harness
|
|
21
|
+
- login
|
|
22
|
+
- claude
|
|
23
|
+
- codex
|
|
24
|
+
- account
|
|
25
|
+
execution:
|
|
26
|
+
type: script
|
|
27
|
+
script:
|
|
28
|
+
file: execute.sh
|
|
29
|
+
interpreter: bash
|
|
30
|
+
timeoutMs: 30000
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
# Harness Login
|
|
34
|
+
|
|
35
|
+
The owner asks you to log Claude Code or Codex in again, or to use a different
|
|
36
|
+
account ("帮我重新登陆 claude code", "换个账号", "send me the login link").
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bash config/skills/orchestrator/harness-login/execute.sh --harness claude
|
|
40
|
+
bash config/skills/orchestrator/harness-login/execute.sh --harness codex --switch-account
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## What happens
|
|
44
|
+
|
|
45
|
+
1. Crewly starts the harness's own login command in a terminal it keeps alive
|
|
46
|
+
(`claude setup-token` for Claude, `codex login --device-auth` for Codex) —
|
|
47
|
+
even when the harness is still logged in, because the owner asked.
|
|
48
|
+
2. The owner gets the link (and Codex's one-time code) in Slack, in the thread
|
|
49
|
+
they asked in.
|
|
50
|
+
3. Claude: the owner pastes the code shown after authorizing straight back into
|
|
51
|
+
that thread. Crewly types it into the login. Codex needs nothing pasted.
|
|
52
|
+
4. Crewly tells the owner in one line when it worked (and restarts the agents
|
|
53
|
+
on that harness so they use the new login), or when it failed.
|
|
54
|
+
|
|
55
|
+
The skill returns at once:
|
|
56
|
+
|
|
57
|
+
```json
|
|
58
|
+
{"success":true,"status":"started","harnessId":"claude-code","displayName":"Claude Code","dmAvailable":true,"next":"…"}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**After that, say nothing more about this login.** Do not repeat the link, do
|
|
62
|
+
not say "I've sent it", do not write a status report. The flow speaks for
|
|
63
|
+
itself. If `dmAvailable` is false, follow `next` (Slack is down: tell the owner
|
|
64
|
+
in one line to finish it in Setup).
|
|
65
|
+
|
|
66
|
+
## Rules
|
|
67
|
+
|
|
68
|
+
- **Never** run `claude setup-token`, `claude /login`, `claude auth login`,
|
|
69
|
+
`codex login` or an Antigravity (`agy`) login in bash. The process dies when
|
|
70
|
+
the tool call returns, so every code the owner pastes is stale (2026-09-26).
|
|
71
|
+
The bash tool refuses these commands.
|
|
72
|
+
- Only when the owner asked. The backend checks that an owner message from the
|
|
73
|
+
last 30 minutes asks for this login; otherwise it answers
|
|
74
|
+
`owner_request_not_found`. Do not start logins on your own.
|
|
75
|
+
- `antigravity` answers `no_link_login` (it uses a Gemini API key, entered in
|
|
76
|
+
Setup); Gemini CLI is enterprise-only. Pass the message on in one line.
|
|
77
|
+
- The owner can also just write 「重新登录 claude」 / 「换个账号登录 codex」 /
|
|
78
|
+
`relogin claude` in your DM — Crewly handles that without you.
|
|
79
|
+
|
|
80
|
+
## Errors
|
|
81
|
+
|
|
82
|
+
| reason | meaning |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `orchestrator_only` | Only the orchestrator may call this |
|
|
85
|
+
| `owner_request_not_found` | No recent owner message asks for this login |
|
|
86
|
+
| `owner_request_unverifiable` | The owner's chat history could not be read |
|
|
87
|
+
| `unknown_harness` | Use claude, codex or antigravity |
|
|
88
|
+
| `no_link_login` | The harness has no link login (Antigravity, Gemini) |
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# =============================================================================
|
|
3
|
+
# harness-login — start the harness login (or account switch) the owner asked
|
|
4
|
+
# for: Claude Code, Codex. Backed by POST /api/harness/<id>/owner-login.
|
|
5
|
+
#
|
|
6
|
+
# Crewly runs the login in its own terminal and keeps it alive, DMs the owner
|
|
7
|
+
# the link (and Codex's code) in the thread they asked in, types the code they
|
|
8
|
+
# paste back into the login, and tells them itself when it worked or failed.
|
|
9
|
+
# This returns at once. After it succeeds, say NOTHING more about the login —
|
|
10
|
+
# no link, no "I've sent it", no status report.
|
|
11
|
+
#
|
|
12
|
+
# NEVER run `claude setup-token`, `claude /login`, `claude auth login`,
|
|
13
|
+
# `codex login` or an agy login in bash: that process dies when the tool call
|
|
14
|
+
# returns, so every code the owner pastes goes stale.
|
|
15
|
+
#
|
|
16
|
+
# Only works when the owner asked for the login in the last 30 minutes (their
|
|
17
|
+
# message is checked). Orchestrator only.
|
|
18
|
+
#
|
|
19
|
+
# Usage:
|
|
20
|
+
# bash execute.sh --harness claude
|
|
21
|
+
# bash execute.sh --harness codex --switch-account
|
|
22
|
+
# bash execute.sh '{"harness":"claude","switchAccount":true}'
|
|
23
|
+
# =============================================================================
|
|
24
|
+
set -euo pipefail
|
|
25
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
26
|
+
source "${SCRIPT_DIR}/../_common/lib.sh"
|
|
27
|
+
|
|
28
|
+
print_usage() {
|
|
29
|
+
cat <<'EOF_USAGE'
|
|
30
|
+
Usage:
|
|
31
|
+
bash execute.sh --harness <claude|codex|antigravity> [--switch-account]
|
|
32
|
+
bash execute.sh '{"harness":"claude","switchAccount":false}'
|
|
33
|
+
|
|
34
|
+
Options:
|
|
35
|
+
--harness claude (Claude Code), codex (Codex CLI) or antigravity (agy) — required
|
|
36
|
+
--switch-account The owner wants a different account (changes the wording of the DM)
|
|
37
|
+
--help | -h Show this help
|
|
38
|
+
EOF_USAGE
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
INPUT_JSON=""; HARNESS=""; SWITCH=false
|
|
42
|
+
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then INPUT_JSON="$1"; shift || true; fi
|
|
43
|
+
while [[ $# -gt 0 ]]; do
|
|
44
|
+
case "$1" in
|
|
45
|
+
--harness) [ $# -ge 2 ] || error_exit "--harness requires a value"; HARNESS="$2"; shift 2 ;;
|
|
46
|
+
--switch-account) SWITCH=true; shift ;;
|
|
47
|
+
--help|-h) print_usage; exit 0 ;;
|
|
48
|
+
*) error_exit "Unknown option: $1" ;;
|
|
49
|
+
esac
|
|
50
|
+
done
|
|
51
|
+
if [ -n "$INPUT_JSON" ]; then
|
|
52
|
+
INPUT=$(read_json_input "$INPUT_JSON")
|
|
53
|
+
[ -z "$HARNESS" ] && HARNESS=$(printf '%s' "$INPUT" | jq -r '.harness // .harnessId // empty')
|
|
54
|
+
[ "$(printf '%s' "$INPUT" | jq -r '.switchAccount // false')" = "true" ] && SWITCH=true
|
|
55
|
+
fi
|
|
56
|
+
require_param "harness (--harness)" "$HARNESS"
|
|
57
|
+
|
|
58
|
+
# "Claude Code" → "claude-code"; anything else than [a-z0-9-] never reaches the URL.
|
|
59
|
+
HARNESS_ID=$(printf '%s' "$HARNESS" | tr '[:upper:]' '[:lower:]' | sed -E 's/[[:space:]_]+/-/g')
|
|
60
|
+
[[ "$HARNESS_ID" =~ ^[a-z0-9-]+$ ]] || error_exit "Invalid harness: $HARNESS (use claude, codex or antigravity)"
|
|
61
|
+
|
|
62
|
+
BODY=$(jq -cn --argjson sw "$SWITCH" '{switchAccount: $sw}')
|
|
63
|
+
|
|
64
|
+
ERR_FILE=$(mktemp); trap 'rm -f "$ERR_FILE"' EXIT
|
|
65
|
+
RESPONSE=$(api_call POST "/harness/${HARNESS_ID}/owner-login" "$BODY" 2>"$ERR_FILE") || {
|
|
66
|
+
ERR=$(tail -n 1 "$ERR_FILE")
|
|
67
|
+
printf '%s' "$ERR" | jq -c '{success: false,
|
|
68
|
+
reason: (.details.code // "login_not_started"),
|
|
69
|
+
error: (.details.error // .error // "login not started")}
|
|
70
|
+
+ (if .details.next then {next: .details.next} else {} end)' 2>/dev/null \
|
|
71
|
+
|| jq -cn --arg e "$ERR" '{success: false, reason: "login_not_started", error: $e}'
|
|
72
|
+
exit 1
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
printf '%s' "$RESPONSE" | jq -c '.data | {success: true} + .'
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Tests for harness-login — run with: bash execute.test.sh </dev/null
|
|
3
|
+
# A python HTTP stub plays the backend; asserts the route, the body, the
|
|
4
|
+
# orchestrator header and how refusals are reported.
|
|
5
|
+
set -u
|
|
6
|
+
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
EXEC="$HERE/execute.sh"
|
|
8
|
+
PASS=0; FAIL=0
|
|
9
|
+
check() {
|
|
10
|
+
local name="$1"; local got="$2"; local want="$3"
|
|
11
|
+
if [ "$got" = "$want" ]; then PASS=$((PASS+1)); else FAIL=$((FAIL+1)); echo "FAIL: $name"; echo " want: $want"; echo " got: $got"; fi
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
PORT=18853
|
|
15
|
+
STUB_LOG="$(mktemp)"; export STUB_LOG; export STUB_PORT="$PORT"
|
|
16
|
+
python3 -u <<'PY' >/dev/null 2>&1 &
|
|
17
|
+
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
18
|
+
import json, os
|
|
19
|
+
LOG = os.environ['STUB_LOG']; PORT = int(os.environ['STUB_PORT'])
|
|
20
|
+
class H(BaseHTTPRequestHandler):
|
|
21
|
+
def reply(self, code, body):
|
|
22
|
+
self.send_response(code); self.send_header('Content-Type', 'application/json'); self.end_headers()
|
|
23
|
+
self.wfile.write(json.dumps(body).encode())
|
|
24
|
+
def do_POST(self):
|
|
25
|
+
body = json.loads(self.rfile.read(int(self.headers.get('Content-Length', 0))) or b'{}')
|
|
26
|
+
open(LOG, 'w').write(json.dumps({'path': self.path, 'body': body, 'agent': self.headers.get('X-Agent-Session')}))
|
|
27
|
+
if self.headers.get('X-Agent-Session') != 'crewly-orc':
|
|
28
|
+
return self.reply(403, {'success': False, 'code': 'orchestrator_only', 'error': 'Only the orchestrator can start a harness login for the owner. Ask the orchestrator.'})
|
|
29
|
+
if self.path.startswith('/api/harness/codex/'):
|
|
30
|
+
return self.reply(403, {'success': False, 'code': 'owner_request_not_found', 'error': 'No owner message in the last 30 min asks to log Codex in.'})
|
|
31
|
+
if self.path.startswith('/api/harness/antigravity/'):
|
|
32
|
+
return self.reply(400, {'success': False, 'code': 'no_link_login', 'error': 'Antigravity CLI 用的是 Gemini API key', 'next': 'Tell the owner this in one short line, in their language.'})
|
|
33
|
+
self.reply(202, {'success': True, 'data': {'status': 'started', 'harnessId': 'claude-code', 'displayName': 'Claude Code', 'dmAvailable': True, 'next': 'Say nothing more about this login'}})
|
|
34
|
+
def log_message(self, *a, **k): pass
|
|
35
|
+
HTTPServer(('127.0.0.1', PORT), H).serve_forever()
|
|
36
|
+
PY
|
|
37
|
+
STUB_PID=$!
|
|
38
|
+
disown "$STUB_PID" 2>/dev/null || true
|
|
39
|
+
trap 'kill "$STUB_PID" >/dev/null 2>&1; rm -f "$STUB_LOG"' EXIT
|
|
40
|
+
for i in $(seq 1 30); do curl -s -o /dev/null -m 0.2 "http://127.0.0.1:${PORT}/" 2>/dev/null && break; sleep 0.1; done
|
|
41
|
+
|
|
42
|
+
run() { CREWLY_SESSION_NAME="${AS:-crewly-orc}" CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" "$@" 2>/dev/null; }
|
|
43
|
+
run_err() { CREWLY_SESSION_NAME=crewly-orc CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" "$@" 2>&1 >/dev/null | jq -rs 'last.error' 2>/dev/null; }
|
|
44
|
+
|
|
45
|
+
OUT=$(run --harness claude)
|
|
46
|
+
check "route" "$(jq -r .path "$STUB_LOG")" "/api/harness/claude/owner-login"
|
|
47
|
+
check "body" "$(jq -c .body "$STUB_LOG")" '{"switchAccount":false}'
|
|
48
|
+
check "orchestrator header" "$(jq -r .agent "$STUB_LOG")" "crewly-orc"
|
|
49
|
+
check "returns at once with the next step" "$(printf '%s' "$OUT" | jq -c '{success, status, harnessId, dmAvailable}')" '{"success":true,"status":"started","harnessId":"claude-code","dmAvailable":true}'
|
|
50
|
+
|
|
51
|
+
OUT=$(run --harness "Claude Code" --switch-account)
|
|
52
|
+
check "display name → id, switch flag" "$(jq -c '{path, body}' "$STUB_LOG")" '{"path":"/api/harness/claude-code/owner-login","body":{"switchAccount":true}}'
|
|
53
|
+
|
|
54
|
+
OUT=$(run '{"harness":"claude","switchAccount":true}')
|
|
55
|
+
check "json input" "$(jq -c .body "$STUB_LOG")" '{"switchAccount":true}'
|
|
56
|
+
|
|
57
|
+
OUT=$(run --harness codex); RC=$?
|
|
58
|
+
check "no owner request: exit 1" "$RC" "1"
|
|
59
|
+
check "no owner request: reason" "$(printf '%s' "$OUT" | jq -r .reason)" "owner_request_not_found"
|
|
60
|
+
|
|
61
|
+
OUT=$(run --harness antigravity); RC=$?
|
|
62
|
+
check "no link login: reason and next" "$(printf '%s' "$OUT" | jq -c '{reason, next}')" '{"reason":"no_link_login","next":"Tell the owner this in one short line, in their language."}'
|
|
63
|
+
|
|
64
|
+
OUT=$(AS=dev-team-joe run --harness claude)
|
|
65
|
+
check "other agents refused" "$(printf '%s' "$OUT" | jq -r .reason)" "orchestrator_only"
|
|
66
|
+
|
|
67
|
+
check "missing harness" "$(run_err)" "Missing required parameter: harness (--harness)"
|
|
68
|
+
check "path injection refused" "$(run_err --harness '../orc')" "Invalid harness: ../orc (use claude, codex or antigravity)"
|
|
69
|
+
check "unknown option" "$(run_err --yes)" "Unknown option: --yes"
|
|
70
|
+
|
|
71
|
+
echo "=== Results: $PASS passed, $FAIL failed ==="
|
|
72
|
+
[ "$FAIL" -eq 0 ]
|
|
@@ -69,10 +69,20 @@ bash config/skills/orchestrator/reply-chat/execute.sh '{"conversationId":"conv-a
|
|
|
69
69
|
|
|
70
70
|
| Flag | Short | Description |
|
|
71
71
|
|------|-------|-------------|
|
|
72
|
-
| `--conversation` | `-C` | Chat conversation ID (
|
|
72
|
+
| `--conversation` | `-C` | Chat conversation ID. Omitted → the conversation your current turn came from (the `[CHAT:<id>]` of the last user message you received) |
|
|
73
73
|
| `--text` | `-t` | Message text |
|
|
74
74
|
| `--text-file` | | Read message text from file |
|
|
75
75
|
| `--sender` | `-s` | Sender name (default: "Orchestrator") |
|
|
76
76
|
| `--sender-type` | | Sender type: orchestrator, agent, system (default: orchestrator) |
|
|
77
|
+
| `--cross-post` | | Deliberately post to a conversation other than the one your turn came from (you were asked to post there) |
|
|
77
78
|
| `--json` | `-j` | Raw JSON payload |
|
|
78
79
|
| `--help` | `-h` | Show help |
|
|
80
|
+
|
|
81
|
+
## Where your reply goes
|
|
82
|
+
|
|
83
|
+
Your reply belongs in the conversation the user wrote to you from. While the
|
|
84
|
+
last user message you received is under 15 minutes old, a reply to a
|
|
85
|
+
conversation nobody has written to you from in the last 30 minutes is sent to
|
|
86
|
+
the conversation that message came from instead, and a warning is logged. This
|
|
87
|
+
also covers system turns (WorkItem dispatch, reminders) that follow a user's
|
|
88
|
+
message. Pass `--cross-post` only when you were asked to post somewhere else.
|
|
@@ -22,6 +22,11 @@ Options:
|
|
|
22
22
|
--text-file Read message text from the specified file path
|
|
23
23
|
--sender | -s Sender name (default: Orchestrator)
|
|
24
24
|
--sender-type Sender type: orchestrator, agent, system (default: orchestrator)
|
|
25
|
+
--cross-post Deliberately post in a conversation other than the one
|
|
26
|
+
your current turn came from (e.g. the owner asked you to
|
|
27
|
+
post there). Without it, an orchestrator reply aimed at a
|
|
28
|
+
conversation nobody wrote to you from recently is sent
|
|
29
|
+
back to the conversation the turn came from.
|
|
25
30
|
--json | -j Raw JSON payload
|
|
26
31
|
--help | -h Show this help
|
|
27
32
|
EOF_USAGE
|
|
@@ -32,6 +37,7 @@ CONVERSATION_ID=""
|
|
|
32
37
|
TEXT=""
|
|
33
38
|
SENDER_NAME="Orchestrator"
|
|
34
39
|
SENDER_TYPE="orchestrator"
|
|
40
|
+
CROSS_POST="false"
|
|
35
41
|
|
|
36
42
|
# Detect legacy JSON argument as the first parameter
|
|
37
43
|
if [[ $# -gt 0 && ${1:0:1} == '{' ]]; then
|
|
@@ -61,6 +67,10 @@ while [[ $# -gt 0 ]]; do
|
|
|
61
67
|
SENDER_TYPE="$2"
|
|
62
68
|
shift 2
|
|
63
69
|
;;
|
|
70
|
+
--cross-post)
|
|
71
|
+
CROSS_POST="true"
|
|
72
|
+
shift
|
|
73
|
+
;;
|
|
64
74
|
--json|-j)
|
|
65
75
|
INPUT_JSON="$2"
|
|
66
76
|
shift 2
|
|
@@ -117,7 +127,9 @@ BODY=$(jq -n \
|
|
|
117
127
|
--arg senderName "$SENDER_NAME" \
|
|
118
128
|
--arg senderType "$SENDER_TYPE" \
|
|
119
129
|
--arg conversationId "$CONVERSATION_ID" \
|
|
130
|
+
--argjson crossPost "$CROSS_POST" \
|
|
120
131
|
'{content: $content, senderName: $senderName, senderType: $senderType} +
|
|
121
|
-
(if $conversationId != "" then {conversationId: $conversationId} else {} end)
|
|
132
|
+
(if $conversationId != "" then {conversationId: $conversationId} else {} end) +
|
|
133
|
+
(if $crossPost then {crossPost: true} else {} end)')
|
|
122
134
|
|
|
123
135
|
api_call POST "/chat/agent-response" "$BODY"
|
|
@@ -56,6 +56,7 @@ bash config/skills/orchestrator/reply-slack/execute.sh '{"channelId":"C0123","te
|
|
|
56
56
|
| `--image` / `-i` | No | Path to an image file to upload to Slack. When provided, calls `/api/slack/upload-image` instead of `/api/slack/send`. The `--text` becomes an optional comment on the image |
|
|
57
57
|
| `--file` / `-f` | No | Path to any file type (PDF/CSV/ZIP/etc.) to upload via `/api/slack/upload-file`. The `--text` becomes an optional comment |
|
|
58
58
|
| `--allow-new-thread` | No | Explicitly allow posting without a thread (safety override) |
|
|
59
|
+
| `--cross-post` | No | Deliberately post to a Slack DM other than the one your turn came from. Without it, a DM post (`D…`) nobody wrote to you from recently is sent back to the conversation your turn came from. Channel posts are never re-routed |
|
|
59
60
|
| `conversationId` / `--conversation` | No | Conversation ID from the `[CHAT:...]` prefix so the queue can resolve instantly (falls back to the active conversation if omitted) |
|
|
60
61
|
|
|
61
62
|
## Image Upload
|
|
@@ -27,12 +27,17 @@ Options:
|
|
|
27
27
|
--image | -i Path to image file to upload (uses /api/slack/upload-image)
|
|
28
28
|
--file | -f Path to file upload (uses /api/slack/upload-file)
|
|
29
29
|
--allow-new-thread Allow posting without --thread (disabled by default for safety)
|
|
30
|
+
--cross-post Deliberately post to a Slack DM other than the one your
|
|
31
|
+
current turn came from. Without it, a DM post nobody wrote
|
|
32
|
+
to you from recently is sent back where the turn came from.
|
|
33
|
+
(Channel posts are never re-routed.)
|
|
30
34
|
--json | -j Raw JSON payload (same as legacy usage)
|
|
31
35
|
--help | -h Show this help
|
|
32
36
|
EOF_USAGE
|
|
33
37
|
}
|
|
34
38
|
|
|
35
39
|
INPUT_JSON=""
|
|
40
|
+
CROSS_POST="false"
|
|
36
41
|
CHANNEL_ID=""
|
|
37
42
|
TEXT=""
|
|
38
43
|
THREAD_TS=""
|
|
@@ -78,6 +83,10 @@ while [[ $# -gt 0 ]]; do
|
|
|
78
83
|
ALLOW_NEW_THREAD="true"
|
|
79
84
|
shift
|
|
80
85
|
;;
|
|
86
|
+
--cross-post)
|
|
87
|
+
CROSS_POST="true"
|
|
88
|
+
shift
|
|
89
|
+
;;
|
|
81
90
|
--conversation|-C)
|
|
82
91
|
CONVERSATION_ID="$2"
|
|
83
92
|
shift 2
|
|
@@ -200,10 +209,10 @@ else
|
|
|
200
209
|
export _SLACK_TEXT="$TEXT"
|
|
201
210
|
if [ -n "$THREAD_TS" ]; then
|
|
202
211
|
export _SLACK_THREAD="$THREAD_TS"
|
|
203
|
-
BODY=$(jq -n '{channelId: env._SLACK_CHANNEL, text: env._SLACK_TEXT, threadTs: env._SLACK_THREAD}')
|
|
212
|
+
BODY=$(jq -n --argjson crossPost "$CROSS_POST" '{channelId: env._SLACK_CHANNEL, text: env._SLACK_TEXT, threadTs: env._SLACK_THREAD} + (if $crossPost then {crossPost: true} else {} end)')
|
|
204
213
|
unset _SLACK_THREAD
|
|
205
214
|
else
|
|
206
|
-
BODY=$(jq -n '{channelId: env._SLACK_CHANNEL, text: env._SLACK_TEXT}')
|
|
215
|
+
BODY=$(jq -n --argjson crossPost "$CROSS_POST" '{channelId: env._SLACK_CHANNEL, text: env._SLACK_TEXT} + (if $crossPost then {crossPost: true} else {} end)')
|
|
207
216
|
fi
|
|
208
217
|
unset _SLACK_CHANNEL _SLACK_TEXT
|
|
209
218
|
|
|
@@ -216,6 +216,27 @@ export declare const VERSION_CHECK_CONSTANTS: {
|
|
|
216
216
|
readonly CACHE_TTL_MS: number;
|
|
217
217
|
readonly REQUEST_TIMEOUT_MS: 5000;
|
|
218
218
|
};
|
|
219
|
+
export declare const AUTO_UPDATE_CONSTANTS: {
|
|
220
|
+
readonly CHECK_INTERVAL_MS: number;
|
|
221
|
+
readonly FIRST_CHECK_DELAY_MS: number;
|
|
222
|
+
readonly REGISTRY_MAX_AGE_MS: number;
|
|
223
|
+
readonly QUIET_CONFIRM_MS: number;
|
|
224
|
+
readonly BUSY_RETRY_MS: number;
|
|
225
|
+
readonly MAX_BUSY_DEFER_MS: number;
|
|
226
|
+
readonly FAILURE_BACKOFF_MS: number;
|
|
227
|
+
readonly FAILURE_NOTIFY_THRESHOLD: 2;
|
|
228
|
+
readonly INSTALL_TIMEOUT_MS: number;
|
|
229
|
+
readonly NOTIFY_WAIT_MS: number;
|
|
230
|
+
readonly NOTIFY_POLL_MS: number;
|
|
231
|
+
readonly MARKER_MAX_AGE_MS: number;
|
|
232
|
+
readonly ENV_VAR: "CREWLY_AUTO_UPDATE";
|
|
233
|
+
readonly SUPERVISOR_ENV_VAR: "CREWLY_RESTART_SUPERVISOR";
|
|
234
|
+
readonly SUPERVISOR_CLI_START: "cli-start";
|
|
235
|
+
readonly LOG_FILE: "auto-update.log";
|
|
236
|
+
readonly STATE_FILE: "auto-update-state.json";
|
|
237
|
+
readonly MARKER_FILE: "auto-update-pending.json";
|
|
238
|
+
readonly PACKAGE_NAME: "crewly";
|
|
239
|
+
};
|
|
219
240
|
export declare const AGENT_HEARTBEAT_MONITOR_CONSTANTS: {
|
|
220
241
|
readonly CHECK_INTERVAL_MS: 30000;
|
|
221
242
|
readonly HEARTBEAT_REQUEST_THRESHOLD_MS: 300000;
|
|
@@ -629,6 +650,28 @@ export declare const TERMINAL_GATEWAY_CONSTANTS: {
|
|
|
629
650
|
*/
|
|
630
651
|
readonly MONITORING_RETRY_BACKOFFS_MS: readonly number[];
|
|
631
652
|
};
|
|
653
|
+
/**
|
|
654
|
+
* Orchestrator reply routing (2026-09-26 incident: the owner asked the orc a
|
|
655
|
+
* question in a Slack DM, and its answer landed in #pro-think-tank).
|
|
656
|
+
* See `services/orc/orc-reply-route.service.ts`.
|
|
657
|
+
*/
|
|
658
|
+
export declare const ORC_REPLY_ROUTE_CONSTANTS: {
|
|
659
|
+
/**
|
|
660
|
+
* How long after the last user message the orchestrator received its
|
|
661
|
+
* conversation stays "the one its turn came from". Covers a long turn and
|
|
662
|
+
* the system-triggered turns (WorkItem dispatch, reminders) that follow it.
|
|
663
|
+
*/
|
|
664
|
+
readonly ORIGIN_TTL_MS: number;
|
|
665
|
+
/**
|
|
666
|
+
* A conversation the orchestrator received a user message from within this
|
|
667
|
+
* window is one it is actively in; replies there are never re-routed.
|
|
668
|
+
*/
|
|
669
|
+
readonly RECENT_INBOUND_MS: number;
|
|
670
|
+
/** Cap on remembered inbound conversations per session (oldest dropped). */
|
|
671
|
+
readonly MAX_TRACKED_CONVERSATIONS: 50;
|
|
672
|
+
/** Slack channel-id prefix of a direct-message conversation. */
|
|
673
|
+
readonly SLACK_DM_PREFIX: "D";
|
|
674
|
+
};
|
|
632
675
|
export declare const CHAT_ROUTING_CONSTANTS: {
|
|
633
676
|
/** Message format prefix for chat routing */
|
|
634
677
|
readonly MESSAGE_PREFIX: "CHAT";
|
|
@@ -3145,6 +3188,18 @@ export declare const HARNESS_CONSTANTS: {
|
|
|
3145
3188
|
/** Waiting agents named in a DM; the rest are counted */
|
|
3146
3189
|
readonly DM_MAX_LISTED_AGENTS: 8;
|
|
3147
3190
|
};
|
|
3191
|
+
/**
|
|
3192
|
+
* Owner-requested logins (「重新登录 claude」 in the orc DM, or the orc's
|
|
3193
|
+
* `harness-login` skill). specs/onboarding-harness-login.md "Owner-triggered login".
|
|
3194
|
+
*/
|
|
3195
|
+
readonly OWNER_LOGIN: {
|
|
3196
|
+
/** Longest DM (normalised) the deterministic trigger considers; longer text goes to the orc */
|
|
3197
|
+
readonly MAX_TRIGGER_LENGTH: 60;
|
|
3198
|
+
/** How far back an owner message may ask for the login the orc's skill starts */
|
|
3199
|
+
readonly EVIDENCE_LOOKBACK_MS: number;
|
|
3200
|
+
/** Owner messages read for that evidence */
|
|
3201
|
+
readonly EVIDENCE_MAX_MESSAGES: 50;
|
|
3202
|
+
};
|
|
3148
3203
|
/** Claude Code facts */
|
|
3149
3204
|
readonly CLAUDE: {
|
|
3150
3205
|
readonly OAUTH_TOKEN_ENV: "CLAUDE_CODE_OAUTH_TOKEN";
|