crewly 1.20.264 → 1.20.266

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 (144) hide show
  1. package/config/skills/agent/core/docs-comment/SKILL.md +6 -3
  2. package/config/skills/agent/core/docs-comment/execute.sh +1 -1
  3. package/config/skills/agent/core/gmail-send/SKILL.md +4 -0
  4. package/config/skills/agent/core/gmail-send/execute.sh +1 -1
  5. package/config/skills/agent/core/gmail-send/execute.test.sh +11 -0
  6. package/config/skills/agent/core/slack-file/SKILL.md +53 -0
  7. package/config/skills/agent/core/slack-file/execute.sh +72 -0
  8. package/config/skills/agent/core/slack-file/execute.test.sh +34 -0
  9. package/dist/backend/backend/src/constants.d.ts +77 -0
  10. package/dist/backend/backend/src/constants.d.ts.map +1 -1
  11. package/dist/backend/backend/src/constants.js +77 -0
  12. package/dist/backend/backend/src/constants.js.map +1 -1
  13. package/dist/backend/backend/src/controllers/connector/connector.routes.d.ts.map +1 -1
  14. package/dist/backend/backend/src/controllers/connector/connector.routes.js +6 -1
  15. package/dist/backend/backend/src/controllers/connector/connector.routes.js.map +1 -1
  16. package/dist/backend/backend/src/controllers/connector/remote-mcp-proxy.controller.d.ts +69 -0
  17. package/dist/backend/backend/src/controllers/connector/remote-mcp-proxy.controller.d.ts.map +1 -0
  18. package/dist/backend/backend/src/controllers/connector/remote-mcp-proxy.controller.js +203 -0
  19. package/dist/backend/backend/src/controllers/connector/remote-mcp-proxy.controller.js.map +1 -0
  20. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.d.ts +16 -0
  21. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.d.ts.map +1 -1
  22. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.js +126 -5
  23. package/dist/backend/backend/src/controllers/connector/remote-mcp.controller.js.map +1 -1
  24. package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts +12 -1
  25. package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts.map +1 -1
  26. package/dist/backend/backend/src/controllers/google/google-connect-card.js +28 -10
  27. package/dist/backend/backend/src/controllers/google/google-connect-card.js.map +1 -1
  28. package/dist/backend/backend/src/controllers/google/google.controller.d.ts +26 -2
  29. package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
  30. package/dist/backend/backend/src/controllers/google/google.controller.js +123 -33
  31. package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
  32. package/dist/backend/backend/src/controllers/slack/slack.controller.d.ts.map +1 -1
  33. package/dist/backend/backend/src/controllers/slack/slack.controller.js +37 -0
  34. package/dist/backend/backend/src/controllers/slack/slack.controller.js.map +1 -1
  35. package/dist/backend/backend/src/index.d.ts.map +1 -1
  36. package/dist/backend/backend/src/index.js +15 -0
  37. package/dist/backend/backend/src/index.js.map +1 -1
  38. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  39. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js +2 -1
  40. package/dist/backend/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  41. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
  42. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +4 -3
  43. package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
  44. package/dist/backend/backend/src/services/connector/remote-mcp-auth-card.d.ts +43 -0
  45. package/dist/backend/backend/src/services/connector/remote-mcp-auth-card.d.ts.map +1 -0
  46. package/dist/backend/backend/src/services/connector/remote-mcp-auth-card.js +98 -0
  47. package/dist/backend/backend/src/services/connector/remote-mcp-auth-card.js.map +1 -0
  48. package/dist/backend/backend/src/services/connector/remote-mcp-auth.service.d.ts +277 -0
  49. package/dist/backend/backend/src/services/connector/remote-mcp-auth.service.d.ts.map +1 -0
  50. package/dist/backend/backend/src/services/connector/remote-mcp-auth.service.js +719 -0
  51. package/dist/backend/backend/src/services/connector/remote-mcp-auth.service.js.map +1 -0
  52. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.d.ts +29 -5
  53. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.d.ts.map +1 -1
  54. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.js +40 -12
  55. package/dist/backend/backend/src/services/connector/remote-mcp-launch.service.js.map +1 -1
  56. package/dist/backend/backend/src/services/connector/remote-mcp-oauth.d.ts +196 -0
  57. package/dist/backend/backend/src/services/connector/remote-mcp-oauth.d.ts.map +1 -0
  58. package/dist/backend/backend/src/services/connector/remote-mcp-oauth.js +351 -0
  59. package/dist/backend/backend/src/services/connector/remote-mcp-oauth.js.map +1 -0
  60. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.d.ts +3 -1
  61. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.d.ts.map +1 -1
  62. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.js +8 -0
  63. package/dist/backend/backend/src/services/connector/remote-mcp-probe.service.js.map +1 -1
  64. package/dist/backend/backend/src/services/core/credential-files.d.ts.map +1 -1
  65. package/dist/backend/backend/src/services/core/credential-files.js +2 -0
  66. package/dist/backend/backend/src/services/core/credential-files.js.map +1 -1
  67. package/dist/backend/backend/src/services/google/docs-comments.service.d.ts.map +1 -1
  68. package/dist/backend/backend/src/services/google/docs-comments.service.js +4 -1
  69. package/dist/backend/backend/src/services/google/docs-comments.service.js.map +1 -1
  70. package/dist/backend/backend/src/services/google/google-api.client.d.ts +16 -0
  71. package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
  72. package/dist/backend/backend/src/services/google/google-api.client.js +44 -0
  73. package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
  74. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts +159 -0
  75. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts.map +1 -0
  76. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js +283 -0
  77. package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js.map +1 -0
  78. package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts +71 -0
  79. package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts.map +1 -0
  80. package/dist/backend/backend/src/services/google/google-reauth.wiring.js +132 -0
  81. package/dist/backend/backend/src/services/google/google-reauth.wiring.js.map +1 -0
  82. package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts +28 -10
  83. package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
  84. package/dist/backend/backend/src/services/google/google-workspace-token.service.js +24 -11
  85. package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
  86. package/dist/backend/backend/src/services/slack/slack-file-fetch.service.d.ts +119 -0
  87. package/dist/backend/backend/src/services/slack/slack-file-fetch.service.d.ts.map +1 -0
  88. package/dist/backend/backend/src/services/slack/slack-file-fetch.service.js +415 -0
  89. package/dist/backend/backend/src/services/slack/slack-file-fetch.service.js.map +1 -0
  90. package/dist/backend/backend/src/services/slack/slack-file-ref.d.ts +69 -0
  91. package/dist/backend/backend/src/services/slack/slack-file-ref.d.ts.map +1 -0
  92. package/dist/backend/backend/src/services/slack/slack-file-ref.js +177 -0
  93. package/dist/backend/backend/src/services/slack/slack-file-ref.js.map +1 -0
  94. package/dist/backend/backend/src/services/slack/slack-initializer.d.ts.map +1 -1
  95. package/dist/backend/backend/src/services/slack/slack-initializer.js +16 -0
  96. package/dist/backend/backend/src/services/slack/slack-initializer.js.map +1 -1
  97. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts +15 -0
  98. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  99. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js +84 -1
  100. package/dist/backend/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  101. package/dist/backend/backend/src/services/slack/slack.service.d.ts +2 -1
  102. package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
  103. package/dist/backend/backend/src/services/slack/slack.service.js +3 -1
  104. package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
  105. package/dist/backend/backend/src/types/slack.types.d.ts +11 -0
  106. package/dist/backend/backend/src/types/slack.types.d.ts.map +1 -1
  107. package/dist/backend/backend/src/types/slack.types.js.map +1 -1
  108. package/dist/backend/build-info.json +2 -2
  109. package/dist/cli/backend/src/constants.d.ts +77 -0
  110. package/dist/cli/backend/src/constants.d.ts.map +1 -1
  111. package/dist/cli/backend/src/constants.js +77 -0
  112. package/dist/cli/backend/src/constants.js.map +1 -1
  113. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.d.ts.map +1 -1
  114. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js +2 -1
  115. package/dist/cli/backend/src/services/ai/prompt-modules/skills-reference.module.js.map +1 -1
  116. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.d.ts +29 -5
  117. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.d.ts.map +1 -1
  118. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.js +40 -12
  119. package/dist/cli/backend/src/services/connector/remote-mcp-launch.service.js.map +1 -1
  120. package/dist/cli/backend/src/services/core/credential-files.d.ts.map +1 -1
  121. package/dist/cli/backend/src/services/core/credential-files.js +2 -0
  122. package/dist/cli/backend/src/services/core/credential-files.js.map +1 -1
  123. package/dist/cli/backend/src/services/slack/slack-file-fetch.service.d.ts +119 -0
  124. package/dist/cli/backend/src/services/slack/slack-file-fetch.service.d.ts.map +1 -0
  125. package/dist/cli/backend/src/services/slack/slack-file-fetch.service.js +415 -0
  126. package/dist/cli/backend/src/services/slack/slack-file-fetch.service.js.map +1 -0
  127. package/dist/cli/backend/src/services/slack/slack-file-ref.d.ts +69 -0
  128. package/dist/cli/backend/src/services/slack/slack-file-ref.d.ts.map +1 -0
  129. package/dist/cli/backend/src/services/slack/slack-file-ref.js +177 -0
  130. package/dist/cli/backend/src/services/slack/slack-file-ref.js.map +1 -0
  131. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts +15 -0
  132. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.d.ts.map +1 -1
  133. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js +84 -1
  134. package/dist/cli/backend/src/services/slack/slack-orchestrator-bridge.js.map +1 -1
  135. package/dist/cli/backend/src/services/slack/slack.service.d.ts +2 -1
  136. package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
  137. package/dist/cli/backend/src/services/slack/slack.service.js +3 -1
  138. package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
  139. package/dist/cli/backend/src/types/slack.types.d.ts +11 -0
  140. package/dist/cli/backend/src/types/slack.types.d.ts.map +1 -1
  141. package/dist/cli/backend/src/types/slack.types.js.map +1 -1
  142. package/frontend/dist/assets/{index-83188f0b.js → index-7e5ebf78.js} +111 -111
  143. package/frontend/dist/index.html +1 -1
  144. package/package.json +1 -1
@@ -14,7 +14,7 @@ import { GOOGLE_PRODUCTS } from '../../constants.js';
14
14
  import { LoggerService } from '../../services/core/logger.service.js';
15
15
  const logger = LoggerService.getInstance().createComponentLogger('GoogleConnectCard');
16
16
  /** Human names for the products, for the card's first line. */
17
- const PRODUCT_LABELS = {
17
+ export const PRODUCT_LABELS = {
18
18
  gmail: 'Gmail',
19
19
  calendar: 'Google Calendar',
20
20
  drive: 'Google Drive',
@@ -22,14 +22,39 @@ const PRODUCT_LABELS = {
22
22
  /**
23
23
  * Build the card. Pure, so the wording is testable without Slack.
24
24
  *
25
+ * A reconnect (`reconnect`) replaces the generic "Needs access" with the
26
+ * reason the harness hit — "Gmail needs re-authorization to save drafts" —
27
+ * and names the Google account, because an owner with two Gmail logins has
28
+ * to know which one to pick.
29
+ *
25
30
  * @param product - Product needing consent
26
31
  * @param url - The ticket link behind the button
27
32
  * @param expiresAt - When the link stops working
33
+ * @param reconnect - Why a working connection needs the owner again, and for which account
28
34
  * @returns Block Kit blocks and the fallback text
29
35
  */
30
- export function buildConnectCard(product, url, expiresAt) {
36
+ export function buildConnectCard(product, url, expiresAt, reconnect) {
31
37
  const label = PRODUCT_LABELS[product] ?? product;
32
38
  const minutes = Math.max(1, Math.round((new Date(expiresAt).getTime() - Date.now()) / 60_000));
39
+ // Say both, because both surprise people: the link dies, and it is for
40
+ // them alone.
41
+ const note = `Only you can see this. The link works once, for about ${minutes} minutes.`;
42
+ if (reconnect) {
43
+ return {
44
+ text: reconnect.message,
45
+ blocks: [
46
+ {
47
+ type: 'section',
48
+ text: { type: 'mrkdwn', text: reconnect.message },
49
+ accessory: { type: 'button', text: { type: 'plain_text', text: 'Reconnect' }, url, style: 'primary' },
50
+ },
51
+ {
52
+ type: 'context',
53
+ elements: [{ type: 'mrkdwn', text: reconnect.account ? `${reconnect.account} · ${note}` : note }],
54
+ },
55
+ ],
56
+ };
57
+ }
33
58
  return {
34
59
  text: `${label} needs access — open the link to authorize Crewly.`,
35
60
  blocks: [
@@ -40,14 +65,7 @@ export function buildConnectCard(product, url, expiresAt) {
40
65
  },
41
66
  {
42
67
  type: 'context',
43
- elements: [
44
- {
45
- type: 'mrkdwn',
46
- // Say both, because both surprise people: the link dies, and it
47
- // is for them alone.
48
- text: `Only you can see this. The link works once, for about ${minutes} minutes.`,
49
- },
50
- ],
68
+ elements: [{ type: 'mrkdwn', text: note }],
51
69
  },
52
70
  ],
53
71
  };
@@ -1 +1 @@
1
- {"version":3,"file":"google-connect-card.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google-connect-card.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"google-connect-card.js","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google-connect-card.ts"],"names":[],"mappings":"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"}
@@ -20,6 +20,7 @@ import { DocsService } from '../../services/google/docs.service.js';
20
20
  import { DocsCommentsService } from '../../services/google/docs-comments.service.js';
21
21
  import { SheetsService } from '../../services/google/sheets.service.js';
22
22
  import { SlidesService } from '../../services/google/slides.service.js';
23
+ import { type ReauthNotifyResult, type ReauthTrigger } from '../../services/google/google-reauth-notifier.service.js';
23
24
  /** The services the handlers use; swappable for tests. */
24
25
  export interface GoogleControllerDeps {
25
26
  tokens: GoogleWorkspaceTokenService;
@@ -37,16 +38,39 @@ export interface GoogleControllerDeps {
37
38
  * @param next - Dependency set or null to rebuild lazily
38
39
  */
39
40
  export declare function setGoogleControllerDeps(next: GoogleControllerDeps | null): void;
41
+ /**
42
+ * The reconnect a failure calls for, if only the owner can fix it: the grant
43
+ * lacks a scope this call needs (Google 403 insufficient scopes), or Google
44
+ * no longer honours it (expired / revoked — Cloud said `grant_revoked`).
45
+ *
46
+ * @param err - The failure
47
+ * @param req - Incoming request (agent session, Google account)
48
+ * @returns The trigger, or null for any other failure
49
+ */
50
+ export declare function reauthTriggerFor(err: unknown, req: Request): ReauthTrigger | null;
51
+ /**
52
+ * The agent-facing next step after a reconnect card was (or was not) sent.
53
+ *
54
+ * The agent must not send the owner to the Connections page: the owner is
55
+ * usually on a phone, and the card already is the whole fix.
56
+ *
57
+ * @param trigger - The failure
58
+ * @param result - What the notifier did
59
+ * @returns The hint, or null to fall back to the generic one
60
+ */
61
+ export declare function reauthHint(trigger: ReauthTrigger, result: ReauthNotifyResult | null): string | null;
40
62
  /**
41
63
  * Answer a failure with the contract's `{ success:false, error, hint }`
42
64
  * shape. `not_connected` carries the consent URL as the hint; the other
43
- * codes get a one-line next step.
65
+ * codes get a one-line next step. A failure only the owner can fix (missing
66
+ * scope, expired grant) first posts the owner a one-tap reconnect card in
67
+ * Slack, and the hint says so.
44
68
  *
45
69
  * @param req - Incoming request (for the connect URL)
46
70
  * @param res - Response
47
71
  * @param err - The failure
48
72
  */
49
- export declare function sendGoogleError(req: Request, res: Response, err: unknown): void;
73
+ export declare function sendGoogleError(req: Request, res: Response, err: unknown): Promise<void>;
50
74
  /**
51
75
  * GET /api/google/status — `{ connected, cloudConnected, email?, scopes?, grantedAt? }`.
52
76
  *
@@ -1 +1 @@
1
- {"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"google.controller.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/controllers/google/google.controller.ts"],"names":[],"mappings":"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"}
@@ -26,6 +26,8 @@ import { SheetsService } from '../../services/google/sheets.service.js';
26
26
  import { SlidesService } from '../../services/google/slides.service.js';
27
27
  import { isOwnerCaller } from '../../middleware/caller-identity.middleware.js';
28
28
  import { readAgentSessionHeader } from '../../utils/agent-caller.utils.js';
29
+ import { GoogleReauthNotifier, } from '../../services/google/google-reauth-notifier.service.js';
30
+ import { PRODUCT_LABELS } from './google-connect-card.js';
29
31
  /** Who a held send is attributed to when the caller named no agent session. */
30
32
  const UNIDENTIFIED_SENDER = 'unidentified caller';
31
33
  const logger = LoggerService.getInstance().createComponentLogger('GoogleController');
@@ -171,22 +173,101 @@ function accountOf(req) {
171
173
  const raw = typeof req.query.account === 'string' ? req.query.account : req.get('X-Google-Account') ?? '';
172
174
  return raw.trim() || undefined;
173
175
  }
176
+ /**
177
+ * The reconnect a failure calls for, if only the owner can fix it: the grant
178
+ * lacks a scope this call needs (Google 403 insufficient scopes), or Google
179
+ * no longer honours it (expired / revoked — Cloud said `grant_revoked`).
180
+ *
181
+ * @param err - The failure
182
+ * @param req - Incoming request (agent session, Google account)
183
+ * @returns The trigger, or null for any other failure
184
+ */
185
+ export function reauthTriggerFor(err, req) {
186
+ if (!(err instanceof GoogleWorkspaceError))
187
+ return null;
188
+ const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
189
+ const product = err.details?.product;
190
+ if (!product)
191
+ return null;
192
+ let kind;
193
+ if (err.code === CODES.REAUTH_REQUIRED)
194
+ kind = 'missing_scope';
195
+ else if (err.code === CODES.NOT_CONNECTED && err.details?.reason === 'grant_revoked')
196
+ kind = 'expired';
197
+ else
198
+ return null;
199
+ const account = err.details?.account ?? accountOf(req);
200
+ // Only an agent's call: the owner at the dashboard is already looking at
201
+ // the Connections page, and a card in Slack would be noise.
202
+ const agentSession = isOwnerCaller(req) ? undefined : readAgentSessionHeader(req);
203
+ if (!agentSession)
204
+ return null;
205
+ return { product, kind, agentSession, ...(account ? { account } : {}) };
206
+ }
207
+ /**
208
+ * Ask the owner to reconnect, without holding the skill call for long.
209
+ *
210
+ * @param trigger - The failure
211
+ * @returns What happened, or null when no notifier is wired or it timed out
212
+ */
213
+ async function notifyReauth(trigger) {
214
+ const notifier = GoogleReauthNotifier.getInstance();
215
+ if (!notifier)
216
+ return null;
217
+ let timer;
218
+ const timeout = new Promise((resolve) => {
219
+ timer = setTimeout(() => resolve(null), GOOGLE_WORKSPACE_CONSTANTS.REAUTH.POST_TIMEOUT_MS);
220
+ });
221
+ try {
222
+ return await Promise.race([notifier.notify(trigger).catch(() => null), timeout]);
223
+ }
224
+ finally {
225
+ if (timer)
226
+ clearTimeout(timer);
227
+ }
228
+ }
229
+ /**
230
+ * The agent-facing next step after a reconnect card was (or was not) sent.
231
+ *
232
+ * The agent must not send the owner to the Connections page: the owner is
233
+ * usually on a phone, and the card already is the whole fix.
234
+ *
235
+ * @param trigger - The failure
236
+ * @param result - What the notifier did
237
+ * @returns The hint, or null to fall back to the generic one
238
+ */
239
+ export function reauthHint(trigger, result) {
240
+ const label = PRODUCT_LABELS[trigger.product] ?? trigger.product;
241
+ if (result?.status === 'posted') {
242
+ return `A reconnect link was sent to the owner in Slack. Tell them in one line that you need them to tap it (no need to mention Connections). You will get a message saying ${label} is reconnected — then retry.`;
243
+ }
244
+ if (result?.status === 'already_sent') {
245
+ return `A reconnect link was already sent to the owner in Slack at ${result.sentAt}; no new one is sent before ${result.nextCardAfter}. Do not ask again — you will get a message saying ${label} is reconnected, then retry.`;
246
+ }
247
+ return null;
248
+ }
174
249
  /**
175
250
  * Answer a failure with the contract's `{ success:false, error, hint }`
176
251
  * shape. `not_connected` carries the consent URL as the hint; the other
177
- * codes get a one-line next step.
252
+ * codes get a one-line next step. A failure only the owner can fix (missing
253
+ * scope, expired grant) first posts the owner a one-tap reconnect card in
254
+ * Slack, and the hint says so.
178
255
  *
179
256
  * @param req - Incoming request (for the connect URL)
180
257
  * @param res - Response
181
258
  * @param err - The failure
182
259
  */
183
- export function sendGoogleError(req, res, err) {
260
+ export async function sendGoogleError(req, res, err) {
184
261
  const CODES = GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES;
185
262
  if (err instanceof GoogleWorkspaceError) {
263
+ const trigger = reauthTriggerFor(err, req);
264
+ const reauth = trigger ? await notifyReauth(trigger) : null;
265
+ const reauthText = trigger ? reauthHint(trigger, reauth) : null;
186
266
  let hint;
187
267
  switch (err.code) {
188
268
  case CODES.NOT_CONNECTED:
189
- hint = connectUrlOrNull(req)
269
+ hint = reauthText
270
+ ?? connectUrlOrNull(req)
190
271
  ?? 'Sign in to Crewly Cloud (Settings → Cloud & devices), then connect Google Workspace under Connections.';
191
272
  break;
192
273
  case CODES.NOT_LOGGED_IN:
@@ -198,10 +279,13 @@ export function sendGoogleError(req, res, err) {
198
279
  case CODES.VALIDATION:
199
280
  hint = 'Fix the request and retry.';
200
281
  break;
201
- case CODES.REAUTH_REQUIRED:
282
+ case CODES.REAUTH_REQUIRED: {
202
283
  // Owner-away: the only step is one tap on the Slack card.
203
- hint = 'Ask the owner to reconnect Google Drive: run the google-connect skill with --product drive. It posts a one-tap card in Slack; nothing to do on this machine.';
284
+ const product = err.details?.product ?? 'drive';
285
+ hint = reauthText
286
+ ?? `Ask the owner to reconnect ${PRODUCT_LABELS[product] ?? product}: run the google-connect skill with --product ${product}. It posts a one-tap card in Slack; nothing to do on this machine.`;
204
287
  break;
288
+ }
205
289
  case PEOPLE_CONSTANTS.NOT_PERMITTED_CODE:
206
290
  hint = PEOPLE_CONSTANTS.NOT_PERMITTED_HINT;
207
291
  break;
@@ -210,7 +294,13 @@ export function sendGoogleError(req, res, err) {
210
294
  ? 'The Google token was rejected; retry once — the cache has been cleared.'
211
295
  : 'Google or Crewly Cloud failed; retry later.';
212
296
  }
213
- res.status(err.status).json({ success: false, error: err.code, message: err.message, hint });
297
+ res.status(err.status).json({
298
+ success: false,
299
+ error: err.code,
300
+ message: err.message,
301
+ hint,
302
+ ...(reauthText ? { reconnectLinkSent: true } : {}),
303
+ });
214
304
  return;
215
305
  }
216
306
  const message = err instanceof Error ? err.message : String(err);
@@ -251,7 +341,7 @@ export async function getStatus(req, res) {
251
341
  res.json({ success: true, data });
252
342
  }
253
343
  catch (err) {
254
- sendGoogleError(req, res, err);
344
+ await sendGoogleError(req, res, err);
255
345
  }
256
346
  }
257
347
  /**
@@ -267,7 +357,7 @@ export async function getConnectUrl(req, res) {
267
357
  res.json({ success: true, data: { url } });
268
358
  }
269
359
  catch (err) {
270
- sendGoogleError(req, res, err);
360
+ await sendGoogleError(req, res, err);
271
361
  }
272
362
  }
273
363
  /**
@@ -283,7 +373,7 @@ export async function disconnect(req, res) {
283
373
  res.json({ success: true, data });
284
374
  }
285
375
  catch (err) {
286
- sendGoogleError(req, res, err);
376
+ await sendGoogleError(req, res, err);
287
377
  }
288
378
  }
289
379
  /**
@@ -305,7 +395,7 @@ export async function setDefaultAccount(req, res) {
305
395
  res.json({ success: true, data });
306
396
  }
307
397
  catch (err) {
308
- sendGoogleError(req, res, err);
398
+ await sendGoogleError(req, res, err);
309
399
  }
310
400
  }
311
401
  /**
@@ -335,7 +425,7 @@ export async function gmailSearch(req, res) {
335
425
  res.json({ success: true, data: { query, count: messages.length, messages } });
336
426
  }
337
427
  catch (err) {
338
- sendGoogleError(req, res, err);
428
+ await sendGoogleError(req, res, err);
339
429
  }
340
430
  }
341
431
  /**
@@ -350,7 +440,7 @@ export async function gmailRead(req, res) {
350
440
  res.json({ success: true, data: message });
351
441
  }
352
442
  catch (err) {
353
- sendGoogleError(req, res, err);
443
+ await sendGoogleError(req, res, err);
354
444
  }
355
445
  }
356
446
  /**
@@ -424,7 +514,7 @@ export async function gmailSend(req, res) {
424
514
  res.json({ success: true, data: sent });
425
515
  }
426
516
  catch (err) {
427
- sendGoogleError(req, res, err);
517
+ await sendGoogleError(req, res, err);
428
518
  }
429
519
  }
430
520
  /**
@@ -444,7 +534,7 @@ export async function calendarList(req, res) {
444
534
  res.json({ success: true, data: { count: events.length, events } });
445
535
  }
446
536
  catch (err) {
447
- sendGoogleError(req, res, err);
537
+ await sendGoogleError(req, res, err);
448
538
  }
449
539
  }
450
540
  /**
@@ -474,7 +564,7 @@ export async function calendarCreate(req, res) {
474
564
  res.json({ success: true, data: event });
475
565
  }
476
566
  catch (err) {
477
- sendGoogleError(req, res, err);
567
+ await sendGoogleError(req, res, err);
478
568
  }
479
569
  }
480
570
  // ---------------------------------------------------------------------------
@@ -497,7 +587,7 @@ export async function driveSearch(req, res) {
497
587
  res.json({ success: true, data: { count: files.length, files } });
498
588
  }
499
589
  catch (err) {
500
- sendGoogleError(req, res, err);
590
+ await sendGoogleError(req, res, err);
501
591
  }
502
592
  }
503
593
  /**
@@ -511,7 +601,7 @@ export async function driveGet(req, res) {
511
601
  res.json({ success: true, data: await depsForRequest(req).drive.get(String(req.params.id ?? '')) });
512
602
  }
513
603
  catch (err) {
514
- sendGoogleError(req, res, err);
604
+ await sendGoogleError(req, res, err);
515
605
  }
516
606
  }
517
607
  /**
@@ -525,7 +615,7 @@ export async function driveContent(req, res) {
525
615
  res.json({ success: true, data: await depsForRequest(req).drive.readContent(String(req.params.id ?? '')) });
526
616
  }
527
617
  catch (err) {
528
- sendGoogleError(req, res, err);
618
+ await sendGoogleError(req, res, err);
529
619
  }
530
620
  }
531
621
  /**
@@ -549,7 +639,7 @@ export async function driveUpload(req, res) {
549
639
  res.json({ success: true, data: file });
550
640
  }
551
641
  catch (err) {
552
- sendGoogleError(req, res, err);
642
+ await sendGoogleError(req, res, err);
553
643
  }
554
644
  }
555
645
  // ---------------------------------------------------------------------------
@@ -566,7 +656,7 @@ export async function docsRead(req, res) {
566
656
  res.json({ success: true, data: await depsForRequest(req).docs.read(String(req.params.id ?? '')) });
567
657
  }
568
658
  catch (err) {
569
- sendGoogleError(req, res, err);
659
+ await sendGoogleError(req, res, err);
570
660
  }
571
661
  }
572
662
  /**
@@ -583,7 +673,7 @@ export async function docsCreate(req, res) {
583
673
  res.json({ success: true, data: doc });
584
674
  }
585
675
  catch (err) {
586
- sendGoogleError(req, res, err);
676
+ await sendGoogleError(req, res, err);
587
677
  }
588
678
  }
589
679
  /**
@@ -598,7 +688,7 @@ export async function docsAppend(req, res) {
598
688
  res.json({ success: true, data: await depsForRequest(req).docs.append(String(req.params.id ?? ''), String(body.text ?? '')) });
599
689
  }
600
690
  catch (err) {
601
- sendGoogleError(req, res, err);
691
+ await sendGoogleError(req, res, err);
602
692
  }
603
693
  }
604
694
  /**
@@ -614,7 +704,7 @@ export async function docsCommentsList(req, res) {
614
704
  res.json({ success: true, data: await depsForRequest(req).docComments.list(String(req.params.id ?? ''), { includeResolved }) });
615
705
  }
616
706
  catch (err) {
617
- sendGoogleError(req, res, err);
707
+ await sendGoogleError(req, res, err);
618
708
  }
619
709
  }
620
710
  /**
@@ -632,7 +722,7 @@ export async function docsCommentsAdd(req, res) {
632
722
  res.json({ success: true, data });
633
723
  }
634
724
  catch (err) {
635
- sendGoogleError(req, res, err);
725
+ await sendGoogleError(req, res, err);
636
726
  }
637
727
  }
638
728
  /**
@@ -649,7 +739,7 @@ export async function docsCommentsReply(req, res) {
649
739
  res.json({ success: true, data });
650
740
  }
651
741
  catch (err) {
652
- sendGoogleError(req, res, err);
742
+ await sendGoogleError(req, res, err);
653
743
  }
654
744
  }
655
745
  /**
@@ -667,7 +757,7 @@ export async function docsCommentsResolve(req, res) {
667
757
  res.json({ success: true, data });
668
758
  }
669
759
  catch (err) {
670
- sendGoogleError(req, res, err);
760
+ await sendGoogleError(req, res, err);
671
761
  }
672
762
  }
673
763
  // ---------------------------------------------------------------------------
@@ -684,7 +774,7 @@ export async function sheetsInfo(req, res) {
684
774
  res.json({ success: true, data: await depsForRequest(req).sheets.info(String(req.params.id ?? '')) });
685
775
  }
686
776
  catch (err) {
687
- sendGoogleError(req, res, err);
777
+ await sendGoogleError(req, res, err);
688
778
  }
689
779
  }
690
780
  /**
@@ -698,7 +788,7 @@ export async function sheetsRead(req, res) {
698
788
  res.json({ success: true, data: await depsForRequest(req).sheets.read(String(req.params.id ?? ''), q(req, 'range') || undefined) });
699
789
  }
700
790
  catch (err) {
701
- sendGoogleError(req, res, err);
791
+ await sendGoogleError(req, res, err);
702
792
  }
703
793
  }
704
794
  /**
@@ -715,7 +805,7 @@ export async function sheetsCreate(req, res) {
715
805
  res.json({ success: true, data: info });
716
806
  }
717
807
  catch (err) {
718
- sendGoogleError(req, res, err);
808
+ await sendGoogleError(req, res, err);
719
809
  }
720
810
  }
721
811
  /**
@@ -733,7 +823,7 @@ export async function sheetsWrite(req, res) {
733
823
  res.json({ success: true, data: { mode: body.mode === 'update' ? 'update' : 'append', ...result } });
734
824
  }
735
825
  catch (err) {
736
- sendGoogleError(req, res, err);
826
+ await sendGoogleError(req, res, err);
737
827
  }
738
828
  }
739
829
  // ---------------------------------------------------------------------------
@@ -750,7 +840,7 @@ export async function slidesRead(req, res) {
750
840
  res.json({ success: true, data: await depsForRequest(req).slides.read(String(req.params.id ?? '')) });
751
841
  }
752
842
  catch (err) {
753
- sendGoogleError(req, res, err);
843
+ await sendGoogleError(req, res, err);
754
844
  }
755
845
  }
756
846
  /**
@@ -767,7 +857,7 @@ export async function slidesCreate(req, res) {
767
857
  res.json({ success: true, data: deck });
768
858
  }
769
859
  catch (err) {
770
- sendGoogleError(req, res, err);
860
+ await sendGoogleError(req, res, err);
771
861
  }
772
862
  }
773
863
  /**
@@ -848,7 +938,7 @@ export async function gmailResolveHeld(req, res) {
848
938
  res.json({ success: true, data: sent });
849
939
  }
850
940
  catch (err) {
851
- sendGoogleError(req, res, err);
941
+ await sendGoogleError(req, res, err);
852
942
  }
853
943
  }
854
944
  //# sourceMappingURL=google.controller.js.map