crewly 1.20.290 → 1.20.292

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 (120) hide show
  1. package/config/domain-sops/expert-distillation.sop.md +45 -45
  2. package/config/skills/agent/core/calendar-create/SKILL.md +1 -1
  3. package/config/skills/agent/core/calendar-list/SKILL.md +1 -1
  4. package/config/skills/agent/core/docs-comment/SKILL.md +5 -3
  5. package/config/skills/agent/core/docs-read/SKILL.md +4 -2
  6. package/config/skills/agent/core/docs-write/SKILL.md +4 -2
  7. package/config/skills/agent/core/drive-read/SKILL.md +4 -2
  8. package/config/skills/agent/core/drive-search/SKILL.md +4 -2
  9. package/config/skills/agent/core/drive-upload/SKILL.md +4 -2
  10. package/config/skills/agent/core/gmail-read/SKILL.md +1 -1
  11. package/config/skills/agent/core/gmail-search/SKILL.md +5 -4
  12. package/config/skills/agent/core/gmail-send/SKILL.md +2 -2
  13. package/config/skills/agent/core/google-connect/SKILL.md +17 -14
  14. package/config/skills/agent/core/google-connect/execute.sh +25 -8
  15. package/config/skills/agent/core/sheets-read/SKILL.md +4 -2
  16. package/config/skills/agent/core/sheets-write/SKILL.md +4 -2
  17. package/config/skills/agent/core/slides-create/SKILL.md +4 -2
  18. package/config/skills/agent/core/slides-read/SKILL.md +4 -2
  19. package/dist/backend/backend/src/constants.d.ts +24 -9
  20. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  21. package/dist/backend/backend/src/constants.js +41 -26
  22. package/dist/backend/backend/src/constants.js.map +1 -1
  23. package/dist/backend/backend/src/controllers/bundle/bundle.controller.js +1 -1
  24. package/dist/backend/backend/src/controllers/bundle/bundle.controller.js.map +1 -1
  25. package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts +36 -19
  26. package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts.map +1 -1
  27. package/dist/backend/backend/src/controllers/google/google-connect-card.js +57 -40
  28. package/dist/backend/backend/src/controllers/google/google-connect-card.js.map +1 -1
  29. package/dist/backend/backend/src/controllers/google/google.controller.d.ts +3 -2
  30. package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
  31. package/dist/backend/backend/src/controllers/google/google.controller.js +36 -10
  32. package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
  33. package/dist/backend/backend/src/services/bundle/bundle-apply.service.js +45 -45
  34. package/dist/backend/backend/src/services/bundle/bundle-apply.service.js.map +1 -1
  35. package/dist/backend/backend/src/services/bundle/bundle-placeholders.js +7 -7
  36. package/dist/backend/backend/src/services/bundle/bundle-placeholders.js.map +1 -1
  37. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +3 -3
  38. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +19 -19
  39. package/dist/backend/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  40. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.d.ts +1 -1
  41. package/dist/backend/backend/src/services/chat-v2/sqlite/message.store.js +1 -1
  42. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts +17 -21
  43. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts.map +1 -1
  44. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js +34 -39
  45. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js.map +1 -1
  46. package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts +6 -2
  47. package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts.map +1 -1
  48. package/dist/backend/backend/src/services/google/google-reauth.wiring.js +9 -4
  49. package/dist/backend/backend/src/services/google/google-reauth.wiring.js.map +1 -1
  50. package/dist/backend/backend/src/services/google/google-workspace-token.service.js +1 -1
  51. package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
  52. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js +2 -2
  53. package/dist/backend/backend/src/services/messaging/owner-message-watchdog.wiring.js.map +1 -1
  54. package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js +1 -1
  55. package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -1
  56. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  57. package/dist/backend/backend/src/services/slack/slack-initializer.js +36 -12
  58. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  59. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js +1 -1
  60. package/dist/backend/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  61. package/dist/backend/backend/src/services/slack/slack-thread-context.service.js +1 -1
  62. package/dist/backend/backend/src/services/slack/slack-thread-context.service.js.map +1 -1
  63. package/dist/backend/backend/src/services/slack/slack-thread-key.d.ts +12 -0
  64. package/dist/backend/backend/src/services/slack/slack-thread-key.d.ts.map +1 -1
  65. package/dist/backend/backend/src/services/slack/slack-thread-key.js +20 -0
  66. package/dist/backend/backend/src/services/slack/slack-thread-key.js.map +1 -1
  67. package/dist/backend/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  68. package/dist/backend/backend/src/services/task-pool/task-pool.service.js +2 -2
  69. package/dist/backend/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  70. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.d.ts +3 -3
  71. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js +7 -7
  72. package/dist/backend/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  73. package/dist/backend/backend/src/services/v3/ticket-intake.service.d.ts +2 -2
  74. package/dist/backend/backend/src/services/v3/ticket-intake.service.js +1 -1
  75. package/dist/backend/backend/src/services/v3/ticket-review.service.js +5 -5
  76. package/dist/backend/backend/src/services/v3/ticket-review.service.js.map +1 -1
  77. package/dist/backend/backend/src/utils/incomplete-turn.utils.js +6 -6
  78. package/dist/backend/backend/src/utils/incomplete-turn.utils.js.map +1 -1
  79. package/dist/backend/build-info.json +2 -2
  80. package/dist/cli/backend/src/constants.d.ts +24 -9
  81. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  82. package/dist/cli/backend/src/constants.js +41 -26
  83. package/dist/cli/backend/src/constants.js.map +1 -1
  84. package/dist/cli/backend/src/services/bundle/bundle-apply.service.js +45 -45
  85. package/dist/cli/backend/src/services/bundle/bundle-apply.service.js.map +1 -1
  86. package/dist/cli/backend/src/services/bundle/bundle-placeholders.js +7 -7
  87. package/dist/cli/backend/src/services/bundle/bundle-placeholders.js.map +1 -1
  88. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.d.ts +3 -3
  89. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js +19 -19
  90. package/dist/cli/backend/src/services/chat-v2/chat-v2.dispatcher.service.js.map +1 -1
  91. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.d.ts +1 -1
  92. package/dist/cli/backend/src/services/chat-v2/sqlite/message.store.js +1 -1
  93. package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js +1 -1
  94. package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -1
  95. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js +1 -1
  96. package/dist/cli/backend/src/services/slack/slack-team-channel.service.js.map +1 -1
  97. package/dist/cli/backend/src/services/slack/slack-thread-context.service.js +1 -1
  98. package/dist/cli/backend/src/services/slack/slack-thread-context.service.js.map +1 -1
  99. package/dist/cli/backend/src/services/slack/slack-thread-key.d.ts +12 -0
  100. package/dist/cli/backend/src/services/slack/slack-thread-key.d.ts.map +1 -1
  101. package/dist/cli/backend/src/services/slack/slack-thread-key.js +20 -0
  102. package/dist/cli/backend/src/services/slack/slack-thread-key.js.map +1 -1
  103. package/dist/cli/backend/src/services/task-pool/task-pool.service.d.ts.map +1 -1
  104. package/dist/cli/backend/src/services/task-pool/task-pool.service.js +2 -2
  105. package/dist/cli/backend/src/services/task-pool/task-pool.service.js.map +1 -1
  106. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.d.ts +3 -3
  107. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js +7 -7
  108. package/dist/cli/backend/src/services/v3/ticket-channel-hooks.js.map +1 -1
  109. package/dist/cli/backend/src/services/v3/ticket-intake.service.d.ts +2 -2
  110. package/dist/cli/backend/src/services/v3/ticket-intake.service.js +1 -1
  111. package/dist/cli/backend/src/services/v3/ticket-review.service.js +5 -5
  112. package/dist/cli/backend/src/services/v3/ticket-review.service.js.map +1 -1
  113. package/dist/cli/backend/src/utils/incomplete-turn.utils.js +6 -6
  114. package/dist/cli/backend/src/utils/incomplete-turn.utils.js.map +1 -1
  115. package/dist/cli/cli/src/commands/deploy-bundle.js +4 -4
  116. package/dist/cli/cli/src/commands/deploy-bundle.js.map +1 -1
  117. package/dist/cli/cli/src/commands/onboard.js +1 -1
  118. package/dist/cli/cli/src/commands/onboard.js.map +1 -1
  119. package/package.json +1 -1
  120. package/packages/crewly-agent/src/runtime/reply-tool-calls.ts +0 -3
@@ -1,70 +1,70 @@
1
- # SOP: Expert Mindset Distillation (名人思维蒸馏)
1
+ # SOP: Expert Mindset Distillation
2
2
 
3
3
  **Version:** 1.0.0
4
4
  **Owner:** Product Team (Mia)
5
5
  **Scope:** Crewly Pro Core Methodology
6
6
 
7
- ## 1. 目标 (Objective)
8
- 本 SOP 旨在标准化「专家思维蒸馏」流程,将非结构化的名人/专家素材转化为 Crewly 可用的结构化 `Expert Profile` (MD + JSON),从而为 Agent 提供高质量的思维注入。
7
+ ## 1. Objective
8
+ This SOP standardizes the "expert mindset distillation" process: turning unstructured material from famous people and experts into a structured `Expert Profile` (MD + JSON) that Crewly can use, so Agents get high-quality mindset injection.
9
9
 
10
- ## 2. 输入 (Inputs)
11
- - **Primary Source:** 专家著作 (PDF/EPUB)、公开访谈录音或转录稿 (Markdown/TXT)。
12
- - **Secondary Source:** 媒体分析文章、维基百科、YouTube 视频转录。
10
+ ## 2. Inputs
11
+ - **Primary Source:** the expert's books (PDF/EPUB), public interview recordings or transcripts (Markdown/TXT).
12
+ - **Secondary Source:** media analysis articles, Wikipedia, YouTube video transcripts.
13
13
  - **Tools:**
14
- - Teacher Model: Claude 3.5 Sonnet (首选) 或 GPT-4o。
15
- - Crewly Distiller CLI: `crewly-pro distill`。
14
+ - Teacher Model: Claude 3.5 Sonnet (preferred) or GPT-4o.
15
+ - Crewly Distiller CLI: `crewly-pro distill`.
16
16
 
17
- ## 3. 流程阶段 (Phases)
17
+ ## 3. Phases
18
18
 
19
- ### Phase 1: 素材清洗 (Data Preprocessing)
20
- - **任务:** 过滤掉无关信息(广告、日常寒暄、重复片段)。
21
- - **标准:** 仅保留包含「决策逻辑」、「价值观」、「行业洞察」和「语言风格」的核心文本。
22
- - **输出:** 清洗后的文本文件 (`raw_distill_input.txt`)。
19
+ ### Phase 1: Data Preprocessing
20
+ - **Task:** filter out irrelevant material (ads, small talk, repeated passages).
21
+ - **Standard:** keep only the core text that contains "decision logic", "values", "industry insights" and "language style".
22
+ - **Output:** the cleaned text file (`raw_distill_input.txt`).
23
23
 
24
- ### Phase 2: 专家特征提取 (Mindset Extraction)
25
- - **任务:** 使用 Teacher Model 执行蒸馏提示词 (Distillation Prompt)。
24
+ ### Phase 2: Mindset Extraction
25
+ - **Task:** run the Distillation Prompt with the Teacher Model.
26
26
  - **Prompt:**
27
27
  ```markdown
28
28
  # SYSTEM PROMPT: Expert Mindset Distiller
29
- 你是一名顶级的「思维建模专家」。你的目标是分析提供的专家素材,提取其底层的「思维软件」。
29
+ You are a top-tier "mindset modeling expert". Your goal is to analyze the provided expert material and extract the underlying "thinking software".
30
30
 
31
- ## 提取维度:
32
- 1. **Mental Models (思维模型):** 专家常用的核心框架(如第一性原理、二八定律)。
33
- 2. **Decision Logic (决策逻辑):** 专家如何权衡风险、处理权衡、评估长短期利益。
34
- 3. **Industry Insights (行业洞察):** 专家对特定领域的独特「反直觉」见解。
35
- 4. **Communication Style (沟通风格):** 语气词、标志性短语、论证逻辑结构。
31
+ ## Dimensions to extract:
32
+ 1. **Mental Models:** the core frameworks the expert uses often (e.g. first principles, the 80/20 rule).
33
+ 2. **Decision Logic:** how the expert weighs risk, handles trade-offs, and evaluates short- vs long-term benefit.
34
+ 3. **Industry Insights:** the expert's distinctive "counter-intuitive" views on a specific field.
35
+ 4. **Communication Style:** filler words, signature phrases, the structure of their argumentation.
36
36
 
37
- ## 约束:
38
- - 必须使用分析性的、冷静的第三方视角描述,而非模仿其语气说话。
39
- - 提取的思维模型必须具有「可操作性」,即 Agent 可以在执行任务时引用。
37
+ ## Constraints:
38
+ - Describe from an analytical, calm third-person perspective; do not imitate their tone of voice.
39
+ - The extracted mental models must be "actionable", i.e. an Agent can cite them while executing tasks.
40
40
  ```
41
- - **输出:** 专家思维草稿 (`{expert-id}-draft.md`)。
41
+ - **Output:** the expert mindset draft (`{expert-id}-draft.md`).
42
42
 
43
- ### Phase 3: 格式化与 JSON 元数据生成 (Synthesis)
44
- - **任务:** 将草稿整理为标准 Markdown 格式,并生成元数据 JSON。
45
- - **JSON 规范:** 参考 `config/experts/EXAMPLE.json`。
46
- - **MD 规范:** 参考 `config/experts/EXAMPLE.md`。
43
+ ### Phase 3: Formatting and JSON Metadata (Synthesis)
44
+ - **Task:** turn the draft into standard Markdown and generate the metadata JSON.
45
+ - **JSON spec:** see `config/experts/EXAMPLE.json`.
46
+ - **MD spec:** see `config/experts/EXAMPLE.md`.
47
47
 
48
- ### Phase 4: OSS/Pro 边界处理 (Security & Packaging)
49
- - **任务:** 根据分发渠道进行打包。
48
+ ### Phase 4: OSS/Pro Boundary (Security & Packaging)
49
+ - **Task:** package according to the distribution channel.
50
50
  - **OSS:**
51
- - 仅包含 MD 文件。
52
- - 存储于 `config/experts/`。
51
+ - MD file only.
52
+ - Stored in `config/experts/`.
53
53
  - **Pro:**
54
- - 包含 MD + JSON。
55
- - 包含预设的 `intensity` 值。
56
- - 存储于 `crewly-pro/data/experts/`。
57
- - 必须通过 `LicenseValidator` 检查。
54
+ - MD + JSON.
55
+ - Includes a preset `intensity` value.
56
+ - Stored in `crewly-pro/data/experts/`.
57
+ - Must pass the `LicenseValidator` check.
58
58
 
59
- ### Phase 5: 质量审核 (Quality Gates)
60
- - **Round 1 (Self):** 蒸馏者检查逻辑是否自洽。
61
- - **Round 2 (Peer):** 另一名 PM 或专家审核提取的模型是否抓住了本质。
62
- - **Round 3 (Test):** 将 Profile 注入 Agent,进行 3 个标准任务的 Prompt 压力测试。
59
+ ### Phase 5: Quality Gates
60
+ - **Round 1 (Self):** the distiller checks that the logic is self-consistent.
61
+ - **Round 2 (Peer):** another PM or expert reviews whether the extracted models capture the essence.
62
+ - **Round 3 (Test):** inject the Profile into an Agent and run a prompt stress test on 3 standard tasks.
63
63
 
64
- ## 4. 交付物 (Outputs)
64
+ ## 4. Outputs
65
65
  - `config/experts/{id}.md`
66
66
  - `crewly-pro/data/experts/{id}.json` (Pro Only)
67
67
 
68
- ## 5. 质量指标 (KPIs)
69
- - **Accuracy:** 蒸馏模型能准确预测专家在 80% 常见商业场景下的决策倾向。
70
- - **Utility:** Agent 使用该模板后,在特定领域的专业评分提升 ≥ 20%。
68
+ ## 5. KPIs
69
+ - **Accuracy:** the distilled model accurately predicts the expert's decision tendencies in 80% of common business scenarios.
70
+ - **Utility:** after an Agent uses the template, its professional rating in the specific domain improves by ≥ 20%.
@@ -63,7 +63,7 @@ Missing `--summary` / `--start` / `--end` → `{"error":"Missing required parame
63
63
 
64
64
  ## Choosing a Google account
65
65
 
66
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
66
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
67
67
 
68
68
  ```bash
69
69
  bash execute.sh --account work@company.com ...
@@ -59,7 +59,7 @@ when the owner has not connected Google Workspace.
59
59
 
60
60
  ## Choosing a Google account
61
61
 
62
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
62
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
63
63
 
64
64
  ```bash
65
65
  bash execute.sh --account work@company.com ...
@@ -100,8 +100,10 @@ older connections do not include. When the output has
100
100
  `"reconnectLinkSent":true`, the harness has already sent the owner a one-tap
101
101
  reconnect card in Slack: tell them in one line what you will do once it is
102
102
  granted, and retry when you get `[GOOGLE] Google Drive reconnected — retry your
103
- comment.` Without it, run `google-connect --product drive --channel <chat-channel-id>` to
104
- post the card yourself. Do not paste a link yourself.
103
+ comment.` The card's link does not expire. If the owner says it did not work (or
104
+ there is no `reconnectLinkSent`), run `google-connect --product drive --resend` for a
105
+ fresh card, or give them https://crewlyai.com/portal/integrations/google?products=drive&auto=1
106
+ to open directly. Never send them to Crewly settings or the Connections page.
105
107
 
106
108
  `{"success":false,"reason":"not_connected","hint":"…"}` (exit 1): Google
107
109
  Drive is not connected. Use `google-connect --product drive` the same way.
@@ -115,7 +117,7 @@ wrong, or the account cannot see the document.
115
117
 
116
118
  ## Choosing a Google account
117
119
 
118
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
120
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
119
121
 
120
122
  ```bash
121
123
  bash execute.sh list --doc 1AbC… --account work@company.com
@@ -45,13 +45,15 @@ bash execute.sh --id "https://docs.google.com/document/d/1AbC…/edit"
45
45
  ## Failures
46
46
 
47
47
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
48
- when the owner has not connected Google Workspace (Settings → Integrations).
48
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
49
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
50
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
49
51
  A `403` with `reason: "google_error"` on a write means the file was not
50
52
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
51
53
 
52
54
  ## Choosing a Google account
53
55
 
54
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
56
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
55
57
 
56
58
  ```bash
57
59
  bash execute.sh --account work@company.com ...
@@ -50,13 +50,15 @@ re-connect Google Workspace once the scope is enabled".
50
50
  ## Failures
51
51
 
52
52
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
53
- when the owner has not connected Google Workspace (Settings → Integrations).
53
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
54
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
55
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
54
56
  A `403` with `reason: "google_error"` on a write means the file was not
55
57
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
56
58
 
57
59
  ## Choosing a Google account
58
60
 
59
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
61
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
60
62
 
61
63
  ```bash
62
64
  bash execute.sh --account work@company.com ...
@@ -39,13 +39,15 @@ Files over 10 MB are refused with a `webViewLink` to open instead.
39
39
  ## Failures
40
40
 
41
41
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
42
- when the owner has not connected Google Workspace (Settings → Integrations).
42
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
43
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
44
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
43
45
  A `403` with `reason: "google_error"` on a write means the file was not
44
46
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
45
47
 
46
48
  ## Choosing a Google account
47
49
 
48
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
50
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
49
51
 
50
52
  ```bash
51
53
  bash execute.sh --account work@company.com ...
@@ -41,13 +41,15 @@ else → `drive-read`.
41
41
  ## Failures
42
42
 
43
43
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
44
- when the owner has not connected Google Workspace (Settings → Integrations).
44
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
45
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
46
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
45
47
  A `403` with `reason: "google_error"` on a write means the file was not
46
48
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
47
49
 
48
50
  ## Choosing a Google account
49
51
 
50
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
52
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
51
53
 
52
54
  ```bash
53
55
  bash execute.sh --account work@company.com ...
@@ -40,13 +40,15 @@ permissions are the owner's — this skill does not change sharing).
40
40
  ## Failures
41
41
 
42
42
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
43
- when the owner has not connected Google Workspace (Settings → Integrations).
43
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
44
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
45
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
44
46
  A `403` with `reason: "google_error"` on a write means the file was not
45
47
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
46
48
 
47
49
  ## Choosing a Google account
48
50
 
49
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
51
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
50
52
 
51
53
  ```bash
52
54
  bash execute.sh --account work@company.com ...
@@ -62,7 +62,7 @@ with a 404 message when the id is unknown.
62
62
 
63
63
  ## Choosing a Google account
64
64
 
65
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
65
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
66
66
 
67
67
  ```bash
68
68
  bash execute.sh --account work@company.com ...
@@ -33,7 +33,7 @@ execution:
33
33
  # Gmail Search
34
34
 
35
35
  Runs a Gmail search on the owner's mailbox and prints the hits. Uses the
36
- Google Workspace connection the owner made under Settings → Integrations;
36
+ Google Workspace connection the owner made in Crewly;
37
37
  the mail content goes straight from Google to this instance.
38
38
 
39
39
  ```bash
@@ -60,12 +60,13 @@ Use the `id` with `gmail-read` to get the body; `threadId` + `gmail-read`'s
60
60
  ## Failures
61
61
 
62
62
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` — the
63
- owner has not connected Google Workspace yet; hand them the hint URL (or
64
- point them to Settings → Integrations → Google Workspace). Exit code 1.
63
+ owner has not connected Google Workspace yet; run the `google-connect` skill so
64
+ they get a one-tap card in Slack (manual fallback: https://crewlyai.com/portal/integrations/google; never
65
+ Crewly settings or the Connections page). Exit code 1.
65
66
 
66
67
  ## Choosing a Google account
67
68
 
68
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
69
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
69
70
 
70
71
  ```bash
71
72
  bash execute.sh --account work@company.com ...
@@ -103,13 +103,13 @@ There is no output shape in which you have sent an email.
103
103
  Missing `--to` / `--subject` / body → `{"error":"Missing required parameter: …"}` on stderr, exit 1, nothing sent.
104
104
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1) when the owner has not connected Google Workspace.
105
105
 
106
- `{"success":false,"reason":"reauth_required","hint":"A reconnect link was sent to the owner in Slack. …","reconnectLinkSent":true}` (exit 1): the Gmail connection cannot save drafts yet (connections made before 2026-10-08 lack that permission). The harness has already sent the owner a one-tap reconnect card in Slack. Tell them in one line that you need them to tap it — do not ask them to open Connections, and do not paste a link. When it is done you get `[GOOGLE] Gmail reconnected — retry your draft.`; run the same command again.
106
+ `{"success":false,"reason":"reauth_required","hint":"A reconnect link was sent to the owner in Slack. …","reconnectLinkSent":true}` (exit 1): the Gmail connection cannot save drafts yet (connections made before 2026-10-08 lack that permission). The harness has already sent the owner a one-tap reconnect card in Slack. Tell them in one line that you need them to tap it — do not send them to Crewly settings or Connections. The card's link does not expire; if they say it failed, run the `google-connect` skill for a fresh one, or give them https://crewlyai.com/portal/integrations/google. When it is done you get `[GOOGLE] Gmail reconnected — retry your draft.`; run the same command again.
107
107
 
108
108
  `{"success":false,"reason":"not_connected",…,"reconnectLinkSent":true}` (exit 1): Gmail access expired or was revoked. Same as above: the owner already has the card; wait for `[GOOGLE] Gmail reconnected …` and retry.
109
109
 
110
110
  ## Choosing a Google account
111
111
 
112
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
112
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
113
113
 
114
114
  ```bash
115
115
  bash execute.sh --account work@company.com ...
@@ -23,22 +23,25 @@ execution:
23
23
 
24
24
  # Google Connect
25
25
 
26
- When a Google skill answers `not_connected`, the owner has not granted that
27
- product yet. Do **not** improvise an authorization link: the one this
28
- instance can build carries a Cloud session token, and posting it into a
29
- channel publishes a credential. It also expires within the hour, so the link
30
- you paste is usually dead by the time anyone clicks it.
31
-
32
- Run this instead. It posts a card with an **Add** button that only the
33
- person who asked can see, backed by a single-use link.
26
+ When a Google skill answers `not_connected` or `reauth_required`, the owner has
27
+ to grant (or re-grant) a product. Do **not** improvise an authorization link:
28
+ never build one by hand and never paste one. Run this instead. It posts a card
29
+ with a button that only the person who asked can see; the button opens the
30
+ Crewly portal's Google page, so the link carries no credential and **never
31
+ expires**. The owner can tap it hours later, from a phone.
34
32
 
35
33
  ```bash
36
- bash execute.sh --product gmail --channel <chat-channel-id>
34
+ bash execute.sh --product gmail [--channel <chat-channel-id>] [--account me@example.com]
37
35
  ```
38
36
 
39
- `--channel` is the id in the `[CHAT:…]` header of the message you are
40
- answering.
37
+ - `--channel` is the id in the `[CHAT:…]` or `[SLACK-THREAD:…]` header of the
38
+ message you are answering. It is optional: without it, or if it cannot be
39
+ resolved, the card goes where you are working with the owner, else their DM.
40
+ - Every call posts a fresh card. If the owner says the last card did not work,
41
+ run it again (`--resend` is accepted to make that intent explicit).
42
+ - Never tell the owner to open Crewly settings or the Connections page — they
43
+ are usually on a phone and cannot reach it. If they cannot find the card, the
44
+ manual fallback is https://crewlyai.com/portal/integrations/google
41
45
 
42
- After running it, say in one line that you have asked for access and what
43
- you will do once it is granted. Do not repeat the link — there is no link
44
- to repeat.
46
+ After running it, say in one line that you have asked for access and what you
47
+ will do once it is granted. Do not repeat a link.
@@ -3,11 +3,11 @@
3
3
  # google-connect — Ask the owner to authorize a Google product, in Slack
4
4
  #
5
5
  # Backed by POST /api/google/connect-card, which posts a Block Kit card whose
6
- # button carries a single-use ticket. Never build an authorization link by
7
- # hand: the one this instance can build embeds the Cloud session token.
6
+ # button opens the Cloud portal's Google page (no token in the link, and it
7
+ # never expires). Never build an authorization link by hand.
8
8
  #
9
9
  # Usage:
10
- # bash execute.sh --product gmail --channel chat-abc123
10
+ # bash execute.sh --product gmail [--channel chat-abc123] [--account me@x.com] [--resend]
11
11
  # =============================================================================
12
12
  set -euo pipefail
13
13
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
@@ -16,32 +16,49 @@ source "${SCRIPT_DIR}/../../_common/lib.sh"
16
16
  print_usage() {
17
17
  cat <<'EOF_USAGE'
18
18
  Usage:
19
- bash execute.sh --product <gmail|calendar|drive> --channel <chat-channel-id>
19
+ bash execute.sh --product <gmail|calendar|drive> [--channel <id>] [--account <email>] [--resend]
20
20
 
21
21
  Options:
22
22
  --product Which Google product needs access (required)
23
- --channel The chat channel you are answering in — the id in [CHAT:…] (required)
23
+ --channel The id in the [CHAT:...] / [SLACK-THREAD:...] header of the message you are
24
+ answering. Optional: without it (or if it cannot be resolved) the card goes
25
+ where you are working, else the owner's DM.
26
+ --account Google account to reconnect, when it matters
27
+ --resend The owner said the last card did not work; every call posts a fresh card
28
+ (accepted for clarity, the flag changes nothing)
24
29
  EOF_USAGE
25
30
  }
26
31
 
27
32
  PRODUCT=""
28
33
  CHANNEL=""
34
+ ACCOUNT=""
29
35
  while [ $# -gt 0 ]; do
30
36
  case "$1" in
31
37
  --product) PRODUCT="${2:-}"; shift 2 ;;
32
38
  --channel) CHANNEL="${2:-}"; shift 2 ;;
39
+ --account) ACCOUNT="${2:-}"; shift 2 ;;
40
+ --resend) shift ;;
33
41
  -h|--help) print_usage; exit 0 ;;
34
42
  *) echo "Unknown option: $1" >&2; print_usage >&2; exit 2 ;;
35
43
  esac
36
44
  done
37
45
 
38
- if [ -z "$PRODUCT" ] || [ -z "$CHANNEL" ]; then
39
- echo "Both --product and --channel are required." >&2
46
+ if [ -z "$PRODUCT" ]; then
47
+ echo "--product is required." >&2
40
48
  print_usage >&2
41
49
  exit 2
42
50
  fi
43
51
 
44
- BODY=$(printf '{"product":"%s","channelId":"%s"}' "$PRODUCT" "$CHANNEL")
52
+ # Values go into JSON by hand (no jq dependency): refuse anything that could break out.
53
+ for v in "$PRODUCT" "$CHANNEL" "$ACCOUNT"; do
54
+ case "$v" in
55
+ *[\"\\]*|*$'\n'*) echo "Arguments must not contain quotes, backslashes or newlines." >&2; exit 2 ;;
56
+ esac
57
+ done
58
+ BODY=$(printf '{"product":"%s"' "$PRODUCT")
59
+ [ -n "$CHANNEL" ] && BODY="${BODY},$(printf '"channelId":"%s"' "$CHANNEL")"
60
+ [ -n "$ACCOUNT" ] && BODY="${BODY},$(printf '"account":"%s"' "$ACCOUNT")"
61
+ BODY="${BODY}}"
45
62
  RESPONSE=$(api_call POST "/google/connect-card" "$BODY" 2>&1) || {
46
63
  echo "$RESPONSE" >&2
47
64
  exit 1
@@ -48,13 +48,15 @@ come back as numbers, dates as the sheet's formatted string.
48
48
  ## Failures
49
49
 
50
50
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
51
- when the owner has not connected Google Workspace (Settings → Integrations).
51
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
52
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
53
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
52
54
  A `403` with `reason: "google_error"` on a write means the file was not
53
55
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
54
56
 
55
57
  ## Choosing a Google account
56
58
 
57
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
59
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
58
60
 
59
61
  ```bash
60
62
  bash execute.sh --account work@company.com ...
@@ -51,13 +51,15 @@ the owner made outside Crewly needs the Sheets write scope (`403 google_error`).
51
51
  ## Failures
52
52
 
53
53
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
54
- when the owner has not connected Google Workspace (Settings → Integrations).
54
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
55
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
56
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
55
57
  A `403` with `reason: "google_error"` on a write means the file was not
56
58
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
57
59
 
58
60
  ## Choosing a Google account
59
61
 
60
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
62
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
61
63
 
62
64
  ```bash
63
65
  bash execute.sh --account work@company.com ...
@@ -56,13 +56,15 @@ For designed decks (brand templates, images, video) use the Canva skills.
56
56
  ## Failures
57
57
 
58
58
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
59
- when the owner has not connected Google Workspace (Settings → Integrations).
59
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
60
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
61
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
60
62
  A `403` with `reason: "google_error"` on a write means the file was not
61
63
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
62
64
 
63
65
  ## Choosing a Google account
64
66
 
65
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
67
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
66
68
 
67
69
  ```bash
68
70
  bash execute.sh --account work@company.com ...
@@ -44,13 +44,15 @@ bash execute.sh --id 1AbC…
44
44
  ## Failures
45
45
 
46
46
  `{"success":false,"reason":"not_connected","hint":"<connect URL>"}` (exit 1)
47
- when the owner has not connected Google Workspace (Settings → Integrations).
47
+ when the owner has not connected Google Workspace. Run the `google-connect` skill
48
+ to post the owner a one-tap card in Slack (never send them to Crewly settings or
49
+ the Connections page — they are usually on a phone). Manual fallback: https://crewlyai.com/portal/integrations/google.
48
50
  A `403` with `reason: "google_error"` on a write means the file was not
49
51
  created by Crewly — the grant only edits files Crewly made (`drive.file`).
50
52
 
51
53
  ## Choosing a Google account
52
54
 
53
- Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever you marked default on the Connections page). Name one explicitly when it matters:
55
+ Several Google accounts can be connected at once. Without `--account` the call uses the default one (the first you connected, or whichever the owner marked default). Name one explicitly when it matters:
54
56
 
55
57
  ```bash
56
58
  bash execute.sh --account work@company.com ...
@@ -4717,12 +4717,21 @@ export declare const GOOGLE_WORKSPACE_CONSTANTS: {
4717
4717
  * for want of a scope, or because the grant expired / was revoked.
4718
4718
  */
4719
4719
  readonly REAUTH: {
4720
- /** At most one card per product + Google account in this window (ms) */
4721
- readonly CARD_THROTTLE_MS: number;
4722
- /** How often to check whether the owner reconnected (ms) */
4720
+ /**
4721
+ * A card that went out less than this long ago is not repeated for the
4722
+ * same product + Google account (concurrent failures share one card);
4723
+ * after it, a new failure posts a fresh card unless the owner has
4724
+ * reconnected (ms)
4725
+ */
4726
+ readonly CARD_RESEND_AFTER_MS: number;
4727
+ /** First wait between looks at Cloud for the reconnect (ms) */
4723
4728
  readonly POLL_INTERVAL_MS: 30000;
4724
- /** Keep checking this long after the card's link expires (consent may still be finishing) (ms) */
4725
- readonly POLL_GRACE_MS: number;
4729
+ /** The wait grows by this factor after each look... */
4730
+ readonly POLL_BACKOFF_FACTOR: 1.5;
4731
+ /** ...up to this ceiling (ms) */
4732
+ readonly POLL_MAX_INTERVAL_MS: number;
4733
+ /** The card link never expires, so keep watching for the reconnect this long (ms) */
4734
+ readonly WATCH_MS: number;
4726
4735
  /** Give up posting the card after this long, so the skill call is not held (ms) */
4727
4736
  readonly POST_TIMEOUT_MS: 8000;
4728
4737
  };
@@ -4738,6 +4747,12 @@ export declare const GOOGLE_WORKSPACE_CONSTANTS: {
4738
4747
  readonly SLIDES_MAX_SLIDES: 60;
4739
4748
  /** Dashboard path the Cloud consent flow returns to */
4740
4749
  readonly SETTINGS_RETURN_PATH: "/connections?platform=google-workspace";
4750
+ /**
4751
+ * Cloud portal page that starts Google consent. It mints the consent
4752
+ * ticket when the owner opens it, so a link to it never expires and
4753
+ * carries no credential. Query: `products=<csv>&account=<email>&auto=1`.
4754
+ */
4755
+ readonly PORTAL_CONNECT_PATH: "/portal/integrations/google";
4741
4756
  /** Metadata headers requested on Gmail search hits */
4742
4757
  readonly GMAIL_SEARCH_HEADERS: readonly ["From", "To", "Subject", "Date"];
4743
4758
  /** RFC 2045 line width for base64 message bodies */
@@ -5664,7 +5679,7 @@ export declare const TICKET_CONSTANTS: {
5664
5679
  readonly DONE_REACTION: "white_check_mark";
5665
5680
  /**
5666
5681
  * Receipts are off (owner, 2026-09-24): tickets are Crewly's own record
5667
- * of the work — no 🎫 / ✅ / 「已记成 TKT-…」 in the owner's conversations.
5682
+ * of the work — no 🎫 / ✅ / "Recorded as TKT-…" in the owner's conversations.
5668
5683
  */
5669
5684
  readonly ENABLED: false;
5670
5685
  };
@@ -5741,7 +5756,7 @@ export declare const TICKET_CONSTANTS: {
5741
5756
  /** 「打回 <reason>」 — send it back; group 2 is the reason */
5742
5757
  readonly REJECT_PATTERN: RegExp;
5743
5758
  /** Reason recorded when 打回 came without one */
5744
- readonly REJECT_NO_REASON: "(未写原因)";
5759
+ readonly REJECT_NO_REASON: "(no reason given)";
5745
5760
  /** WorkItem title for a rework sent from the board */
5746
5761
  readonly REWORK_TITLE: (tkt: string) => string;
5747
5762
  };
@@ -6100,7 +6115,7 @@ export declare const ONBOARDING_CONSTANTS: {
6100
6115
  /** Longest first task accepted */
6101
6116
  readonly FIRST_TASK_MAX_LENGTH: 4000;
6102
6117
  /** First line of the message the orchestrator receives for a first task */
6103
- readonly FIRST_TASK_HEADER: "[初始设置 · 第一件事]";
6118
+ readonly FIRST_TASK_HEADER: "[Initial setup · first task]";
6104
6119
  /** Chat metadata `source` of a first task sent from setup */
6105
6120
  readonly FIRST_TASK_SOURCE: "onboarding_first_task";
6106
6121
  /** Query parameter that opens `/setup` at a step (e.g. `/setup?step=cloud`) */
@@ -6170,7 +6185,7 @@ export declare const BUNDLE_CONSTANTS: {
6170
6185
  /** Chat metadata `source` of a first-week task */
6171
6186
  readonly FIRST_WEEK_SOURCE: "bundle_first_week";
6172
6187
  /** First line of a first-week task the orchestrator receives */
6173
- readonly FIRST_WEEK_HEADER: "[成套方案 · 第一周]";
6188
+ readonly FIRST_WEEK_HEADER: "[Solution bundle · week one]";
6174
6189
  /** How often the backend delivers due first-week tasks and resumes waiting deployments */
6175
6190
  readonly TICK_INTERVAL_MS: number;
6176
6191
  /** How often `crewly deploy-bundle` polls a running backend's job */