crewly 1.20.315 → 1.20.317

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.
Files changed (154) hide show
  1. package/config/skills/_common/lib.sh +20 -0
  2. package/config/skills/_common/lib.test.sh +18 -0
  3. package/config/skills/agent/core/app-comments/execute.sh +1 -1
  4. package/config/skills/agent/core/app-data/execute.sh +1 -1
  5. package/config/skills/agent/core/attach-file/SKILL.md +6 -0
  6. package/config/skills/agent/core/attach-file/execute.sh +1 -1
  7. package/config/skills/agent/core/break-down-request/execute.sh +1 -1
  8. package/config/skills/agent/core/calendar-create/execute.sh +1 -1
  9. package/config/skills/agent/core/calendar-create/execute.test.sh +1 -1
  10. package/config/skills/agent/core/calendar-list/execute.sh +1 -1
  11. package/config/skills/agent/core/calendar-list/execute.test.sh +1 -1
  12. package/config/skills/agent/core/cancel-followup/execute.sh +1 -2
  13. package/config/skills/agent/core/canva-create/execute.sh +1 -1
  14. package/config/skills/agent/core/canva-designs/execute.sh +1 -1
  15. package/config/skills/agent/core/canva-export/execute.sh +1 -1
  16. package/config/skills/agent/core/canva-upload/execute.sh +1 -1
  17. package/config/skills/agent/core/create-mission/execute.sh +1 -1
  18. package/config/skills/agent/core/create-request/execute.sh +1 -1
  19. package/config/skills/agent/core/create-task/execute.sh +1 -1
  20. package/config/skills/agent/core/docs-comment/execute.sh +1 -1
  21. package/config/skills/agent/core/docs-read/execute.sh +1 -1
  22. package/config/skills/agent/core/docs-write/execute.sh +1 -1
  23. package/config/skills/agent/core/drive-read/execute.sh +1 -1
  24. package/config/skills/agent/core/drive-search/execute.sh +1 -1
  25. package/config/skills/agent/core/drive-upload/execute.sh +1 -1
  26. package/config/skills/agent/core/experiment-card/execute.sh +1 -1
  27. package/config/skills/agent/core/experiment-card/execute.test.sh +1 -1
  28. package/config/skills/agent/core/find-app-template/execute.sh +1 -1
  29. package/config/skills/agent/core/find-skill/execute.sh +1 -1
  30. package/config/skills/agent/core/find-skill/execute.test.sh +1 -1
  31. package/config/skills/agent/core/get-my-active-work/execute.sh +1 -1
  32. package/config/skills/agent/core/get-my-context/execute.sh +1 -1
  33. package/config/skills/agent/core/get-my-tasks/execute.sh +1 -1
  34. package/config/skills/agent/core/gmail-attachment/execute.sh +1 -1
  35. package/config/skills/agent/core/gmail-read/execute.sh +1 -1
  36. package/config/skills/agent/core/gmail-read/execute.test.sh +1 -1
  37. package/config/skills/agent/core/gmail-search/execute.sh +1 -1
  38. package/config/skills/agent/core/gmail-search/execute.test.sh +1 -1
  39. package/config/skills/agent/core/gmail-send/execute.sh +1 -1
  40. package/config/skills/agent/core/gmail-send/execute.test.sh +1 -1
  41. package/config/skills/agent/core/google-connect/execute.sh +1 -1
  42. package/config/skills/agent/core/install-skill/execute.sh +1 -1
  43. package/config/skills/agent/core/install-skill/execute.test.sh +1 -1
  44. package/config/skills/agent/core/list-channels/execute.sh +1 -1
  45. package/config/skills/agent/core/list-my-crons/execute.sh +1 -2
  46. package/config/skills/agent/core/list-my-followups/execute.sh +1 -2
  47. package/config/skills/agent/core/project-tickets/execute.sh +1 -1
  48. package/config/skills/agent/core/publish-app/execute.sh +1 -1
  49. package/config/skills/agent/core/recall/execute.sh +1 -1
  50. package/config/skills/agent/core/receive-file/execute.sh +1 -1
  51. package/config/skills/agent/core/record-learning/execute.sh +1 -1
  52. package/config/skills/agent/core/record-prediction/execute.sh +1 -1
  53. package/config/skills/agent/core/register-self/execute.sh +1 -1
  54. package/config/skills/agent/core/remember/execute.sh +1 -1
  55. package/config/skills/agent/core/reply/SKILL.md +5 -0
  56. package/config/skills/agent/core/reply/execute.sh +1 -1
  57. package/config/skills/agent/core/reply-channel/SKILL.md +8 -0
  58. package/config/skills/agent/core/reply-channel/execute.sh +1 -2
  59. package/config/skills/agent/core/reply-chat/execute.sh +1 -1
  60. package/config/skills/agent/core/report-status/execute.sh +1 -1
  61. package/config/skills/agent/core/request-file/execute.sh +1 -1
  62. package/config/skills/agent/core/resolve-prediction/execute.sh +1 -1
  63. package/config/skills/agent/core/schedule-followup/execute.sh +1 -2
  64. package/config/skills/agent/core/search-chat/execute.sh +1 -1
  65. package/config/skills/agent/core/send-file/execute.sh +1 -1
  66. package/config/skills/agent/core/send-message/execute.sh +1 -1
  67. package/config/skills/agent/core/set-focus/execute.sh +1 -1
  68. package/config/skills/agent/core/set-focus/execute.test.sh +1 -1
  69. package/config/skills/agent/core/sheets-read/execute.sh +1 -1
  70. package/config/skills/agent/core/sheets-write/execute.sh +1 -1
  71. package/config/skills/agent/core/slack-file/execute.sh +1 -1
  72. package/config/skills/agent/core/slack-post/execute.sh +1 -1
  73. package/config/skills/agent/core/slides-create/execute.sh +1 -1
  74. package/config/skills/agent/core/slides-read/execute.sh +1 -1
  75. package/config/skills/agent/core/split-ticket/execute.sh +1 -1
  76. package/config/skills/agent/core/standing-update/execute.sh +1 -1
  77. package/config/skills/agent/core/supersede-memory/execute.sh +1 -1
  78. package/config/skills/agent/core/suppress-noise/execute.sh +1 -1
  79. package/config/skills/agent/core/ticket-check/execute.sh +1 -1
  80. package/config/skills/agent/core/todo-add/execute.sh +1 -1
  81. package/config/skills/agent/core/todo-lists/execute.sh +1 -1
  82. package/config/skills/agent/core/todo-lists/execute.test.sh +1 -1
  83. package/config/skills/agent/core/todo-tasks/execute.sh +1 -1
  84. package/config/skills/agent/core/todo-update/execute.sh +1 -1
  85. package/config/skills/agent/core/use-app-template/execute.sh +1 -1
  86. package/config/skills/agent/core/watch-for-event/execute.sh +1 -2
  87. package/config/skills/agent/core/whatsapp-draft/execute.sh +1 -1
  88. package/config/skills/agent/core/whatsapp-draft/execute.test.sh +1 -1
  89. package/config/skills/agent/core/whatsapp-inbox/execute.sh +1 -1
  90. package/config/skills/agent/core/whatsapp-inbox/execute.test.sh +1 -1
  91. package/config/skills/agent/core/whatsapp-read/execute.sh +1 -1
  92. package/config/skills/agent/core/whatsapp-read/execute.test.sh +1 -1
  93. package/config/skills/agent/core/whatsapp-send/execute.sh +1 -1
  94. package/config/skills/agent/core/whatsapp-send/execute.test.sh +1 -1
  95. package/config/skills/agent/core/wiki-query/execute.sh +1 -1
  96. package/config/skills/agent/core/workspace/execute.sh +1 -1
  97. package/config/skills/agent/core/zoho-draft/execute.sh +1 -1
  98. package/config/skills/agent/onboarding/materialize-team/execute.sh +1 -1
  99. package/config/skills/agent/onboarding/recommend-team/execute.sh +1 -1
  100. package/config/skills/agent/onboarding/synthesize-hierarchy/execute.sh +1 -1
  101. package/config/skills/agent/remote-browser/execute.sh +1 -1
  102. package/config/skills/agent/v3/plan-request/execute.sh +1 -1
  103. package/config/skills/orchestrator/delegate-task/execute.sh +1 -1
  104. package/config/skills/orchestrator/harness-login/execute.sh +1 -1
  105. package/config/skills/orchestrator/harness-login/execute.test.sh +1 -1
  106. package/config/skills/orchestrator/reply-chat/execute.sh +1 -1
  107. package/config/skills/orchestrator/reply-gchat/execute.sh +1 -1
  108. package/config/skills/orchestrator/reply-remote/execute.sh +1 -1
  109. package/config/skills/orchestrator/reply-slack/execute.sh +1 -1
  110. package/config/skills/orchestrator/send-message/execute.sh +1 -1
  111. package/config/skills/orchestrator/send-message/execute.test.sh +1 -1
  112. package/config/skills/orchestrator/send-pdf-to-slack/execute.sh +1 -1
  113. package/config/skills/orchestrator/send-to-remote/execute.sh +1 -1
  114. package/config/skills/orchestrator/wiki-bookkeep/execute.sh +1 -1
  115. package/config/skills/orchestrator/wiki-cleanup/execute.sh +1 -1
  116. package/config/skills/orchestrator/wiki-ingest/execute.sh +1 -1
  117. package/config/skills/orchestrator/wiki-lint/execute.sh +1 -1
  118. package/config/skills/orchestrator/wiki-migrate/execute.sh +1 -1
  119. package/config/skills/orchestrator/wiki-process-queue/execute.sh +1 -1
  120. package/config/skills/orchestrator/wiki-queue-add/execute.sh +1 -1
  121. package/config/skills/team-leader/assign-ticket/execute.sh +1 -1
  122. package/config/skills/team-leader/assign-ticket/execute.test.sh +1 -1
  123. package/config/skills/team-leader/delegate-task/execute.sh +1 -1
  124. package/config/skills/team-leader/signal-digest/execute.sh +1 -1
  125. package/config/skills/team-leader/wiki-review-proposals/execute.sh +1 -1
  126. package/config/skills/team-leader/wiki-supersede/execute.sh +1 -1
  127. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  128. package/dist/backend/backend/src/controllers/slack/slack.controller.js +23 -0
  129. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  130. package/dist/backend/backend/src/services/slack/attach-file-chat-record.d.ts +49 -0
  131. package/dist/backend/backend/src/services/slack/attach-file-chat-record.d.ts.map +1 -0
  132. package/dist/backend/backend/src/services/slack/attach-file-chat-record.js +77 -0
  133. package/dist/backend/backend/src/services/slack/attach-file-chat-record.js.map +1 -0
  134. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  135. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js +3 -0
  136. package/dist/backend/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  137. package/dist/backend/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  138. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +3 -0
  139. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  140. package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts +8 -0
  141. package/dist/backend/backend/src/services/team-move/team-move-importer.d.ts.map +1 -1
  142. package/dist/backend/backend/src/services/team-move/team-move-importer.js +15 -0
  143. package/dist/backend/backend/src/services/team-move/team-move-importer.js.map +1 -1
  144. package/dist/backend/backend/src/services/team-move/team-move-runtime.d.ts.map +1 -1
  145. package/dist/backend/backend/src/services/team-move/team-move-runtime.js +6 -0
  146. package/dist/backend/backend/src/services/team-move/team-move-runtime.js.map +1 -1
  147. package/dist/backend/build-info.json +2 -2
  148. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.d.ts.map +1 -1
  149. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js +3 -0
  150. package/dist/cli/backend/src/services/slack/slack-agent-dm.service.js.map +1 -1
  151. package/dist/cli/backend/src/services/slack/slack-team-channel.service.d.ts.map +1 -1
  152. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +3 -0
  153. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  154. package/package.json +1 -1
@@ -378,6 +378,26 @@ error_exit() {
378
378
  exit 1
379
379
  }
380
380
 
381
+ # -----------------------------------------------------------------------------
382
+ # unknown_arg_exit arg
383
+ # Reports an unrecognised CLI argument as ONE machine-readable JSON line on
384
+ # stderr (always the LAST line, so `| tail -1` still shows it) and exits 2.
385
+ # An unknown flag gets the bare message. A bare word (not starting with "-") is almost always text that was split
386
+ # because an unescaped double quote ended a --content/--message/--comment
387
+ # string, so the hint says nothing was sent and how to avoid it.
388
+ # Call this INSTEAD of printing usage afterwards; print usage first if wanted.
389
+ # -----------------------------------------------------------------------------
390
+ unknown_arg_exit() {
391
+ local arg="${1:-}" msg
392
+ if [[ "$arg" == -* ]]; then
393
+ msg="Unknown argument: ${arg}"
394
+ else
395
+ msg="Unknown argument: ${arg} — nothing was sent. If your text contains double quotes, they ended the string (this word is the rest of it); use --content-file <path>, a heredoc via stdin, or single quotes."
396
+ fi
397
+ jq -cn --arg e "$msg" '{"success":false,"error":$e}' >&2
398
+ exit 2
399
+ }
400
+
381
401
  # -----------------------------------------------------------------------------
382
402
  # require_param name value
383
403
  # Exits with error if value is empty.
@@ -360,6 +360,24 @@ CREWLY_SESSION_NAME=dev-1 CREWLY_SCHEDULER_CREDENTIAL=scheduler.sig bash "$TEMP_
360
360
  assert_eq "api_call: an agent session wins over a leaked scheduler credential" "0" "$(grep -c 'X-Crewly-Internal' "$ARGS_OUT" || true)"
361
361
  unset ARGS_OUT
362
362
 
363
+ # ---- Test 31: unknown_arg_exit — the error is the LAST line, one JSON object, exit 2 ----
364
+ UA_OUT=$(bash -c 'source "$1"; unknown_arg_exit app; ' _ "$SCRIPT_DIR/lib.sh" 2>&1 >/dev/null; echo "rc=$?")
365
+ assert_contains "unknown_arg_exit: bare word → nothing sent + quoting hint" "nothing was sent" "$UA_OUT"
366
+ assert_contains "unknown_arg_exit: hint names content-file" "content-file" "$UA_OUT"
367
+ assert_contains "unknown_arg_exit: exit code 2" "rc=2" "$UA_OUT"
368
+ assert_eq "unknown_arg_exit: success:false" "false" "$(printf '%s' "$UA_OUT" | head -1 | jq -r .success)"
369
+ UA_FLAG=$(bash -c 'source "$1"; unknown_arg_exit --bogus' _ "$SCRIPT_DIR/lib.sh" 2>&1 >/dev/null || true)
370
+ assert_eq "unknown_arg_exit: unknown flag → bare message, no quoting hint" "Unknown argument: --bogus" "$(printf '%s' "$UA_FLAG" | jq -r .error)"
371
+
372
+ # ---- Test 32: reply-channel with a split --content (the 2026-10-12 incident) ----
373
+ RC_OUT=$(CREWLY_SESSION_NAME=t bash "$SCRIPT_DIR/../agent/core/reply-channel/execute.sh" --channel C1 --content 是我理解错了:我问要不要先不用 app 画面 2>&1 | tail -1; echo "rc=${PIPESTATUS[0]}")
374
+ assert_contains "reply-channel split content: LAST line is the JSON error" '"success":false' "$RC_OUT"
375
+ assert_contains "reply-channel split content: says nothing was sent" "nothing was sent" "$RC_OUT"
376
+ RC_RC=$(CREWLY_SESSION_NAME=t bash "$SCRIPT_DIR/../agent/core/reply-channel/execute.sh" --channel C1 --content a b c >/dev/null 2>&1; echo $?)
377
+ assert_eq "reply-channel split content: exit code 2" "2" "$RC_RC"
378
+ AF_RC=$(CREWLY_SESSION_NAME=t bash "$SCRIPT_DIR/../agent/core/attach-file/execute.sh" --channel C1 --path /x --comment a b c 2>&1 | tail -1 || true)
379
+ assert_contains "attach-file split comment: LAST line is the JSON error" '"success":false' "$AF_RC"
380
+
363
381
  echo ""
364
382
  echo "=== Results: $PASS/$TOTAL passed, $FAIL failed ==="
365
383
 
@@ -65,7 +65,7 @@ while [[ $# -gt 0 ]]; do
65
65
  --status) [ $# -ge 2 ] || error_exit "--status requires a value"; STATUS="$2"; shift 2 ;;
66
66
  --text) [ $# -ge 2 ] || error_exit "--text requires a value"; TEXT="$2"; HAS_TEXT=1; shift 2 ;;
67
67
  --help|-h) print_usage; exit 0 ;;
68
- *) error_exit "Unknown option: $1" ;;
68
+ *) unknown_arg_exit "$1" ;;
69
69
  esac
70
70
  done
71
71
 
@@ -169,7 +169,7 @@ while [[ $# -gt 0 ]]; do
169
169
  --scope) [ $# -ge 2 ] || error_exit "--scope requires a value"; SCOPE="$2"; shift 2 ;;
170
170
  --reason) [ $# -ge 2 ] || error_exit "--reason requires a value"; REASON="$2"; shift 2 ;;
171
171
  --help|-h) print_usage; exit 0 ;;
172
- *) error_exit "Unknown option: $1" ;;
172
+ *) unknown_arg_exit "$1" ;;
173
173
  esac
174
174
  done
175
175
 
@@ -60,6 +60,12 @@ they will want to edit it.
60
60
 
61
61
  Text still goes through `reply-channel` — send the words, attach the file.
62
62
 
63
+ Put `--comment` in single quotes (or leave quotation marks out of it): a
64
+ double quote inside `--comment "..."` splits the text into extra arguments and
65
+ the file is not sent. Read the JSON result; do not cut it off with `| tail -1`.
66
+ The file is also recorded in the chat history under your name, so teammates
67
+ reading the thread see you delivered it.
68
+
63
69
  ## Output
64
70
 
65
71
  `{"success":true,"data":{"slackChannelId":"C…","threadTs":"1758…","fileId":"F…","asAgentBot":true}}`
@@ -41,7 +41,7 @@ while [ $# -gt 0 ]; do
41
41
  --ticket) TICKET="${2:-}"; shift 2 ;;
42
42
  --to) TO="${2:-}"; shift 2 ;;
43
43
  -h|--help) usage; exit 0 ;;
44
- *) echo "{\"error\":\"Unknown argument: $1\"}" >&2; exit 1 ;;
44
+ *) unknown_arg_exit "$1" ;;
45
45
  esac
46
46
  done
47
47
 
@@ -69,7 +69,7 @@ while [[ $# -gt 0 ]]; do
69
69
  INPUT_JSON="$1"
70
70
  shift
71
71
  else
72
- error_exit "Unknown argument: $1. Use --help for usage."
72
+ unknown_arg_exit "$1"
73
73
  fi
74
74
  ;;
75
75
  esac
@@ -55,7 +55,7 @@ while [[ $# -gt 0 ]]; do
55
55
  ATTENDEES_JSON=$(jq -cn --argjson arr "$ATTENDEES_JSON" --arg v "$2" '$arr + [$v]'); shift 2 ;;
56
56
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
57
57
  --help|-h) print_usage; exit 0 ;;
58
- *) error_exit "Unknown option: $1" ;;
58
+ *) unknown_arg_exit "$1" ;;
59
59
  esac
60
60
  done
61
61
 
@@ -74,7 +74,7 @@ check "missing summary errors" "$(run_err --start 2026-10-01 --end 2026-10-02)"
74
74
  check "missing start errors" "$(run_err --summary x --end 2026-10-02)" "Missing required parameter: start (--start)"
75
75
  check "missing end errors" "$(run_err --summary x --start 2026-10-01)" "Missing required parameter: end (--end)"
76
76
  check "validation: no request made" "$(cat "$STUB_LOG")" ""
77
- check "unknown option errors" "$(run_err --bogus 1)" "Unknown option: --bogus"
77
+ check "unknown option errors" "$(run_err --bogus 1)" "Unknown argument: --bogus"
78
78
 
79
79
  echo "=== Results: $PASS passed, $FAIL failed ==="
80
80
  [ "$FAIL" -eq 0 ]
@@ -58,7 +58,7 @@ while [[ $# -gt 0 ]]; do
58
58
  --max|-n) [ $# -ge 2 ] || error_exit "--max requires a value"; MAX="$2"; shift 2 ;;
59
59
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
60
60
  --help|-h) print_usage; exit 0 ;;
61
- *) error_exit "Unknown option: $1" ;;
61
+ *) unknown_arg_exit "$1" ;;
62
62
  esac
63
63
  done
64
64
 
@@ -65,7 +65,7 @@ OUT=$(CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" --calendar no-grant
65
65
  check "409: exit code" "$RC" "1"
66
66
  check "409: reason + hint" "$OUT" '{"success":false,"reason":"not_connected","hint":"https://cloud/start?token=j","message":"no grant"}'
67
67
 
68
- check "unknown option errors" "$(run_err --bogus 1)" "Unknown option: --bogus"
68
+ check "unknown option errors" "$(run_err --bogus 1)" "Unknown argument: --bogus"
69
69
 
70
70
  echo "=== Results: $PASS passed, $FAIL failed ==="
71
71
  [ "$FAIL" -eq 0 ]
@@ -51,8 +51,7 @@ while [[ $# -gt 0 ]]; do
51
51
  if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
52
52
  INPUT_JSON="$1"; shift
53
53
  else
54
- echo '{"error":"Unknown argument: '"$1"'"}' >&2
55
- exit 1
54
+ unknown_arg_exit "$1"
56
55
  fi
57
56
  ;;
58
57
  esac
@@ -63,7 +63,7 @@ while [[ $# -gt 0 ]]; do
63
63
  --size) [ $# -ge 2 ] || error_exit "--size requires a value"; SIZE="$2"; shift 2 ;;
64
64
  --asset) [ $# -ge 2 ] || error_exit "--asset requires a value"; ASSET="$2"; shift 2 ;;
65
65
  --help|-h) print_usage; exit 0 ;;
66
- *) error_exit "Unknown option: $1" ;;
66
+ *) unknown_arg_exit "$1" ;;
67
67
  esac
68
68
  done
69
69
  if [ -n "$INPUT_JSON" ]; then
@@ -67,7 +67,7 @@ while [[ $# -gt 0 ]]; do
67
67
  --limit|-n) [ $# -ge 2 ] || error_exit "--limit requires a value"; LIMIT="$2"; shift 2 ;;
68
68
  --continuation) [ $# -ge 2 ] || error_exit "--continuation requires a value"; CONT="$2"; shift 2 ;;
69
69
  --help|-h) print_usage; exit 0 ;;
70
- *) error_exit "Unknown option: $1" ;;
70
+ *) unknown_arg_exit "$1" ;;
71
71
  esac
72
72
  done
73
73
  if [ -n "$INPUT_JSON" ]; then
@@ -69,7 +69,7 @@ while [[ $# -gt 0 ]]; do
69
69
  --out|-o) [ $# -ge 2 ] || error_exit "--out requires a value"; OUT_PATH="$2"; shift 2 ;;
70
70
  --out-dir) [ $# -ge 2 ] || error_exit "--out-dir requires a value"; OUT_DIR="$2"; shift 2 ;;
71
71
  --help|-h) print_usage; exit 0 ;;
72
- *) error_exit "Unknown option: $1" ;;
72
+ *) unknown_arg_exit "$1" ;;
73
73
  esac
74
74
  done
75
75
  if [ -n "$INPUT_JSON" ]; then
@@ -55,7 +55,7 @@ while [[ $# -gt 0 ]]; do
55
55
  --path|-p) [ $# -ge 2 ] || error_exit "--path requires a value"; FILE="$2"; shift 2 ;;
56
56
  --name) [ $# -ge 2 ] || error_exit "--name requires a value"; NAME="$2"; shift 2 ;;
57
57
  --help|-h) print_usage; exit 0 ;;
58
- *) error_exit "Unknown option: $1" ;;
58
+ *) unknown_arg_exit "$1" ;;
59
59
  esac
60
60
  done
61
61
  if [ -n "$INPUT_JSON" ]; then
@@ -85,7 +85,7 @@ while [[ $# -gt 0 ]]; do
85
85
  INPUT_JSON="$1"
86
86
  shift
87
87
  else
88
- error_exit "Unknown argument: $1. Use --help for usage."
88
+ unknown_arg_exit "$1"
89
89
  fi
90
90
  ;;
91
91
  esac
@@ -90,7 +90,7 @@ while [[ $# -gt 0 ]]; do
90
90
  INPUT_JSON="$1"
91
91
  shift
92
92
  else
93
- error_exit "Unknown argument: $1. Use --help for usage."
93
+ unknown_arg_exit "$1"
94
94
  fi
95
95
  ;;
96
96
  esac
@@ -114,7 +114,7 @@ while [[ $# -gt 0 ]]; do
114
114
  INPUT_JSON="$1"
115
115
  shift
116
116
  else
117
- error_exit "Unknown argument: $1. Use --help for usage."
117
+ unknown_arg_exit "$1"
118
118
  fi
119
119
  ;;
120
120
  esac
@@ -87,7 +87,7 @@ while [[ $# -gt 0 ]]; do
87
87
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
88
88
  --batch) [ $# -ge 2 ] || error_exit "--batch requires a value"; BATCH="$2"; shift 2 ;;
89
89
  --help|-h) print_usage; exit 0 ;;
90
- *) error_exit "Unknown option: $1" ;;
90
+ *) unknown_arg_exit "$1" ;;
91
91
  esac
92
92
  done
93
93
  if [ -n "$INPUT_JSON" ]; then
@@ -55,7 +55,7 @@ while [[ $# -gt 0 ]]; do
55
55
  --id) [ $# -ge 2 ] || error_exit "--id requires a value"; ID="$2"; shift 2 ;;
56
56
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
57
57
  --help|-h) print_usage; exit 0 ;;
58
- *) error_exit "Unknown option: $1" ;;
58
+ *) unknown_arg_exit "$1" ;;
59
59
  esac
60
60
  done
61
61
  if [ -n "$INPUT_JSON" ]; then
@@ -65,7 +65,7 @@ while [[ $# -gt 0 ]]; do
65
65
  --text-file) [ $# -ge 2 ] || error_exit "--text-file requires a value"; TEXT_FILE="$2"; shift 2 ;;
66
66
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
67
67
  --help|-h) print_usage; exit 0 ;;
68
- *) error_exit "Unknown option: $1" ;;
68
+ *) unknown_arg_exit "$1" ;;
69
69
  esac
70
70
  done
71
71
  if [ -n "$INPUT_JSON" ]; then
@@ -57,7 +57,7 @@ while [[ $# -gt 0 ]]; do
57
57
  --out|-o) [ $# -ge 2 ] || error_exit "--out requires a value"; OUT_PATH="$2"; shift 2 ;;
58
58
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
59
59
  --help|-h) print_usage; exit 0 ;;
60
- *) error_exit "Unknown option: $1" ;;
60
+ *) unknown_arg_exit "$1" ;;
61
61
  esac
62
62
  done
63
63
  if [ -n "$INPUT_JSON" ]; then
@@ -61,7 +61,7 @@ while [[ $# -gt 0 ]]; do
61
61
  --max|-n) [ $# -ge 2 ] || error_exit "--max requires a value"; MAX="$2"; shift 2 ;;
62
62
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
63
63
  --help|-h) print_usage; exit 0 ;;
64
- *) error_exit "Unknown option: $1" ;;
64
+ *) unknown_arg_exit "$1" ;;
65
65
  esac
66
66
  done
67
67
  if [ -n "$INPUT_JSON" ]; then
@@ -68,7 +68,7 @@ while [[ $# -gt 0 ]]; do
68
68
  --convert) [ $# -ge 2 ] || error_exit "--convert requires a value"; CONVERT="$2"; shift 2 ;;
69
69
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
70
70
  --help|-h) print_usage; exit 0 ;;
71
- *) error_exit "Unknown option: $1" ;;
71
+ *) unknown_arg_exit "$1" ;;
72
72
  esac
73
73
  done
74
74
  if [ -n "$INPUT_JSON" ]; then
@@ -103,7 +103,7 @@ while [[ $# -gt 0 ]]; do
103
103
  --status) [ $# -ge 2 ] || error_exit "--status requires a value"; STATUS="$2"; shift 2 ;;
104
104
  --reason) [ $# -ge 2 ] || error_exit "--reason requires a value"; REASON="$2"; shift 2 ;;
105
105
  --help|-h) print_usage; exit 0 ;;
106
- *) error_exit "Unknown option: $1" ;;
106
+ *) unknown_arg_exit "$1" ;;
107
107
  esac
108
108
  done
109
109
 
@@ -102,7 +102,7 @@ check "measure: not due" "$(run_err measure --id EXP-1 | grep -c 'not due')" "1"
102
102
 
103
103
  # --- unknown action / option ---
104
104
  check "unknown action" "$(run_err frobnicate | grep -c 'Unknown action')" "1"
105
- check "unknown option" "$(run_err list --nope | grep -c 'Unknown option')" "1"
105
+ check "unknown option" "$(run_err list --nope | grep -c 'Unknown argument')" "1"
106
106
 
107
107
  echo "experiment-card: $PASS passed, $FAIL failed"
108
108
  [ "$FAIL" -eq 0 ]
@@ -37,7 +37,7 @@ while [[ $# -gt 0 ]]; do
37
37
  --category) [ $# -ge 2 ] || error_exit "--category requires a value"; CATEGORY="$2"; shift 2 ;;
38
38
  --limit) [ $# -ge 2 ] || error_exit "--limit requires a value"; LIMIT="$2"; shift 2 ;;
39
39
  --help|-h) print_usage; exit 0 ;;
40
- *) if [ -z "$QUERY" ] && [ "${1:0:1}" != "-" ]; then QUERY="$1"; shift; else error_exit "Unknown option: $1"; fi ;;
40
+ *) if [ -z "$QUERY" ] && [ "${1:0:1}" != "-" ]; then QUERY="$1"; shift; else unknown_arg_exit "$1"; fi ;;
41
41
  esac
42
42
  done
43
43
  if [ -n "$INPUT_JSON" ]; then
@@ -40,7 +40,7 @@ while [[ $# -gt 0 ]]; do
40
40
  --query|-q) [ $# -ge 2 ] || error_exit "--query requires a value"; QUERY="$2"; shift 2 ;;
41
41
  --limit) [ $# -ge 2 ] || error_exit "--limit requires a value"; LIMIT="$2"; shift 2 ;;
42
42
  --help|-h) print_usage; exit 0 ;;
43
- *) error_exit "Unknown option: $1" ;;
43
+ *) unknown_arg_exit "$1" ;;
44
44
  esac
45
45
  done
46
46
  if [ -n "$INPUT_JSON" ]; then
@@ -63,7 +63,7 @@ check "backend error: message" "$(printf '%s' "$OUT" | jq -r .error)" "registry
63
63
 
64
64
  check "missing query" "$(run_err)" "Missing required parameter: query (--query)"
65
65
  check "bad limit" "$(run_err --query x --limit lots)" "--limit must be a number"
66
- check "unknown option" "$(run_err --install)" "Unknown option: --install"
66
+ check "unknown option" "$(run_err --install)" "Unknown argument: --install"
67
67
 
68
68
  echo "=== Results: $PASS passed, $FAIL failed ==="
69
69
  [ "$FAIL" -eq 0 ]
@@ -77,7 +77,7 @@ while [[ $# -gt 0 ]]; do
77
77
  INPUT_JSON="$1"
78
78
  shift
79
79
  else
80
- error_exit "Unknown argument: $1. Use --help for usage."
80
+ unknown_arg_exit "$1"
81
81
  fi
82
82
  ;;
83
83
  esac
@@ -65,7 +65,7 @@ while [[ $# -gt 0 ]]; do
65
65
  INPUT_JSON="$1"
66
66
  shift
67
67
  else
68
- error_exit "Unknown argument: $1. Use --help for usage."
68
+ unknown_arg_exit "$1"
69
69
  fi
70
70
  ;;
71
71
  esac
@@ -59,7 +59,7 @@ while [[ $# -gt 0 ]]; do
59
59
  INPUT_JSON="$1"
60
60
  shift
61
61
  else
62
- error_exit "Unknown argument: $1. Use --help for usage."
62
+ unknown_arg_exit "$1"
63
63
  fi
64
64
  ;;
65
65
  esac
@@ -37,7 +37,7 @@ while [[ $# -gt 0 ]]; do
37
37
  --out|-o) [ $# -ge 2 ] || error_exit "--out requires a value"; OUT="$2"; shift 2 ;;
38
38
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
39
39
  --help|-h) print_usage; exit 0 ;;
40
- *) error_exit "Unknown option: $1" ;;
40
+ *) unknown_arg_exit "$1" ;;
41
41
  esac
42
42
  done
43
43
  if [ -n "$INPUT_JSON" ]; then
@@ -39,7 +39,7 @@ while [[ $# -gt 0 ]]; do
39
39
  --id|-i) [ $# -ge 2 ] || error_exit "--id requires a value"; ID="$2"; shift 2 ;;
40
40
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
41
41
  --help|-h) print_usage; exit 0 ;;
42
- *) error_exit "Unknown option: $1" ;;
42
+ *) unknown_arg_exit "$1" ;;
43
43
  esac
44
44
  done
45
45
 
@@ -62,7 +62,7 @@ OUT=$(CREWLY_API_URL="http://127.0.0.1:${PORT}" bash "$EXEC" --id no-grant 2>/de
62
62
  check "409: hint is the connect URL" "$(printf '%s' "$OUT" | jq -r .hint)" "https://cloud/start?token=j"
63
63
 
64
64
  check "missing id errors" "$(run_err)" "Missing required parameter: id (--id)"
65
- check "unknown option errors" "$(run_err --bogus 1)" "Unknown option: --bogus"
65
+ check "unknown option errors" "$(run_err --bogus 1)" "Unknown argument: --bogus"
66
66
 
67
67
  echo "=== Results: $PASS passed, $FAIL failed ==="
68
68
  [ "$FAIL" -eq 0 ]
@@ -43,7 +43,7 @@ while [[ $# -gt 0 ]]; do
43
43
  --max|-n) [ $# -ge 2 ] || error_exit "--max requires a value"; MAX="$2"; shift 2 ;;
44
44
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
45
45
  --help|-h) print_usage; exit 0 ;;
46
- *) error_exit "Unknown option: $1" ;;
46
+ *) unknown_arg_exit "$1" ;;
47
47
  esac
48
48
  done
49
49
 
@@ -61,7 +61,7 @@ check "409: reason + hint" "$OUT" '{"success":false,"reason":"not_connected","hi
61
61
 
62
62
  # --- validation ---
63
63
  check "missing query errors" "$(run_err --max 3)" "Missing required parameter: query (--query)"
64
- check "unknown option errors" "$(run_err --bogus 1)" "Unknown option: --bogus"
64
+ check "unknown option errors" "$(run_err --bogus 1)" "Unknown argument: --bogus"
65
65
 
66
66
  echo "=== Results: $PASS passed, $FAIL failed ==="
67
67
  [ "$FAIL" -eq 0 ]
@@ -58,7 +58,7 @@ while [[ $# -gt 0 ]]; do
58
58
  --dry-run) DRY_RUN=1; shift ;;
59
59
  --account) [ $# -ge 2 ] || error_exit "--account requires a value"; ACCOUNT="$2"; shift 2 ;;
60
60
  --help|-h) print_usage; exit 0 ;;
61
- *) error_exit "Unknown option: $1" ;;
61
+ *) unknown_arg_exit "$1" ;;
62
62
  esac
63
63
  done
64
64
 
@@ -88,7 +88,7 @@ check "missing subject errors" "$(run_err --to a@b.c --text x)" "Missing require
88
88
  check "missing text errors" "$(run_err --to a@b.c --subject Hi)" "Missing required parameter: text (--text or --text-file)"
89
89
  check "missing text file errors" "$(run_err --to a@b.c --subject Hi --text-file /nonexistent/x.txt)" "text file not found: /nonexistent/x.txt"
90
90
  check "validation: no request made" "$(cat "$STUB_LOG")" ""
91
- check "unknown option errors" "$(run_err --bogus 1)" "Unknown option: --bogus"
91
+ check "unknown option errors" "$(run_err --bogus 1)" "Unknown argument: --bogus"
92
92
 
93
93
  echo "=== Results: $PASS passed, $FAIL failed ==="
94
94
  [ "$FAIL" -eq 0 ]
@@ -39,7 +39,7 @@ while [ $# -gt 0 ]; do
39
39
  --account) ACCOUNT="${2:-}"; shift 2 ;;
40
40
  --resend) shift ;;
41
41
  -h|--help) print_usage; exit 0 ;;
42
- *) echo "Unknown option: $1" >&2; print_usage >&2; exit 2 ;;
42
+ *) print_usage >&2; unknown_arg_exit "$1" ;;
43
43
  esac
44
44
  done
45
45
 
@@ -48,7 +48,7 @@ while [[ $# -gt 0 ]]; do
48
48
  --owner-said) [ $# -ge 2 ] || error_exit "--owner-said requires a value"; OWNER_SAID="$2"; shift 2 ;;
49
49
  --force) FORCE=true; shift ;;
50
50
  --help|-h) print_usage; exit 0 ;;
51
- *) error_exit "Unknown option: $1" ;;
51
+ *) unknown_arg_exit "$1" ;;
52
52
  esac
53
53
  done
54
54
  if [ -n "$INPUT_JSON" ]; then
@@ -68,7 +68,7 @@ OUT=$(run --id ready-one)
68
68
  check "already ready" "$(printf '%s' "$OUT" | jq -c '{state, executePath}')" '{"state":"already-ready","executePath":"/x/execute.sh"}'
69
69
 
70
70
  check "missing id" "$(run_err)" "Missing required parameter: id (--id)"
71
- check "unknown option" "$(run_err --yes)" "Unknown option: --yes"
71
+ check "unknown option" "$(run_err --yes)" "Unknown argument: --yes"
72
72
 
73
73
  echo "=== Results: $PASS passed, $FAIL failed ==="
74
74
  [ "$FAIL" -eq 0 ]
@@ -14,7 +14,7 @@ while [[ $# -gt 0 ]]; do
14
14
  echo " Lists the channels you are a member of; --all lists every channel."
15
15
  echo " Post in one with: reply-channel --channel '#name' --content \"...\""
16
16
  exit 0 ;;
17
- *) echo "Unknown argument: $1" >&2; exit 2 ;;
17
+ *) unknown_arg_exit "$1" ;;
18
18
  esac
19
19
  done
20
20
 
@@ -48,8 +48,7 @@ while [[ $# -gt 0 ]]; do
48
48
  if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
49
49
  INPUT_JSON="$1"; shift
50
50
  else
51
- echo '{"error":"Unknown argument: '"$1"'"}' >&2
52
- exit 1
51
+ unknown_arg_exit "$1"
53
52
  fi
54
53
  ;;
55
54
  esac
@@ -48,8 +48,7 @@ while [[ $# -gt 0 ]]; do
48
48
  if [[ -z "$INPUT_JSON" && ${1:0:1} == '{' ]]; then
49
49
  INPUT_JSON="$1"; shift
50
50
  else
51
- echo '{"error":"Unknown argument: '"$1"'"}' >&2
52
- exit 1
51
+ unknown_arg_exit "$1"
53
52
  fi
54
53
  ;;
55
54
  esac
@@ -217,7 +217,7 @@ while [[ $# -gt 0 ]]; do
217
217
  --skip-labels) [ $# -ge 2 ] || error_exit "--skip-labels requires a comma-separated list or default"; AP_SKIP="$2"; shift 2 ;;
218
218
  --full) shift ;;
219
219
  --help|-h) print_usage; exit 0 ;;
220
- *) error_exit "Unknown option: $1" ;;
220
+ *) unknown_arg_exit "$1" ;;
221
221
  esac
222
222
  done
223
223
 
@@ -137,7 +137,7 @@ while [[ $# -gt 0 ]]; do
137
137
  --unlist-template) [ $# -ge 2 ] || error_exit "--unlist-template requires a template id"; UNLIST_TEMPLATE="$2"; shift 2 ;;
138
138
  --my-templates) MY_TEMPLATES=true; shift ;;
139
139
  --help|-h) print_usage; exit 0 ;;
140
- *) error_exit "Unknown option: $1" ;;
140
+ *) unknown_arg_exit "$1" ;;
141
141
  esac
142
142
  done
143
143
 
@@ -57,7 +57,7 @@ while [[ $# -gt 0 ]]; do
57
57
  INPUT_JSON="$1"
58
58
  shift
59
59
  else
60
- error_exit "Unknown argument: $1"
60
+ unknown_arg_exit "$1"
61
61
  fi
62
62
  ;;
63
63
  esac
@@ -45,7 +45,7 @@ while [[ $# -gt 0 ]]; do
45
45
  --dir) [ $# -ge 2 ] || error_exit "--dir requires a value"; DIR="$2"; shift 2 ;;
46
46
  --no-ack) ACK=0; shift ;;
47
47
  --help|-h) print_usage; exit 0 ;;
48
- *) error_exit "Unknown option: $1" ;;
48
+ *) unknown_arg_exit "$1" ;;
49
49
  esac
50
50
  done
51
51
  [ -n "$ID" ] || error_exit "--id is required"
@@ -90,7 +90,7 @@ EOF
90
90
  INPUT_JSON="$1"
91
91
  shift
92
92
  else
93
- error_exit "Unknown argument: $1"
93
+ unknown_arg_exit "$1"
94
94
  fi
95
95
  ;;
96
96
  esac
@@ -53,7 +53,7 @@ while [[ $# -gt 0 ]]; do
53
53
  [ $# -ge 2 ] || error_exit "--session requires a value"
54
54
  SESSION_NAME="$2"; shift 2 ;;
55
55
  --help|-h) print_usage; exit 0 ;;
56
- *) error_exit "Unknown option: $1" ;;
56
+ *) unknown_arg_exit "$1" ;;
57
57
  esac
58
58
  done
59
59
 
@@ -71,7 +71,7 @@ while [[ $# -gt 0 ]]; do
71
71
  INPUT_JSON="$1"
72
72
  shift
73
73
  else
74
- error_exit "Unknown argument: $1. Use --help for usage."
74
+ unknown_arg_exit "$1"
75
75
  fi
76
76
  ;;
77
77
  esac
@@ -99,7 +99,7 @@ while [[ $# -gt 0 ]]; do
99
99
  INPUT_JSON="$1"
100
100
  shift
101
101
  else
102
- error_exit "Unknown argument: $1. Use --help for usage."
102
+ unknown_arg_exit "$1"
103
103
  fi
104
104
  ;;
105
105
  esac
@@ -91,6 +91,11 @@ bash config/skills/agent/core/reply/execute.sh --new-thread "Wiki link audit" "F
91
91
  Keep the `CREWLY_SESSION_NAME=<you>` prefix when your prompt shows one — it
92
92
  tells the system that you are the one replying.
93
93
 
94
+ **Text with double quotes or several lines:** pipe it on stdin
95
+ (`cat <<'EOF' | bash .../reply/execute.sh` ... `EOF`) instead of a quoted
96
+ argument -- a stray `"` splits the text and nothing is sent. Check for
97
+ `"success":true` in the output; do not cut it off with `| tail -1`.
98
+
94
99
  ## Options
95
100
 
96
101
  | Flag | What it does |
@@ -84,7 +84,7 @@ while [[ $# -gt 0 ]]; do
84
84
  --ack) ACK="1"; shift ;;
85
85
  --help|-h) print_usage; exit 0 ;;
86
86
  --) shift; if [[ $# -gt 0 && -z "$TEXT" ]]; then TEXT="$*"; fi; break ;;
87
- -*) echo "{\"success\":false,\"error\":\"Unknown option: $1\"}" >&2; print_usage >&2; exit 2 ;;
87
+ -*) print_usage >&2; unknown_arg_exit "$1" ;;
88
88
  *) if [ -z "$TEXT" ]; then TEXT="$1"; else TEXT="$TEXT $1"; fi; shift ;;
89
89
  esac
90
90
  done