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
@@ -0,0 +1,177 @@
1
+ /**
2
+ * Slack file references — turn whatever an agent was handed (a file id, a
3
+ * file permalink, a download URL, a message link) into the ids Slack's API
4
+ * needs.
5
+ *
6
+ * Kept in step with the Cloud copy in
7
+ * `crewly-services/auth/src/slack-file-ref.ts`; both sides parse
8
+ * the same links.
9
+ *
10
+ * @module services/slack/slack-file-ref
11
+ */
12
+ const FILE_ID = /^F[A-Z0-9]{6,20}$/;
13
+ const USER_ID = /^[UWB][A-Z0-9]{6,20}$/;
14
+ const TEAM_ID = /^[TE][A-Z0-9]{6,20}$/;
15
+ const CHANNEL_ID = /^[CDG][A-Z0-9]{6,20}$/;
16
+ const TEAM_FILE = /^([TE][A-Z0-9]{6,20})-(F[A-Z0-9]{6,20})(?:-[A-Za-z0-9]+)?$/;
17
+ /** Every Slack file / message link inside free text (`<url|label>` and bare). */
18
+ const LINK_IN_TEXT = /https:\/\/(?:[a-z0-9-]+\.)*(?:slack\.com|slack-files\.com)\/(?:files(?:-pri|-tmb)?|archives)\/[^\s<>|"')\]]+/gi;
19
+ /**
20
+ * `p1696771234567890` → `1696771234.567890`.
21
+ *
22
+ * @param segment - The `p…` path segment of a message link
23
+ * @returns The Slack ts, or undefined when the segment is not one
24
+ */
25
+ function tsFromPermalinkSegment(segment) {
26
+ const m = /^p(\d{10})(\d{6})$/.exec(segment);
27
+ return m ? `${m[1]}.${m[2]}` : undefined;
28
+ }
29
+ /**
30
+ * Parse a file reference.
31
+ *
32
+ * Accepted:
33
+ * - `F0123ABCD` (a bare file id)
34
+ * - `https://<ws>.slack.com/files/<user>/<FILE>/<name>` (file permalink)
35
+ * - `https://files.slack.com/files-pri/<TEAM>-<FILE>/<name>` (+ `/download/`)
36
+ * - `https://files.slack.com/files-tmb/<TEAM>-<FILE>-<hash>/<name>`
37
+ * - `https://slack-files.com/<TEAM>-<FILE>-<secret>` (public permalink)
38
+ * - `https://<ws>.slack.com/archives/<CHANNEL>/p<ts>[?thread_ts=…]` (a message carrying files)
39
+ * - any of the above wrapped Slack-style as `<url|label>`
40
+ *
41
+ * @param input - What the agent passed
42
+ * @returns The parsed reference, or null when it is not a Slack file reference
43
+ */
44
+ export function parseSlackFileRef(input) {
45
+ let raw = (input ?? '').trim();
46
+ if (!raw)
47
+ return null;
48
+ // Slack mrkdwn link: <https://…|label>
49
+ const angle = /^<([^|>]+)(?:\|[^>]*)?>$/.exec(raw);
50
+ if (angle)
51
+ raw = angle[1].trim();
52
+ if (FILE_ID.test(raw))
53
+ return { fileId: raw };
54
+ let url;
55
+ try {
56
+ url = new URL(raw);
57
+ }
58
+ catch {
59
+ return null;
60
+ }
61
+ if (url.protocol !== 'https:')
62
+ return null;
63
+ const host = url.hostname.toLowerCase();
64
+ const isSlackHost = host === 'slack.com' || host.endsWith('.slack.com');
65
+ if (!isSlackHost && host !== 'slack-files.com')
66
+ return null;
67
+ const parts = url.pathname.split('/').filter(Boolean).map((p) => decodeURIComponent(p));
68
+ if (host === 'slack-files.com') {
69
+ const m = parts[0] ? TEAM_FILE.exec(parts[0]) : null;
70
+ return m ? { slackTeamId: m[1], fileId: m[2] } : null;
71
+ }
72
+ const workspaceHost = isWorkspaceHost(host) ? host : undefined;
73
+ if (parts[0] === 'files-pri' || parts[0] === 'files-tmb') {
74
+ const m = parts[1] ? TEAM_FILE.exec(parts[1]) : null;
75
+ return m ? { slackTeamId: m[1], fileId: m[2] } : null;
76
+ }
77
+ if (parts[0] === 'files') {
78
+ // /files/<user>/<FILE>[/<name>]
79
+ const user = parts[1];
80
+ const file = parts[2];
81
+ if (file && FILE_ID.test(file)) {
82
+ return {
83
+ fileId: file,
84
+ ...(user && USER_ID.test(user) ? { uploaderUserId: user } : {}),
85
+ ...(workspaceHost ? { workspaceHost } : {}),
86
+ ...(teamFromQuery(url) ? { slackTeamId: teamFromQuery(url) } : {}),
87
+ };
88
+ }
89
+ return null;
90
+ }
91
+ if (parts[0] === 'archives') {
92
+ const channel = parts[1];
93
+ const ts = parts[2] ? tsFromPermalinkSegment(parts[2]) : undefined;
94
+ if (!channel || !CHANNEL_ID.test(channel) || !ts)
95
+ return null;
96
+ const threadTs = url.searchParams.get('thread_ts') ?? undefined;
97
+ return {
98
+ channelId: channel,
99
+ messageTs: ts,
100
+ ...(threadTs && /^\d{10}\.\d{6}$/.test(threadTs) ? { threadTs } : {}),
101
+ ...(workspaceHost ? { workspaceHost } : {}),
102
+ };
103
+ }
104
+ return null;
105
+ }
106
+ /**
107
+ * Slack file and message links in a piece of text (deduplicated, in order).
108
+ *
109
+ * @param text - Message text
110
+ * @returns Links that {@link parseSlackFileRef} accepts
111
+ */
112
+ export function findSlackFileLinks(text) {
113
+ const out = [];
114
+ for (const m of (text ?? '').matchAll(LINK_IN_TEXT)) {
115
+ const link = m[0].replace(/[.,;:!?]+$/, '');
116
+ if (!out.includes(link) && parseSlackFileRef(link))
117
+ out.push(link);
118
+ }
119
+ return out;
120
+ }
121
+ /** `acme.slack.com` is a workspace; `files.slack.com`, `app.slack.com`, `slack.com` are not. */
122
+ function isWorkspaceHost(host) {
123
+ if (!host.endsWith('.slack.com'))
124
+ return false;
125
+ const sub = host.slice(0, -'.slack.com'.length);
126
+ return !!sub && !['files', 'app', 'api', 'www', 'edgeapi', 'status'].includes(sub);
127
+ }
128
+ function teamFromQuery(url) {
129
+ const t = url.searchParams.get('origin_team') ?? url.searchParams.get('team');
130
+ return t && TEAM_ID.test(t) ? t : undefined;
131
+ }
132
+ /** Hosts a Slack file download may be served from (redirects included). */
133
+ export function isSlackDownloadHost(host) {
134
+ const h = host.toLowerCase();
135
+ return (h === 'slack.com' ||
136
+ h.endsWith('.slack.com') ||
137
+ h === 'slack-edge.com' ||
138
+ h.endsWith('.slack-edge.com') ||
139
+ h === 'slack-files.com' ||
140
+ h.endsWith('.slack-files.com'));
141
+ }
142
+ /** Mimetypes / extensions treated as text (returned as text, previewed). */
143
+ const TEXT_MIMES = new Set([
144
+ 'application/json',
145
+ 'application/xml',
146
+ 'application/javascript',
147
+ 'application/x-javascript',
148
+ 'application/typescript',
149
+ 'application/x-yaml',
150
+ 'application/yaml',
151
+ 'application/x-sh',
152
+ 'application/sql',
153
+ 'application/csv',
154
+ ]);
155
+ const TEXT_EXTENSIONS = new Set([
156
+ 'txt', 'md', 'markdown', 'csv', 'tsv', 'json', 'jsonl', 'yaml', 'yml', 'xml', 'html', 'htm',
157
+ 'js', 'ts', 'tsx', 'jsx', 'py', 'sh', 'sql', 'log', 'ini', 'toml', 'css', 'srt', 'vtt',
158
+ ]);
159
+ /**
160
+ * Whether a file is text (so it can be handed back as a string).
161
+ *
162
+ * @param mimetype - Slack mimetype
163
+ * @param name - File name
164
+ * @returns True for text-like files
165
+ */
166
+ export function isTextFile(mimetype, name) {
167
+ const mime = (mimetype ?? '').toLowerCase().split(';')[0].trim();
168
+ if (mime.startsWith('text/'))
169
+ return true;
170
+ if (TEXT_MIMES.has(mime))
171
+ return true;
172
+ const ext = (name ?? '').toLowerCase().split('.').pop() ?? '';
173
+ return !!ext && (name ?? '').includes('.') && TEXT_EXTENSIONS.has(ext);
174
+ }
175
+ /** Exposed for tests. */
176
+ export const SLACK_ID_PATTERNS = { FILE_ID, USER_ID, TEAM_ID, CHANNEL_ID };
177
+ //# sourceMappingURL=slack-file-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slack-file-ref.js","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-file-ref.ts"],"names":[],"mappings":"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"}
@@ -418,6 +418,21 @@ export declare class SlackOrchestratorBridge extends EventEmitter {
418
418
  * @param nonImageFiles - Non-image SlackFile objects to download
419
419
  */
420
420
  private downloadMessageFiles;
421
+ /**
422
+ * Fetch Slack files linked in a message's text, like attachments.
423
+ *
424
+ * Ella posted `longform-en.md` in #pro-crewly-marketing and handed it to
425
+ * Rex on another machine by link; Rex's bot was not in that channel and
426
+ * he asked her to paste the text (2026-10-08). The link is now fetched
427
+ * here — local bots first, then Cloud, which holds every bot of the
428
+ * account — so the hand-off carries the file. Best effort and capped:
429
+ * file links only (message links are left to `slack-file get`), at most
430
+ * {@link SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_PER_MESSAGE}, each under
431
+ * {@link SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_BYTES}. Never throws.
432
+ *
433
+ * @param message - Inbound message; `linkedFiles` / `linkedFileFailures` are set on it
434
+ */
435
+ fetchLinkedFiles(message: SlackIncomingMessage): Promise<void>;
421
436
  /**
422
437
  * Enrich message text with file path references so agents
423
438
  * can read them via their file-reading tools (Claude Code Read, Gemini @file).
@@ -1 +1 @@
1
- {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"slack-orchestrator-bridge.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/slack/slack-orchestrator-bridge.ts"],"names":[],"mappings":"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"}
@@ -26,7 +26,7 @@ import { ContentApprovalService } from '../onboarding/content-approval.service.j
26
26
  import { getSlackImageService } from './slack-image.service.js';
27
27
  import { getOwnerMessageWatchdog } from '../messaging/owner-message-watchdog.service.js';
28
28
  import { isOwnerAuthored } from './slack-auto-working.service.js';
29
- import { ORCHESTRATOR_SESSION_NAME, MESSAGE_QUEUE_CONSTANTS, SLACK_IMAGE_CONSTANTS, SLACK_FILE_DOWNLOAD_CONSTANTS, SLACK_BRIDGE_CONSTANTS, AUDITOR_SCHEDULER_CONSTANTS, THREAD_STATUS_CONSTANTS, OWNER_EVIDENCE_METADATA } from '../../constants.js';
29
+ import { ORCHESTRATOR_SESSION_NAME, MESSAGE_QUEUE_CONSTANTS, SLACK_IMAGE_CONSTANTS, SLACK_FILE_DOWNLOAD_CONSTANTS, SLACK_FILE_FETCH_CONSTANTS, SLACK_BRIDGE_CONSTANTS, AUDITOR_SCHEDULER_CONSTANTS, THREAD_STATUS_CONSTANTS, OWNER_EVIDENCE_METADATA } from '../../constants.js';
30
30
  import { LoggerService } from '../core/logger.service.js';
31
31
  import { CROSS_MACHINE_PREFIX } from '../../types/cross-machine.types.js';
32
32
  import { getCrossMachineMessageService } from './cross-machine-message.service.js';
@@ -350,6 +350,9 @@ export class SlackOrchestratorBridge extends EventEmitter {
350
350
  await this.downloadMessageFiles(message, nonImageFiles);
351
351
  }
352
352
  }
353
+ // Slack files LINKED in the text — a colleague on another machine
354
+ // pointing at a file in a channel this machine's bots are not in.
355
+ await this.fetchLinkedFiles(message);
353
356
  // What the Slack thread actually says — including posts by agents on
354
357
  // other machines, which Cloud never forwards here. Prompt context only;
355
358
  // read in the background, awaited right before a prompt is built.
@@ -1585,6 +1588,76 @@ Just type naturally to chat with the orchestrator!`;
1585
1588
  }
1586
1589
  }
1587
1590
  }
1591
+ /**
1592
+ * Fetch Slack files linked in a message's text, like attachments.
1593
+ *
1594
+ * Ella posted `longform-en.md` in #pro-crewly-marketing and handed it to
1595
+ * Rex on another machine by link; Rex's bot was not in that channel and
1596
+ * he asked her to paste the text (2026-10-08). The link is now fetched
1597
+ * here — local bots first, then Cloud, which holds every bot of the
1598
+ * account — so the hand-off carries the file. Best effort and capped:
1599
+ * file links only (message links are left to `slack-file get`), at most
1600
+ * {@link SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_PER_MESSAGE}, each under
1601
+ * {@link SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_BYTES}. Never throws.
1602
+ *
1603
+ * @param message - Inbound message; `linkedFiles` / `linkedFileFailures` are set on it
1604
+ */
1605
+ async fetchLinkedFiles(message) {
1606
+ try {
1607
+ const { findSlackFileLinks, parseSlackFileRef } = await import('./slack-file-ref.js');
1608
+ const attachedIds = new Set((message.files ?? []).map((f) => f.id));
1609
+ const links = findSlackFileLinks(message.text || '')
1610
+ .filter((link) => {
1611
+ const ref = parseSlackFileRef(link);
1612
+ return !!ref?.fileId && !attachedIds.has(ref.fileId);
1613
+ })
1614
+ .slice(0, SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_PER_MESSAGE);
1615
+ if (links.length === 0)
1616
+ return;
1617
+ const { getSlackFileFetchService } = await import('./slack-file-fetch.service.js');
1618
+ const service = await getSlackFileFetchService();
1619
+ const fetched = [];
1620
+ const failures = [];
1621
+ for (const link of links) {
1622
+ try {
1623
+ const { meta, localPath } = await service.get(link, {
1624
+ ...(message.agentSession ? { requesterAgent: message.agentSession } : {}),
1625
+ maxBytes: SLACK_FILE_FETCH_CONSTANTS.MAX_LINKED_BYTES,
1626
+ });
1627
+ let extractedText;
1628
+ if (meta.isText) {
1629
+ const text = await fs.readFile(localPath, 'utf8').catch(() => '');
1630
+ const max = SLACK_FILE_DOWNLOAD_CONSTANTS.MAX_EXTRACTED_TEXT_LENGTH;
1631
+ extractedText = text.length > max ? `${text.slice(0, max)}\n[... truncated — read the whole file at ${localPath}]` : text;
1632
+ }
1633
+ else if (SLACK_FILE_DOWNLOAD_CONSTANTS.EXTRACTABLE_MIMES.includes(meta.mimetype)) {
1634
+ extractedText = await this.extractPdfText(localPath, meta.name);
1635
+ }
1636
+ fetched.push({
1637
+ id: meta.id,
1638
+ name: meta.name,
1639
+ mimetype: meta.mimetype,
1640
+ localPath,
1641
+ size: meta.size,
1642
+ permalink: meta.permalink ?? link,
1643
+ ...(extractedText ? { extractedText } : {}),
1644
+ });
1645
+ }
1646
+ catch (err) {
1647
+ const reason = err instanceof Error ? err.message : String(err);
1648
+ this.logger.info('Linked Slack file not fetched', { reason });
1649
+ failures.push({ link, reason });
1650
+ }
1651
+ }
1652
+ if (fetched.length > 0)
1653
+ message.linkedFiles = fetched;
1654
+ if (failures.length > 0)
1655
+ message.linkedFileFailures = failures;
1656
+ }
1657
+ catch (err) {
1658
+ this.logger.warn('Linked Slack files skipped', { error: err instanceof Error ? err.message : String(err) });
1659
+ }
1660
+ }
1588
1661
  /**
1589
1662
  * Enrich message text with file path references so agents
1590
1663
  * can read them via their file-reading tools (Claude Code Read, Gemini @file).
@@ -1615,6 +1688,16 @@ Just type naturally to chat with the orchestrator!`;
1615
1688
  text += `\n${hint}`;
1616
1689
  }
1617
1690
  }
1691
+ for (const file of message.linkedFiles ?? []) {
1692
+ const sizeStr = file.size < 1024 ? `${file.size}B` : `${Math.round(file.size / 1024)}KB`;
1693
+ text += `\n[Slack File (linked): ${file.localPath} (${file.name}, ${file.mimetype}, ${sizeStr})]`;
1694
+ if (file.extractedText) {
1695
+ text += `\n--- Content of ${file.name} ---\n${file.extractedText}\n--- End of ${file.name} ---`;
1696
+ }
1697
+ }
1698
+ for (const f of message.linkedFileFailures ?? []) {
1699
+ text += `\n[Slack: the linked file ${f.link} could not be fetched automatically (${f.reason}). Try \`slack-file get ${f.link}\` before asking anyone to paste it.]`;
1700
+ }
1618
1701
  // A download that failed left no trace in the text at all, so the agent
1619
1702
  // saw "have a look at this" with nothing to look at and answered about
1620
1703
  // the previous topic instead of saying it could not see the attachment