crewly 1.20.263 → 1.20.265
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/skills/agent/core/app-data/SKILL.md +12 -1
- package/config/skills/agent/core/app-data/execute.sh +3 -3
- package/config/skills/agent/core/app-data/execute.test.sh +4 -1
- package/config/skills/agent/core/docs-comment/SKILL.md +6 -3
- package/config/skills/agent/core/docs-comment/execute.sh +1 -1
- package/config/skills/agent/core/gmail-send/SKILL.md +4 -0
- package/config/skills/agent/core/gmail-send/execute.sh +1 -1
- package/config/skills/agent/core/gmail-send/execute.test.sh +11 -0
- package/config/skills/agent/core/publish-app/SKILL.md +1 -1
- package/dist/backend/backend/src/constants.d.ts +21 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +21 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.js +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.routes.d.ts +1 -1
- package/dist/backend/backend/src/controllers/apps/apps.routes.js +1 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts +12 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google-connect-card.js +28 -10
- package/dist/backend/backend/src/controllers/google/google-connect-card.js.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts +26 -2
- package/dist/backend/backend/src/controllers/google/google.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/google/google.controller.js +123 -33
- package/dist/backend/backend/src/controllers/google/google.controller.js.map +1 -1
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +10 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/services/apps/app-collaborators.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/apps/app-collaborators.service.js +2 -1
- package/dist/backend/backend/src/services/apps/app-collaborators.service.js.map +1 -1
- package/dist/backend/backend/src/services/apps/app-wake.service.d.ts +11 -2
- package/dist/backend/backend/src/services/apps/app-wake.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/apps/app-wake.service.js +29 -0
- package/dist/backend/backend/src/services/apps/app-wake.service.js.map +1 -1
- package/dist/backend/backend/src/services/apps/apps.service.d.ts +16 -6
- package/dist/backend/backend/src/services/apps/apps.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/apps/apps.service.js +47 -13
- package/dist/backend/backend/src/services/apps/apps.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.js +4 -1
- package/dist/backend/backend/src/services/google/docs-comments.service.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.d.ts +16 -0
- package/dist/backend/backend/src/services/google/google-api.client.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-api.client.js +44 -0
- package/dist/backend/backend/src/services/google/google-api.client.js.map +1 -1
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts +159 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js +283 -0
- package/dist/backend/backend/src/services/google/google-reauth-notifier.service.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts +71 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.d.ts.map +1 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.js +132 -0
- package/dist/backend/backend/src/services/google/google-reauth.wiring.js.map +1 -0
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts +28 -10
- package/dist/backend/backend/src/services/google/google-workspace-token.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js +24 -11
- package/dist/backend/backend/src/services/google/google-workspace-token.service.js.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/backend/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/slack/slack.service.js +3 -1
- package/dist/backend/backend/src/services/slack/slack.service.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +21 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +21 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts +2 -1
- package/dist/cli/backend/src/services/slack/slack.service.d.ts.map +1 -1
- package/dist/cli/backend/src/services/slack/slack.service.js +3 -1
- package/dist/cli/backend/src/services/slack/slack.service.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google reconnect cards — the harness asks the owner, not the agent.
|
|
3
|
+
*
|
|
4
|
+
* 2026-10-08: the Personal Assistant tried to save a reply as a Gmail draft,
|
|
5
|
+
* Google answered 403 "insufficient authentication scopes" (no grant carried
|
|
6
|
+
* `gmail.compose`), and the agent told the owner to "re-authorize Gmail in
|
|
7
|
+
* Crewly Connections" — a page the owner cannot reach from a phone. The
|
|
8
|
+
* same dead end follows an expired or revoked grant.
|
|
9
|
+
*
|
|
10
|
+
* So when a Google call fails because the grant is too narrow or no longer
|
|
11
|
+
* honoured, this posts the existing one-tap connect card (single-use ticket,
|
|
12
|
+
* `google-connect-card.ts`) to the owner in Slack — where the agent is
|
|
13
|
+
* working if that is known, else the owner's DM with that agent — at most
|
|
14
|
+
* once per product and Google account per
|
|
15
|
+
* {@link GOOGLE_WORKSPACE_CONSTANTS.REAUTH.CARD_THROTTLE_MS}. It then watches
|
|
16
|
+
* Cloud until the reconnect lands and tells the waiting agents to retry.
|
|
17
|
+
*
|
|
18
|
+
* Everything that touches Slack, Cloud or an agent is injected, so the
|
|
19
|
+
* machine the failure happened on is the one that posts — any machine with
|
|
20
|
+
* Slack and a Cloud session works the same.
|
|
21
|
+
*
|
|
22
|
+
* @module services/google/google-reauth-notifier.service
|
|
23
|
+
*/
|
|
24
|
+
import { GOOGLE_WORKSPACE_CONSTANTS } from '../../constants.js';
|
|
25
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
26
|
+
import { buildConnectCard, PRODUCT_LABELS } from '../../controllers/google/google-connect-card.js';
|
|
27
|
+
const logger = LoggerService.getInstance().createComponentLogger('GoogleReauthNotifier');
|
|
28
|
+
/**
|
|
29
|
+
* The scope a `missing_scope` failure is about, per product — what a
|
|
30
|
+
* reconnect must have added for the retry to work.
|
|
31
|
+
*/
|
|
32
|
+
const EXTRA_SCOPE = {
|
|
33
|
+
gmail: GOOGLE_WORKSPACE_CONSTANTS.GMAIL_COMPOSE_SCOPE,
|
|
34
|
+
drive: GOOGLE_WORKSPACE_CONSTANTS.DRIVE_FULL_SCOPE,
|
|
35
|
+
};
|
|
36
|
+
/** What the missing scope lets the agent do, for the card. */
|
|
37
|
+
const EXTRA_PURPOSE = {
|
|
38
|
+
gmail: 'save drafts',
|
|
39
|
+
drive: 'comment on documents',
|
|
40
|
+
};
|
|
41
|
+
/** What the agent retries once the scope is there. */
|
|
42
|
+
const EXTRA_RETRY = {
|
|
43
|
+
gmail: 'your draft',
|
|
44
|
+
drive: 'your comment',
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* The card's first line. Owner-facing, so it says what broke and that it is
|
|
48
|
+
* quick — not which scope is missing.
|
|
49
|
+
*
|
|
50
|
+
* @param trigger - The failure
|
|
51
|
+
* @returns Card message
|
|
52
|
+
*/
|
|
53
|
+
export function reauthCardMessage(trigger) {
|
|
54
|
+
const label = PRODUCT_LABELS[trigger.product] ?? trigger.product;
|
|
55
|
+
if (trigger.kind === 'expired')
|
|
56
|
+
return `${label} access expired — tap to reconnect.`;
|
|
57
|
+
const purpose = EXTRA_PURPOSE[trigger.product];
|
|
58
|
+
return `${label} needs re-authorization${purpose ? ` to ${purpose}` : ''} (missing permission). Tap to reconnect — takes 30 seconds on your phone.`;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* What the agent is told once the owner has reconnected.
|
|
62
|
+
*
|
|
63
|
+
* @param trigger - The failure
|
|
64
|
+
* @returns Notice text
|
|
65
|
+
*/
|
|
66
|
+
export function reauthRetryNotice(trigger) {
|
|
67
|
+
const label = PRODUCT_LABELS[trigger.product] ?? trigger.product;
|
|
68
|
+
const what = trigger.kind === 'missing_scope' ? EXTRA_RETRY[trigger.product] : undefined;
|
|
69
|
+
return `[GOOGLE] ${label} reconnected — retry ${what ?? 'what failed'}.`;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Whether a status from Cloud shows the failure fixed.
|
|
73
|
+
*
|
|
74
|
+
* - `missing_scope`: the account is connected for the product and now
|
|
75
|
+
* carries the scope the call lacked (or, for a product with no known
|
|
76
|
+
* extra, reports nothing missing).
|
|
77
|
+
* - `expired`: the account is connected for the product again (Cloud
|
|
78
|
+
* deleted the dead grant, so being there at all is new).
|
|
79
|
+
*
|
|
80
|
+
* @param status - Cloud's connections
|
|
81
|
+
* @param trigger - The failure
|
|
82
|
+
* @returns True when the agent can retry
|
|
83
|
+
*/
|
|
84
|
+
export function isReconnected(status, trigger) {
|
|
85
|
+
if (!status.connected)
|
|
86
|
+
return false;
|
|
87
|
+
const account = trigger.account?.toLowerCase();
|
|
88
|
+
const connection = account
|
|
89
|
+
? status.connections.find((c) => c.email.toLowerCase() === account)
|
|
90
|
+
: status.connections.find((c) => c.isDefault) ?? status.connections[0];
|
|
91
|
+
if (!connection || !connection.products.includes(trigger.product))
|
|
92
|
+
return false;
|
|
93
|
+
if (trigger.kind === 'expired')
|
|
94
|
+
return true;
|
|
95
|
+
const needed = EXTRA_SCOPE[trigger.product];
|
|
96
|
+
if (needed)
|
|
97
|
+
return connection.scopes.includes(needed);
|
|
98
|
+
return (connection.missingScopes ?? []).length === 0;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Throttle key: one card per product and Google account.
|
|
102
|
+
*
|
|
103
|
+
* @param trigger - The failure
|
|
104
|
+
* @returns Key
|
|
105
|
+
*/
|
|
106
|
+
function keyOf(trigger) {
|
|
107
|
+
return `${trigger.product}\u0000${(trigger.account ?? '').toLowerCase()}`;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Posts reconnect cards and tells agents when to retry.
|
|
111
|
+
*/
|
|
112
|
+
export class GoogleReauthNotifier {
|
|
113
|
+
deps;
|
|
114
|
+
static instance = null;
|
|
115
|
+
pending = new Map();
|
|
116
|
+
/** Posts on the wire, so two failures at once post one card */
|
|
117
|
+
posting = new Map();
|
|
118
|
+
now;
|
|
119
|
+
setTimer;
|
|
120
|
+
/**
|
|
121
|
+
* @param deps - Collaborators
|
|
122
|
+
*/
|
|
123
|
+
constructor(deps) {
|
|
124
|
+
this.deps = deps;
|
|
125
|
+
this.now = deps.now ?? (() => Date.now());
|
|
126
|
+
this.setTimer =
|
|
127
|
+
deps.setTimer ??
|
|
128
|
+
((fn, ms) => {
|
|
129
|
+
const t = setTimeout(fn, ms);
|
|
130
|
+
t.unref?.();
|
|
131
|
+
return { cancel: () => clearTimeout(t) };
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
/** The wired instance, or null when Slack is not set up on this machine. */
|
|
135
|
+
static getInstance() {
|
|
136
|
+
return GoogleReauthNotifier.instance;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Install (or, with null, remove) the process-wide instance.
|
|
140
|
+
*
|
|
141
|
+
* @param next - Notifier
|
|
142
|
+
*/
|
|
143
|
+
static setInstance(next) {
|
|
144
|
+
GoogleReauthNotifier.instance?.stop();
|
|
145
|
+
GoogleReauthNotifier.instance = next;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Ask the owner to reconnect, unless a card for this product and account
|
|
149
|
+
* went out within the throttle window — then only remember that this
|
|
150
|
+
* agent is waiting too.
|
|
151
|
+
*
|
|
152
|
+
* @param trigger - The failure
|
|
153
|
+
* @returns What happened, for the agent's hint
|
|
154
|
+
*/
|
|
155
|
+
async notify(trigger) {
|
|
156
|
+
const key = keyOf(trigger);
|
|
157
|
+
const nowMs = this.now();
|
|
158
|
+
const existing = this.pending.get(key);
|
|
159
|
+
if (existing && nowMs - existing.sentAtMs < GOOGLE_WORKSPACE_CONSTANTS.REAUTH.CARD_THROTTLE_MS) {
|
|
160
|
+
if (trigger.agentSession)
|
|
161
|
+
existing.waiters.add(trigger.agentSession);
|
|
162
|
+
// The watch on the card may have run out; someone is waiting again, so
|
|
163
|
+
// look for a reconnect made some other way (the Connections page).
|
|
164
|
+
if (!existing.timer) {
|
|
165
|
+
existing.watchUntilMs = nowMs + GOOGLE_WORKSPACE_CONSTANTS.REAUTH.POLL_GRACE_MS;
|
|
166
|
+
this.schedule(key, existing);
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
status: 'already_sent',
|
|
170
|
+
sentAt: new Date(existing.sentAtMs).toISOString(),
|
|
171
|
+
nextCardAfter: new Date(existing.sentAtMs + GOOGLE_WORKSPACE_CONSTANTS.REAUTH.CARD_THROTTLE_MS).toISOString(),
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
const inFlight = this.posting.get(key);
|
|
175
|
+
if (inFlight) {
|
|
176
|
+
const result = await inFlight;
|
|
177
|
+
if (trigger.agentSession)
|
|
178
|
+
this.pending.get(key)?.waiters.add(trigger.agentSession);
|
|
179
|
+
return result;
|
|
180
|
+
}
|
|
181
|
+
const task = this.post(key, trigger).finally(() => this.posting.delete(key));
|
|
182
|
+
this.posting.set(key, task);
|
|
183
|
+
return task;
|
|
184
|
+
}
|
|
185
|
+
/** Stop every watch (shutdown, tests). */
|
|
186
|
+
stop() {
|
|
187
|
+
for (const p of this.pending.values())
|
|
188
|
+
p.timer?.cancel();
|
|
189
|
+
this.pending.clear();
|
|
190
|
+
}
|
|
191
|
+
async post(key, trigger) {
|
|
192
|
+
const owner = this.deps.ownerUserId();
|
|
193
|
+
if (!owner)
|
|
194
|
+
return { status: 'unavailable', why: 'the owner is not known on Slack' };
|
|
195
|
+
const place = await this.deps.placeFor(trigger.agentSession, owner).catch(() => null);
|
|
196
|
+
if (!place)
|
|
197
|
+
return { status: 'unavailable', why: 'no Slack conversation with the owner from this machine' };
|
|
198
|
+
let link;
|
|
199
|
+
try {
|
|
200
|
+
link = await this.deps.connectUrl({
|
|
201
|
+
products: [trigger.product],
|
|
202
|
+
...(trigger.account ? { email: trigger.account } : {}),
|
|
203
|
+
slackUserId: owner,
|
|
204
|
+
slackChannelId: place.slackChannelId,
|
|
205
|
+
...(place.threadTs ? { slackThreadTs: place.threadTs } : {}),
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
catch (err) {
|
|
209
|
+
const why = err instanceof Error ? err.message : String(err);
|
|
210
|
+
logger.warn('Could not mint a Google reconnect link', { product: trigger.product, error: why });
|
|
211
|
+
return { status: 'unavailable', why: `Crewly Cloud did not issue a link (${why})` };
|
|
212
|
+
}
|
|
213
|
+
const card = buildConnectCard(trigger.product, link.url, link.expiresAt, {
|
|
214
|
+
message: reauthCardMessage(trigger),
|
|
215
|
+
...(trigger.account ? { account: trigger.account } : {}),
|
|
216
|
+
});
|
|
217
|
+
const posted = await this.deps.postCard(place, owner, card.text, card.blocks).catch(() => false);
|
|
218
|
+
if (!posted)
|
|
219
|
+
return { status: 'unavailable', why: 'Slack refused the card' };
|
|
220
|
+
const sentAtMs = this.now();
|
|
221
|
+
const expiresMs = Date.parse(link.expiresAt);
|
|
222
|
+
const pending = {
|
|
223
|
+
trigger,
|
|
224
|
+
sentAtMs,
|
|
225
|
+
watchUntilMs: (Number.isFinite(expiresMs) ? expiresMs : sentAtMs) + GOOGLE_WORKSPACE_CONSTANTS.REAUTH.POLL_GRACE_MS,
|
|
226
|
+
waiters: new Set(trigger.agentSession ? [trigger.agentSession] : []),
|
|
227
|
+
};
|
|
228
|
+
this.pending.get(key)?.timer?.cancel();
|
|
229
|
+
this.pending.set(key, pending);
|
|
230
|
+
this.schedule(key, pending);
|
|
231
|
+
logger.info('Posted a Google reconnect card', {
|
|
232
|
+
product: trigger.product,
|
|
233
|
+
kind: trigger.kind,
|
|
234
|
+
account: trigger.account,
|
|
235
|
+
slackChannelId: place.slackChannelId,
|
|
236
|
+
threaded: !!place.threadTs,
|
|
237
|
+
agentSession: trigger.agentSession,
|
|
238
|
+
});
|
|
239
|
+
return { status: 'posted', expiresAt: link.expiresAt };
|
|
240
|
+
}
|
|
241
|
+
/** Check again after the poll interval, until the watch window closes. */
|
|
242
|
+
schedule(key, pending) {
|
|
243
|
+
pending.timer = this.setTimer(() => {
|
|
244
|
+
void this.check(key, pending);
|
|
245
|
+
}, GOOGLE_WORKSPACE_CONSTANTS.REAUTH.POLL_INTERVAL_MS);
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* One look at Cloud. On success the waiting agents are told to retry and
|
|
249
|
+
* the throttle is lifted, so a later, different failure gets its own card.
|
|
250
|
+
*/
|
|
251
|
+
async check(key, pending) {
|
|
252
|
+
if (this.pending.get(key) !== pending)
|
|
253
|
+
return;
|
|
254
|
+
let fixed = false;
|
|
255
|
+
try {
|
|
256
|
+
fixed = isReconnected(await this.deps.status(), pending.trigger);
|
|
257
|
+
}
|
|
258
|
+
catch (err) {
|
|
259
|
+
logger.debug('Could not read Google status while waiting for a reconnect', {
|
|
260
|
+
error: err instanceof Error ? err.message : String(err),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
if (!fixed) {
|
|
264
|
+
if (this.now() < pending.watchUntilMs)
|
|
265
|
+
this.schedule(key, pending);
|
|
266
|
+
else
|
|
267
|
+
pending.timer = undefined;
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.pending.delete(key);
|
|
271
|
+
this.deps.clearTokenCache(pending.trigger.account);
|
|
272
|
+
const notice = reauthRetryNotice(pending.trigger);
|
|
273
|
+
for (const session of pending.waiters) {
|
|
274
|
+
await this.deps.tellAgent(session, notice).catch(() => false);
|
|
275
|
+
}
|
|
276
|
+
logger.info('Google reconnected; told the waiting agents to retry', {
|
|
277
|
+
product: pending.trigger.product,
|
|
278
|
+
account: pending.trigger.account,
|
|
279
|
+
agents: [...pending.waiters],
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
//# sourceMappingURL=google-reauth-notifier.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-reauth-notifier.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-reauth-notifier.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google reconnect cards — wiring with the real Slack, Cloud and agents.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from the notifier so its rules (throttle, wording, when a
|
|
5
|
+
* reconnect counts) are testable without Slack. Everything here runs on the
|
|
6
|
+
* machine where the Google call failed: its Slack transport posts the card,
|
|
7
|
+
* its Cloud session mints the ticket, its agents are told to retry. That is
|
|
8
|
+
* the same on every machine, so an agent on a second machine (the Personal
|
|
9
|
+
* Assistant on iriss-air, 2026-10-08) gets the same card as one on the main
|
|
10
|
+
* Mac.
|
|
11
|
+
*
|
|
12
|
+
* @module services/google/google-reauth.wiring
|
|
13
|
+
*/
|
|
14
|
+
import type { SlackBlock } from '../../types/slack.types.js';
|
|
15
|
+
import { GoogleReauthNotifier, type ReauthNotifierDeps } from './google-reauth-notifier.service.js';
|
|
16
|
+
/** The Slack calls the wiring makes (a slice of SlackService). */
|
|
17
|
+
export interface ReauthSlackApi {
|
|
18
|
+
getOwnerUserId?: (() => string | null) | null;
|
|
19
|
+
openDirectMessage: (userId: string, botToken?: string) => Promise<string>;
|
|
20
|
+
sendMessage: (message: {
|
|
21
|
+
channelId: string;
|
|
22
|
+
text: string;
|
|
23
|
+
blocks?: SlackBlock[];
|
|
24
|
+
threadTs?: string;
|
|
25
|
+
botToken?: string;
|
|
26
|
+
skipChatV2Mirror?: boolean;
|
|
27
|
+
}) => Promise<string>;
|
|
28
|
+
sendEphemeral: (channelId: string, userId: string, text: string, blocks?: unknown[], botToken?: string, threadTs?: string) => Promise<boolean>;
|
|
29
|
+
}
|
|
30
|
+
/** What the wiring needs from the rest of the process. */
|
|
31
|
+
export interface ReauthWiringInput {
|
|
32
|
+
/** Deliver text to an agent; wakes it when needed */
|
|
33
|
+
sendToAgent: (session: string, text: string) => Promise<boolean>;
|
|
34
|
+
/** Seams for tests; default to the real singletons */
|
|
35
|
+
slack?: () => ReauthSlackApi;
|
|
36
|
+
/** The Slack place of the agent's current work */
|
|
37
|
+
workDestination?: (session: string) => Promise<{
|
|
38
|
+
slackChannelId: string;
|
|
39
|
+
threadTs?: string;
|
|
40
|
+
} | null>;
|
|
41
|
+
/** The owner↔agent Slack DM, when there is one */
|
|
42
|
+
agentDm?: (session: string) => {
|
|
43
|
+
slackChannelId: string;
|
|
44
|
+
} | null;
|
|
45
|
+
/** The agent's own installed bot token */
|
|
46
|
+
agentBotToken?: (session: string) => string | undefined;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* A Slack DM channel id. DMs are private to the owner and the bot, so a
|
|
50
|
+
* card there can be an ordinary message — which, unlike an ephemeral one,
|
|
51
|
+
* reaches the owner's phone as a notification and survives a reload.
|
|
52
|
+
*
|
|
53
|
+
* @param channelId - Slack channel id
|
|
54
|
+
* @returns True for `D…`
|
|
55
|
+
*/
|
|
56
|
+
export declare function isDirectMessage(channelId: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Build the notifier's collaborators.
|
|
59
|
+
*
|
|
60
|
+
* @param input - Process hooks and test seams
|
|
61
|
+
* @returns Notifier deps
|
|
62
|
+
*/
|
|
63
|
+
export declare function createReauthNotifierDeps(input: ReauthWiringInput): ReauthNotifierDeps;
|
|
64
|
+
/**
|
|
65
|
+
* Install the process-wide notifier. Called once Slack is up.
|
|
66
|
+
*
|
|
67
|
+
* @param input - Process hooks
|
|
68
|
+
* @returns The notifier
|
|
69
|
+
*/
|
|
70
|
+
export declare function startGoogleReauthNotifier(input: ReauthWiringInput): GoogleReauthNotifier;
|
|
71
|
+
//# sourceMappingURL=google-reauth.wiring.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-reauth.wiring.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-reauth.wiring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAM7D,OAAO,EAAE,oBAAoB,EAAE,KAAK,kBAAkB,EAAoB,MAAM,qCAAqC,CAAC;AAItH,kEAAkE;AAClE,MAAM,WAAW,cAAc;IAC7B,cAAc,CAAC,EAAE,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;IAC9C,iBAAiB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC1E,WAAW,EAAE,CAAC,OAAO,EAAE;QACrB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,UAAU,EAAE,CAAC;QACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;KAC5B,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtB,aAAa,EAAE,CACb,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,OAAO,EAAE,EAClB,QAAQ,CAAC,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,KACd,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,0DAA0D;AAC1D,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjE,sDAAsD;IACtD,KAAK,CAAC,EAAE,MAAM,cAAc,CAAC;IAC7B,kDAAkD;IAClD,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,cAAc,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;IACrG,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACjE,0CAA0C;IAC1C,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CACzD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE1D;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,iBAAiB,GAAG,kBAAkB,CAkFrF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,iBAAiB,GAAG,oBAAoB,CAKxF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google reconnect cards — wiring with the real Slack, Cloud and agents.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from the notifier so its rules (throttle, wording, when a
|
|
5
|
+
* reconnect counts) are testable without Slack. Everything here runs on the
|
|
6
|
+
* machine where the Google call failed: its Slack transport posts the card,
|
|
7
|
+
* its Cloud session mints the ticket, its agents are told to retry. That is
|
|
8
|
+
* the same on every machine, so an agent on a second machine (the Personal
|
|
9
|
+
* Assistant on iriss-air, 2026-10-08) gets the same card as one on the main
|
|
10
|
+
* Mac.
|
|
11
|
+
*
|
|
12
|
+
* @module services/google/google-reauth.wiring
|
|
13
|
+
*/
|
|
14
|
+
import { LoggerService } from '../core/logger.service.js';
|
|
15
|
+
import { getSlackService } from '../slack/slack.service.js';
|
|
16
|
+
import { getSlackAgentDmService } from '../slack/slack-agent-dm.service.js';
|
|
17
|
+
import { getSlackAgentIdentityService } from '../slack/slack-agent-identity.service.js';
|
|
18
|
+
import { GoogleWorkspaceTokenService } from './google-workspace-token.service.js';
|
|
19
|
+
import { GoogleReauthNotifier } from './google-reauth-notifier.service.js';
|
|
20
|
+
const logger = LoggerService.getInstance().createComponentLogger('GoogleReauthWiring');
|
|
21
|
+
/**
|
|
22
|
+
* A Slack DM channel id. DMs are private to the owner and the bot, so a
|
|
23
|
+
* card there can be an ordinary message — which, unlike an ephemeral one,
|
|
24
|
+
* reaches the owner's phone as a notification and survives a reload.
|
|
25
|
+
*
|
|
26
|
+
* @param channelId - Slack channel id
|
|
27
|
+
* @returns True for `D…`
|
|
28
|
+
*/
|
|
29
|
+
export function isDirectMessage(channelId) {
|
|
30
|
+
return channelId.startsWith('D');
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Build the notifier's collaborators.
|
|
34
|
+
*
|
|
35
|
+
* @param input - Process hooks and test seams
|
|
36
|
+
* @returns Notifier deps
|
|
37
|
+
*/
|
|
38
|
+
export function createReauthNotifierDeps(input) {
|
|
39
|
+
const slack = input.slack ?? (() => getSlackService());
|
|
40
|
+
const botTokenOf = input.agentBotToken ?? ((session) => getSlackAgentIdentityService()?.getInstalled(session)?.botToken);
|
|
41
|
+
const agentDm = input.agentDm ??
|
|
42
|
+
((session) => {
|
|
43
|
+
const link = getSlackAgentDmService()?.findByAgentSession(session);
|
|
44
|
+
return link ? { slackChannelId: link.slackChannelId } : null;
|
|
45
|
+
});
|
|
46
|
+
const workDestination = input.workDestination ??
|
|
47
|
+
(async (session) => {
|
|
48
|
+
const { resolveAgentSlackDestination } = await import('../orc/work-item-destination.wiring.js');
|
|
49
|
+
return resolveAgentSlackDestination(session);
|
|
50
|
+
});
|
|
51
|
+
const tokens = () => GoogleWorkspaceTokenService.getInstance();
|
|
52
|
+
/** The owner's DM with this bot. */
|
|
53
|
+
const ownerDm = async (owner, botToken) => {
|
|
54
|
+
const id = await slack().openDirectMessage(owner, botToken).catch(() => null);
|
|
55
|
+
return id ? { slackChannelId: id, ...(botToken ? { botToken } : {}) } : null;
|
|
56
|
+
};
|
|
57
|
+
/** One post attempt; a DM gets an ordinary message, a channel an ephemeral one. */
|
|
58
|
+
const postOnce = async (place, owner, text, blocks, botToken) => {
|
|
59
|
+
if (isDirectMessage(place.slackChannelId)) {
|
|
60
|
+
const ts = await slack()
|
|
61
|
+
.sendMessage({
|
|
62
|
+
channelId: place.slackChannelId,
|
|
63
|
+
text,
|
|
64
|
+
blocks: blocks,
|
|
65
|
+
...(place.threadTs ? { threadTs: place.threadTs } : {}),
|
|
66
|
+
...(botToken ? { botToken } : {}),
|
|
67
|
+
// A card is not conversation: keep it out of the chat mirror.
|
|
68
|
+
skipChatV2Mirror: true,
|
|
69
|
+
})
|
|
70
|
+
.catch(() => '');
|
|
71
|
+
return !!ts;
|
|
72
|
+
}
|
|
73
|
+
return slack()
|
|
74
|
+
.sendEphemeral(place.slackChannelId, owner, text, blocks, botToken, place.threadTs)
|
|
75
|
+
.catch(() => false);
|
|
76
|
+
};
|
|
77
|
+
return {
|
|
78
|
+
ownerUserId: () => slack().getOwnerUserId?.() ?? null,
|
|
79
|
+
placeFor: async (session, owner) => {
|
|
80
|
+
const botToken = session ? botTokenOf(session) : undefined;
|
|
81
|
+
if (session) {
|
|
82
|
+
// Where the agent is working — but only a conversation, not a bare
|
|
83
|
+
// team channel: a card at the top of #team would reach nobody.
|
|
84
|
+
const work = await workDestination(session).catch(() => null);
|
|
85
|
+
if (work?.slackChannelId && (work.threadTs || isDirectMessage(work.slackChannelId))) {
|
|
86
|
+
return {
|
|
87
|
+
slackChannelId: work.slackChannelId,
|
|
88
|
+
...(work.threadTs ? { threadTs: work.threadTs } : {}),
|
|
89
|
+
...(botToken ? { botToken } : {}),
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
const dm = agentDm(session);
|
|
93
|
+
if (dm)
|
|
94
|
+
return { slackChannelId: dm.slackChannelId, ...(botToken ? { botToken } : {}) };
|
|
95
|
+
}
|
|
96
|
+
return ownerDm(owner, botToken);
|
|
97
|
+
},
|
|
98
|
+
connectUrl: (args) => tokens().buildSlackConnectUrl(args),
|
|
99
|
+
postCard: async (place, owner, text, blocks) => {
|
|
100
|
+
if (await postOnce(place, owner, text, blocks, place.botToken))
|
|
101
|
+
return true;
|
|
102
|
+
// The agent's own bot may not be in that conversation; the shared bot
|
|
103
|
+
// usually is.
|
|
104
|
+
if (place.botToken && (await postOnce(place, owner, text, blocks)))
|
|
105
|
+
return true;
|
|
106
|
+
if (isDirectMessage(place.slackChannelId))
|
|
107
|
+
return false;
|
|
108
|
+
// A channel thread refused it: the owner's DM still reaches the phone.
|
|
109
|
+
const dm = await ownerDm(owner, place.botToken);
|
|
110
|
+
if (dm && (await postOnce(dm, owner, text, blocks, dm.botToken)))
|
|
111
|
+
return true;
|
|
112
|
+
logger.warn('Could not post the Google reconnect card anywhere', { slackChannelId: place.slackChannelId });
|
|
113
|
+
return false;
|
|
114
|
+
},
|
|
115
|
+
status: () => tokens().status(),
|
|
116
|
+
clearTokenCache: (account) => tokens().clearCache(account),
|
|
117
|
+
tellAgent: input.sendToAgent,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Install the process-wide notifier. Called once Slack is up.
|
|
122
|
+
*
|
|
123
|
+
* @param input - Process hooks
|
|
124
|
+
* @returns The notifier
|
|
125
|
+
*/
|
|
126
|
+
export function startGoogleReauthNotifier(input) {
|
|
127
|
+
const notifier = new GoogleReauthNotifier(createReauthNotifierDeps(input));
|
|
128
|
+
GoogleReauthNotifier.setInstance(notifier);
|
|
129
|
+
logger.info('Google reconnect cards started');
|
|
130
|
+
return notifier;
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=google-reauth.wiring.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-reauth.wiring.js","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-reauth.wiring.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,12 @@ export interface GoogleConnection extends GrantOwnership {
|
|
|
33
33
|
/** Products the grant covers, derived by Cloud from the granted scopes. */
|
|
34
34
|
products: GoogleProduct[];
|
|
35
35
|
scopes: string[];
|
|
36
|
+
/**
|
|
37
|
+
* Optional scopes the grant lacks for products it covers (Cloud auth >=
|
|
38
|
+
* 1.10.9; absent on an older Cloud). E.g. `gmail.compose`: reads and sends
|
|
39
|
+
* work, drafts need a reconnect.
|
|
40
|
+
*/
|
|
41
|
+
missingScopes?: string[];
|
|
36
42
|
grantedAt: string;
|
|
37
43
|
/** True for the account used when a caller names none. */
|
|
38
44
|
isDefault: boolean;
|
|
@@ -55,18 +61,26 @@ export interface GoogleWorkspaceStatus {
|
|
|
55
61
|
* {@link GOOGLE_WORKSPACE_CONSTANTS.ERROR_CODES} (or `http_<n>` for anything
|
|
56
62
|
* unmapped), so the controller and the skills can branch without parsing text.
|
|
57
63
|
*/
|
|
64
|
+
/** Structured context on a {@link GoogleWorkspaceError}. */
|
|
65
|
+
export interface GoogleWorkspaceErrorDetails {
|
|
66
|
+
/** For `not_permitted`: who owns the grant (issue #968) */
|
|
67
|
+
authorizedBy?: string;
|
|
68
|
+
/**
|
|
69
|
+
* Why, when the code alone is not enough: `insufficient_scope` (Google
|
|
70
|
+
* 403, the grant lacks a scope this call needs) or `grant_revoked` (the
|
|
71
|
+
* refresh token is dead — expired or revoked; Cloud deleted the grant).
|
|
72
|
+
*/
|
|
73
|
+
reason?: 'insufficient_scope' | 'grant_revoked';
|
|
74
|
+
/** Product the failing call was for */
|
|
75
|
+
product?: GoogleProduct;
|
|
76
|
+
/** Google account the failing call acted as, when known */
|
|
77
|
+
account?: string;
|
|
78
|
+
}
|
|
58
79
|
export declare class GoogleWorkspaceError extends Error {
|
|
59
80
|
readonly status: number;
|
|
60
81
|
readonly code: string;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
authorizedBy?: string;
|
|
64
|
-
} | undefined;
|
|
65
|
-
constructor(status: number, code: string, message: string,
|
|
66
|
-
/** For `not_permitted`: who owns the grant (issue #968) */
|
|
67
|
-
details?: {
|
|
68
|
-
authorizedBy?: string;
|
|
69
|
-
} | undefined);
|
|
82
|
+
readonly details?: GoogleWorkspaceErrorDetails | undefined;
|
|
83
|
+
constructor(status: number, code: string, message: string, details?: GoogleWorkspaceErrorDetails | undefined);
|
|
70
84
|
}
|
|
71
85
|
/**
|
|
72
86
|
* Map a Cloud workspace-endpoint failure to the status/code this instance
|
|
@@ -79,7 +93,9 @@ export declare class GoogleWorkspaceError extends Error {
|
|
|
79
93
|
* @param message - Human message from Cloud's body, if any
|
|
80
94
|
* @returns The error to throw
|
|
81
95
|
*/
|
|
82
|
-
export declare function mapCloudFailure(httpStatus: number, code: string | undefined, message: string | undefined
|
|
96
|
+
export declare function mapCloudFailure(httpStatus: number, code: string | undefined, message: string | undefined, details?: {
|
|
97
|
+
email?: unknown;
|
|
98
|
+
}): GoogleWorkspaceError;
|
|
83
99
|
/**
|
|
84
100
|
* Fetches, caches and refreshes the Google access token that Cloud mints
|
|
85
101
|
* from the owner's stored grant.
|
|
@@ -219,6 +235,8 @@ export declare class GoogleWorkspaceTokenService {
|
|
|
219
235
|
*/
|
|
220
236
|
buildSlackConnectUrl(options?: {
|
|
221
237
|
products?: readonly GoogleProduct[];
|
|
238
|
+
/** Google account to reconnect; Google preselects it (Cloud auth >= 1.10.9, ignored before). */
|
|
239
|
+
email?: string;
|
|
222
240
|
slackUserId?: string;
|
|
223
241
|
slackChannelId?: string;
|
|
224
242
|
slackThreadTs?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"google-workspace-token.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-workspace-token.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,OAAO,EAAgD,KAAK,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEtG,OAAO,EAAgE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAElJ,0DAA0D;AAC1D,MAAM,WAAW,0BAA0B;IACzC,WAAW,IAAI,OAAO,CAAC;IACvB,QAAQ,IAAI,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,IAAI,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,kFAAkF;AAClF,MAAM,WAAW,+BAA+B;IAC9C,KAAK,CAAC,EAAE,0BAA0B,CAAC;IACnC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;CACpB;AAED,0FAA0F;AAC1F,gEAAgE;AAChE,MAAM,WAAW,gBAAiB,SAAQ,cAAc;IACtD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,8DAA8D;IAC9D,SAAS,EAAE,OAAO,CAAC;IACnB,2DAA2D;IAC3D,cAAc,EAAE,OAAO,CAAC;IACxB,uDAAuD;IACvD,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoBD;;;;;GAKG;AACH,
|
|
1
|
+
{"version":3,"file":"google-workspace-token.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/google/google-workspace-token.service.ts"],"names":[],"mappings":"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"}
|