crewly 1.20.128 → 1.20.129
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/templates/growth-marketing-team.json +12 -1
- package/config/templates/personal-assistant-team.json +28 -0
- package/dist/backend/backend/src/constants.d.ts +45 -0
- package/dist/backend/backend/src/constants.d.ts.map +1 -1
- package/dist/backend/backend/src/constants.js +51 -0
- package/dist/backend/backend/src/constants.js.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts +49 -0
- package/dist/backend/backend/src/controllers/chat/chat.controller.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/chat/chat.controller.js +135 -106
- package/dist/backend/backend/src/controllers/chat/chat.controller.js.map +1 -1
- package/dist/backend/backend/src/controllers/onboarding/index.d.ts +1 -0
- package/dist/backend/backend/src/controllers/onboarding/index.d.ts.map +1 -1
- package/dist/backend/backend/src/controllers/onboarding/index.js +1 -0
- package/dist/backend/backend/src/controllers/onboarding/index.js.map +1 -1
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.controller.d.ts +38 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.controller.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.controller.js +106 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.controller.js.map +1 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.routes.d.ts +24 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.routes.d.ts.map +1 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.routes.js +34 -0
- package/dist/backend/backend/src/controllers/onboarding/onboarding-checklist.routes.js.map +1 -0
- package/dist/backend/backend/src/index.d.ts.map +1 -1
- package/dist/backend/backend/src/index.js +17 -0
- package/dist/backend/backend/src/index.js.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.d.ts.map +1 -1
- package/dist/backend/backend/src/routes/api.routes.js +5 -0
- package/dist/backend/backend/src/routes/api.routes.js.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js +10 -0
- package/dist/backend/backend/src/services/cloud/mobile-api-relay.service.js.map +1 -1
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.d.ts +45 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.js +103 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.factory.js.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.d.ts +301 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js +365 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-state.store.d.ts +89 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-state.store.d.ts.map +1 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-state.store.js +122 -0
- package/dist/backend/backend/src/services/onboarding/onboarding-state.store.js.map +1 -0
- package/dist/backend/backend/src/services/template/template.service.d.ts +15 -1
- package/dist/backend/backend/src/services/template/template.service.d.ts.map +1 -1
- package/dist/backend/backend/src/services/template/template.service.js +22 -1
- package/dist/backend/backend/src/services/template/template.service.js.map +1 -1
- package/dist/backend/backend/src/types/team-template.types.d.ts +30 -0
- package/dist/backend/backend/src/types/team-template.types.d.ts.map +1 -1
- package/dist/backend/backend/src/types/team-template.types.js +24 -0
- package/dist/backend/backend/src/types/team-template.types.js.map +1 -1
- package/dist/backend/build-info.json +2 -2
- package/dist/cli/backend/src/constants.d.ts +45 -0
- package/dist/cli/backend/src/constants.d.ts.map +1 -1
- package/dist/cli/backend/src/constants.js +51 -0
- package/dist/cli/backend/src/constants.js.map +1 -1
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.d.ts +301 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js +365 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-checklist.service.js.map +1 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-state.store.d.ts +89 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-state.store.d.ts.map +1 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-state.store.js +122 -0
- package/dist/cli/backend/src/services/onboarding/onboarding-state.store.js.map +1 -0
- package/dist/cli/backend/src/services/skill/skill-tier.service.d.ts +116 -0
- package/dist/cli/backend/src/services/skill/skill-tier.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/skill/skill-tier.service.js +155 -0
- package/dist/cli/backend/src/services/skill/skill-tier.service.js.map +1 -0
- package/dist/cli/backend/src/services/template/template.service.d.ts +152 -0
- package/dist/cli/backend/src/services/template/template.service.d.ts.map +1 -0
- package/dist/cli/backend/src/services/template/template.service.js +506 -0
- package/dist/cli/backend/src/services/template/template.service.js.map +1 -0
- package/dist/cli/backend/src/types/team-template.types.d.ts +30 -0
- package/dist/cli/backend/src/types/team-template.types.d.ts.map +1 -1
- package/dist/cli/backend/src/types/team-template.types.js +24 -0
- package/dist/cli/backend/src/types/team-template.types.js.map +1 -1
- package/dist/cli/cli/src/commands/onboard-checklist.d.ts +152 -0
- package/dist/cli/cli/src/commands/onboard-checklist.d.ts.map +1 -0
- package/dist/cli/cli/src/commands/onboard-checklist.js +241 -0
- package/dist/cli/cli/src/commands/onboard-checklist.js.map +1 -0
- package/dist/cli/cli/src/commands/onboard.d.ts +87 -6
- package/dist/cli/cli/src/commands/onboard.d.ts.map +1 -1
- package/dist/cli/cli/src/commands/onboard.js +203 -37
- package/dist/cli/cli/src/commands/onboard.js.map +1 -1
- package/dist/cli/cli/src/constants.d.ts +5 -0
- package/dist/cli/cli/src/constants.d.ts.map +1 -1
- package/dist/cli/cli/src/constants.js +5 -0
- package/dist/cli/cli/src/constants.js.map +1 -1
- package/dist/cli/cli/src/index.js +2 -1
- package/dist/cli/cli/src/index.js.map +1 -1
- package/dist/cli/cli/src/utils/templates.d.ts +27 -0
- package/dist/cli/cli/src/utils/templates.d.ts.map +1 -1
- package/dist/cli/cli/src/utils/templates.js +29 -0
- package/dist/cli/cli/src/utils/templates.js.map +1 -1
- package/frontend/dist/assets/index-2bdb57b9.css +42 -0
- package/frontend/dist/assets/{index-aaf65055.js → index-5b98bf77.js} +285 -285
- package/frontend/dist/index.html +2 -2
- package/package.json +1 -1
- package/frontend/dist/assets/index-0a2f783c.css +0 -42
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding checklist — the first-run steps after the harness is ready
|
|
3
|
+
* (specs/onboarding-harness-login.md, Phase 3):
|
|
4
|
+
*
|
|
5
|
+
* harness → first team (starter template or Blank) → first task → Cloud → Slack
|
|
6
|
+
*
|
|
7
|
+
* Every step's `done` is read from the real system, not from UI flags:
|
|
8
|
+
*
|
|
9
|
+
* - `harness`: the orchestrator's harness is recorded, installed and not
|
|
10
|
+
* known to be logged out (the same rule as the web setup redirect);
|
|
11
|
+
* - `team`: at least one team exists, or the owner chose Blank;
|
|
12
|
+
* - `first_task`: the owner has sent at least one message on any surface
|
|
13
|
+
* (chat-v2 `user` rows an agent did not write), or a first task was handed
|
|
14
|
+
* to the orchestrator from setup;
|
|
15
|
+
* - `cloud`: this instance is connected to Crewly Cloud;
|
|
16
|
+
* - `slack`: Slack is connected (Cloud-installed app or self-hosted tokens).
|
|
17
|
+
*
|
|
18
|
+
* The only stored flags are the dashboard card's `dismissed`, the Blank
|
|
19
|
+
* choice and the first-task record (`onboarding-state.store.ts`).
|
|
20
|
+
*
|
|
21
|
+
* Shared by the REST routes (`/api/onboarding/*`, also reachable from the
|
|
22
|
+
* phone / portal over the relay) and `crewly onboard`.
|
|
23
|
+
*
|
|
24
|
+
* @module services/onboarding/onboarding-checklist.service
|
|
25
|
+
*/
|
|
26
|
+
import { ONBOARDING_CONSTANTS, HARNESS_CONSTANTS, CLOUD_CONSTANTS } from '../../constants.js';
|
|
27
|
+
/** A request the checklist cannot fulfil. */
|
|
28
|
+
export class OnboardingError extends Error {
|
|
29
|
+
code;
|
|
30
|
+
/**
|
|
31
|
+
* @param code - Machine-readable code (mapped to an HTTP status by the controller)
|
|
32
|
+
* @param message - Human-readable message
|
|
33
|
+
*/
|
|
34
|
+
constructor(code, message) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.code = code;
|
|
37
|
+
this.name = 'OnboardingError';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// =============================================================================
|
|
41
|
+
// Helpers
|
|
42
|
+
// =============================================================================
|
|
43
|
+
/**
|
|
44
|
+
* Lower-case slug of ASCII letters, digits and dashes.
|
|
45
|
+
*
|
|
46
|
+
* @param value - Any text
|
|
47
|
+
* @returns Slug (may be empty for non-ASCII text)
|
|
48
|
+
*/
|
|
49
|
+
export function toSessionSlug(value) {
|
|
50
|
+
return value
|
|
51
|
+
.toLowerCase()
|
|
52
|
+
.replace(/[^a-z0-9]+/g, '-')
|
|
53
|
+
.replace(/^-+|-+$/g, '');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The Crewly Cloud sign-in that works from any device: Google sign-in on
|
|
57
|
+
* Cloud, ending on the portal's token page (token + refresh token to paste).
|
|
58
|
+
*
|
|
59
|
+
* @returns Absolute URL
|
|
60
|
+
*/
|
|
61
|
+
export function buildTokenPageSignInUrl() {
|
|
62
|
+
const tokenPage = `${ONBOARDING_CONSTANTS.CLOUD.CONSOLE_URL}${ONBOARDING_CONSTANTS.CLOUD.CLI_TOKEN_PATH}`;
|
|
63
|
+
return `${CLOUD_CONSTANTS.DEFAULT_CLOUD_URL}${ONBOARDING_CONSTANTS.CLOUD.GOOGLE_START_PATH}?redirect=${encodeURIComponent(tokenPage)}`;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* The message the orchestrator receives for a first task.
|
|
67
|
+
*
|
|
68
|
+
* @param text - The owner's words
|
|
69
|
+
* @param team - Team it is meant for, or null for the orchestrator itself
|
|
70
|
+
* @returns Message content
|
|
71
|
+
*/
|
|
72
|
+
export function buildFirstTaskMessage(text, team) {
|
|
73
|
+
const lines = [ONBOARDING_CONSTANTS.FIRST_TASK_HEADER];
|
|
74
|
+
if (team) {
|
|
75
|
+
lines.push(`请交给团队「${team.name}」(team id: ${team.id}) 来做;团队还没启动的话先启动它。`);
|
|
76
|
+
}
|
|
77
|
+
lines.push('', text.trim());
|
|
78
|
+
return lines.join('\n');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Starter DTO for a template.
|
|
82
|
+
*
|
|
83
|
+
* @param template - Template with onboarding metadata
|
|
84
|
+
* @param onboarding - Its onboarding metadata
|
|
85
|
+
* @returns Starter
|
|
86
|
+
*/
|
|
87
|
+
function templateToStarter(template, onboarding) {
|
|
88
|
+
return {
|
|
89
|
+
id: template.id,
|
|
90
|
+
name: template.name,
|
|
91
|
+
label: onboarding.label,
|
|
92
|
+
tagline: onboarding.tagline,
|
|
93
|
+
description: template.description,
|
|
94
|
+
recommended: onboarding.recommended,
|
|
95
|
+
members: template.roles.flatMap((role) => Array.from({ length: Math.max(1, role.count) }, (_, i) => ({
|
|
96
|
+
name: role.count > 1 ? `${role.defaultName}${i + 1}` : role.defaultName,
|
|
97
|
+
role: role.role,
|
|
98
|
+
}))),
|
|
99
|
+
suggestions: [...onboarding.suggestions],
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Error text for a failed step read.
|
|
104
|
+
*
|
|
105
|
+
* @param error - Thrown value
|
|
106
|
+
* @returns Message
|
|
107
|
+
*/
|
|
108
|
+
function errorText(error) {
|
|
109
|
+
return error instanceof Error ? error.message : String(error);
|
|
110
|
+
}
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// Service
|
|
113
|
+
// =============================================================================
|
|
114
|
+
/**
|
|
115
|
+
* First-run checklist: step states, starter teams, the first task, dismissal.
|
|
116
|
+
*/
|
|
117
|
+
export class OnboardingChecklistService {
|
|
118
|
+
deps;
|
|
119
|
+
/**
|
|
120
|
+
* @param deps - Dependencies
|
|
121
|
+
*/
|
|
122
|
+
constructor(deps) {
|
|
123
|
+
this.deps = deps;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Read every step from the live system.
|
|
127
|
+
*
|
|
128
|
+
* A step whose source fails reads as not done, with `detail.error` set;
|
|
129
|
+
* the rest of the checklist is still returned.
|
|
130
|
+
*
|
|
131
|
+
* @returns The checklist
|
|
132
|
+
*/
|
|
133
|
+
async getChecklist() {
|
|
134
|
+
const state = await this.deps.store.read();
|
|
135
|
+
const steps = await Promise.all([
|
|
136
|
+
this.harnessStep(),
|
|
137
|
+
this.teamStep(state),
|
|
138
|
+
this.firstTaskStep(state),
|
|
139
|
+
this.cloudStep(),
|
|
140
|
+
this.slackStep(),
|
|
141
|
+
]);
|
|
142
|
+
const doneCount = steps.filter((s) => s.done).length;
|
|
143
|
+
return {
|
|
144
|
+
steps,
|
|
145
|
+
doneCount,
|
|
146
|
+
total: steps.length,
|
|
147
|
+
allDone: doneCount === steps.length,
|
|
148
|
+
dismissed: state.dismissedAt !== null,
|
|
149
|
+
dismissedAt: state.dismissedAt,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* The starter teams: templates marked `onboarding` (by `order`), then Blank.
|
|
154
|
+
*
|
|
155
|
+
* @returns Starters, recommended first
|
|
156
|
+
*/
|
|
157
|
+
listStarters() {
|
|
158
|
+
const starters = this.deps
|
|
159
|
+
.templates()
|
|
160
|
+
.listOnboardingStarters()
|
|
161
|
+
.filter((t) => !!t.onboarding)
|
|
162
|
+
.map((t) => templateToStarter(t, t.onboarding));
|
|
163
|
+
const blank = ONBOARDING_CONSTANTS.BLANK_STARTER;
|
|
164
|
+
starters.push({
|
|
165
|
+
id: ONBOARDING_CONSTANTS.BLANK_STARTER_ID,
|
|
166
|
+
name: blank.NAME,
|
|
167
|
+
label: blank.LABEL,
|
|
168
|
+
tagline: blank.TAGLINE,
|
|
169
|
+
description: blank.TAGLINE,
|
|
170
|
+
recommended: false,
|
|
171
|
+
members: [],
|
|
172
|
+
suggestions: [...blank.SUGGESTIONS],
|
|
173
|
+
});
|
|
174
|
+
return starters;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Create the first team from a starter, or record the Blank choice.
|
|
178
|
+
*
|
|
179
|
+
* Idempotent: a team already created from the same template is returned
|
|
180
|
+
* (a double tap on a phone must not make two teams). Members run on the
|
|
181
|
+
* orchestrator's harness, the only one first-time setup installs.
|
|
182
|
+
*
|
|
183
|
+
* @param starterId - Template id of a starter, or `blank`
|
|
184
|
+
* @returns The team (null for Blank) and whether it was created now
|
|
185
|
+
* @throws OnboardingError `unknown_starter`
|
|
186
|
+
*/
|
|
187
|
+
async createStarterTeam(starterId) {
|
|
188
|
+
if (starterId === ONBOARDING_CONSTANTS.BLANK_STARTER_ID) {
|
|
189
|
+
const now = this.deps.now().toISOString();
|
|
190
|
+
await this.deps.store.update((cur) => ({ blankChosenAt: cur.blankChosenAt ?? now }));
|
|
191
|
+
return { starterId, team: null, created: false };
|
|
192
|
+
}
|
|
193
|
+
const source = this.deps.templates();
|
|
194
|
+
const template = source.getTemplate(starterId);
|
|
195
|
+
if (!template || !template.onboarding) {
|
|
196
|
+
throw new OnboardingError('unknown_starter', `"${starterId}" is not a starter team`);
|
|
197
|
+
}
|
|
198
|
+
const existing = (await this.deps.listTeams()).find((t) => t.templateId === template.id);
|
|
199
|
+
if (existing)
|
|
200
|
+
return { starterId, team: existing, created: false };
|
|
201
|
+
const result = source.createTeamFromTemplate(template.id, template.name);
|
|
202
|
+
if (!result)
|
|
203
|
+
throw new OnboardingError('unknown_starter', `"${starterId}" is not a starter team`);
|
|
204
|
+
const runtime = (await this.deps.getOrcHarness()) ?? HARNESS_CONSTANTS.DEFAULT_ORC_HARNESS;
|
|
205
|
+
const teamSlug = toSessionSlug(template.id);
|
|
206
|
+
for (const member of result.team.members) {
|
|
207
|
+
member.runtimeType = runtime;
|
|
208
|
+
member.sessionName = `${teamSlug}-${toSessionSlug(member.name) || 'member'}-${member.id.slice(0, 8)}`;
|
|
209
|
+
}
|
|
210
|
+
await this.deps.saveTeam(result.team);
|
|
211
|
+
return { starterId, team: result.team, created: true };
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Hand the owner's first task to the orchestrator (through the chat path,
|
|
215
|
+
* so it is a normal owner message: ticket intake, queue while offline).
|
|
216
|
+
*
|
|
217
|
+
* @param text - The owner's words
|
|
218
|
+
* @param teamId - Team it is meant for (omit for the orchestrator itself)
|
|
219
|
+
* @returns Delivery result
|
|
220
|
+
* @throws OnboardingError `invalid_task` | `unknown_team`
|
|
221
|
+
*/
|
|
222
|
+
async sendFirstTask(text, teamId) {
|
|
223
|
+
if (typeof text !== 'string' || text.trim().length === 0) {
|
|
224
|
+
throw new OnboardingError('invalid_task', 'Write what the team should do first');
|
|
225
|
+
}
|
|
226
|
+
if (text.length > ONBOARDING_CONSTANTS.FIRST_TASK_MAX_LENGTH) {
|
|
227
|
+
throw new OnboardingError('invalid_task', `Keep the first task under ${ONBOARDING_CONSTANTS.FIRST_TASK_MAX_LENGTH} characters`);
|
|
228
|
+
}
|
|
229
|
+
let team = null;
|
|
230
|
+
if (teamId !== undefined && teamId !== null && teamId !== '') {
|
|
231
|
+
team = (await this.deps.listTeams()).find((t) => t.id === teamId) ?? null;
|
|
232
|
+
if (!team)
|
|
233
|
+
throw new OnboardingError('unknown_team', `Team "${String(teamId)}" not found`);
|
|
234
|
+
}
|
|
235
|
+
const sent = await this.deps.sendToOrchestrator(buildFirstTaskMessage(text, team), {
|
|
236
|
+
source: ONBOARDING_CONSTANTS.FIRST_TASK_SOURCE,
|
|
237
|
+
...(team ? { teamId: team.id } : {}),
|
|
238
|
+
});
|
|
239
|
+
let sentAt = null;
|
|
240
|
+
if (sent.forwarded) {
|
|
241
|
+
sentAt = this.deps.now().toISOString();
|
|
242
|
+
const record = { sentAt, teamId: team?.id ?? null, conversationId: sent.conversationId };
|
|
243
|
+
await this.deps.store.update(() => ({ firstTask: record, pendingFirstTask: null }));
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
forwarded: sent.forwarded,
|
|
247
|
+
queued: sent.queued,
|
|
248
|
+
conversationId: sent.conversationId,
|
|
249
|
+
teamId: team?.id ?? null,
|
|
250
|
+
sentAt,
|
|
251
|
+
message: sent.error,
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Keep a first task typed while the backend was down (`crewly onboard`).
|
|
256
|
+
*
|
|
257
|
+
* @param text - The owner's words
|
|
258
|
+
* @param teamId - Team it is meant for, or null
|
|
259
|
+
* @throws OnboardingError `invalid_task`
|
|
260
|
+
*/
|
|
261
|
+
async queuePendingFirstTask(text, teamId) {
|
|
262
|
+
if (text.trim().length === 0 || text.length > ONBOARDING_CONSTANTS.FIRST_TASK_MAX_LENGTH) {
|
|
263
|
+
throw new OnboardingError('invalid_task', 'Write what the team should do first');
|
|
264
|
+
}
|
|
265
|
+
const createdAt = this.deps.now().toISOString();
|
|
266
|
+
await this.deps.store.update(() => ({ pendingFirstTask: { text: text.trim(), teamId, createdAt } }));
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Deliver a pending first task (called when the backend starts). A team
|
|
270
|
+
* that no longer exists sends it to the orchestrator itself.
|
|
271
|
+
*
|
|
272
|
+
* @returns The delivery result, or null when nothing was pending
|
|
273
|
+
*/
|
|
274
|
+
async deliverPendingFirstTask() {
|
|
275
|
+
const { pendingFirstTask } = await this.deps.store.read();
|
|
276
|
+
if (!pendingFirstTask)
|
|
277
|
+
return null;
|
|
278
|
+
const teams = await this.deps.listTeams();
|
|
279
|
+
const teamId = pendingFirstTask.teamId && teams.some((t) => t.id === pendingFirstTask.teamId) ? pendingFirstTask.teamId : undefined;
|
|
280
|
+
return this.sendFirstTask(pendingFirstTask.text, teamId);
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Hide or show the dashboard checklist card.
|
|
284
|
+
*
|
|
285
|
+
* @param dismissed - True to hide
|
|
286
|
+
* @returns The checklist after the change
|
|
287
|
+
*/
|
|
288
|
+
async setDismissed(dismissed) {
|
|
289
|
+
const now = this.deps.now().toISOString();
|
|
290
|
+
await this.deps.store.update((cur) => ({ dismissedAt: dismissed ? cur.dismissedAt ?? now : null }));
|
|
291
|
+
return this.getChecklist();
|
|
292
|
+
}
|
|
293
|
+
// ---------------------------------------------------------------------------
|
|
294
|
+
// Steps
|
|
295
|
+
// ---------------------------------------------------------------------------
|
|
296
|
+
/** @returns Harness step */
|
|
297
|
+
async harnessStep() {
|
|
298
|
+
try {
|
|
299
|
+
const detail = await this.deps.getHarnessState();
|
|
300
|
+
const done = detail.orcHarness !== null && detail.installed && detail.loginState !== 'logged_out';
|
|
301
|
+
return { id: 'harness', done, detail };
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
return { id: 'harness', done: false, detail: { orcHarness: null, installed: false, loginState: null, error: errorText(error) } };
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* @param state - Stored onboarding state
|
|
309
|
+
* @returns Team step
|
|
310
|
+
*/
|
|
311
|
+
async teamStep(state) {
|
|
312
|
+
const blank = state.blankChosenAt !== null;
|
|
313
|
+
try {
|
|
314
|
+
const teams = (await this.deps.listTeams()).map((t) => ({ id: t.id, name: t.name, templateId: t.templateId ?? null }));
|
|
315
|
+
return { id: 'team', done: teams.length > 0 || blank, detail: { teams, blank } };
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
return { id: 'team', done: blank, detail: { teams: [], blank, error: errorText(error) } };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* @param state - Stored onboarding state
|
|
323
|
+
* @returns First-task step
|
|
324
|
+
*/
|
|
325
|
+
async firstTaskStep(state) {
|
|
326
|
+
const sentAt = state.firstTask?.sentAt ?? null;
|
|
327
|
+
const pending = state.pendingFirstTask !== null;
|
|
328
|
+
try {
|
|
329
|
+
const ownerMessageSeen = this.deps.hasOwnerMessage();
|
|
330
|
+
return { id: 'first_task', done: sentAt !== null || ownerMessageSeen, detail: { sentAt, ownerMessageSeen, pending } };
|
|
331
|
+
}
|
|
332
|
+
catch (error) {
|
|
333
|
+
return { id: 'first_task', done: sentAt !== null, detail: { sentAt, ownerMessageSeen: false, pending, error: errorText(error) } };
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
/** @returns Cloud step */
|
|
337
|
+
async cloudStep() {
|
|
338
|
+
const tokenPageSignInUrl = buildTokenPageSignInUrl();
|
|
339
|
+
try {
|
|
340
|
+
const { connected, tier } = this.deps.getCloudState();
|
|
341
|
+
return { id: 'cloud', done: connected, detail: { connected, tier: connected ? tier : null, tokenPageSignInUrl } };
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
return { id: 'cloud', done: false, detail: { connected: false, tier: null, tokenPageSignInUrl, error: errorText(error) } };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/** @returns Slack step */
|
|
348
|
+
async slackStep() {
|
|
349
|
+
let cloudConnected = false;
|
|
350
|
+
try {
|
|
351
|
+
cloudConnected = this.deps.getCloudState().connected;
|
|
352
|
+
}
|
|
353
|
+
catch {
|
|
354
|
+
// Reported by the Cloud step.
|
|
355
|
+
}
|
|
356
|
+
try {
|
|
357
|
+
const connected = this.deps.isSlackConnected();
|
|
358
|
+
return { id: 'slack', done: connected, detail: { connected, cloudConnected } };
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
return { id: 'slack', done: false, detail: { connected: false, cloudConnected, error: errorText(error) } };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//# sourceMappingURL=onboarding-checklist.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-checklist.service.js","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/onboarding-checklist.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding state store — `<crewlyHome>/onboarding.json`.
|
|
3
|
+
*
|
|
4
|
+
* Holds the few things the first-run checklist cannot read from the rest of
|
|
5
|
+
* the system (specs/onboarding-harness-login.md, Phase 3):
|
|
6
|
+
*
|
|
7
|
+
* - `dismissedAt`: the owner hid the dashboard checklist card;
|
|
8
|
+
* - `blankChosenAt`: the owner chose "Blank" (the orchestrator only), which
|
|
9
|
+
* completes the team step without a team;
|
|
10
|
+
* - `firstTask`: a first task that was handed to the orchestrator;
|
|
11
|
+
* - `pendingFirstTask`: a first task typed in `crewly onboard` while the
|
|
12
|
+
* backend was down, delivered when the backend starts.
|
|
13
|
+
*
|
|
14
|
+
* Everything else (harness login, teams, Cloud, Slack) is read live.
|
|
15
|
+
* Writes are atomic (temp file + rename) and serialized per store.
|
|
16
|
+
*
|
|
17
|
+
* @module services/onboarding/onboarding-state.store
|
|
18
|
+
*/
|
|
19
|
+
/** A first task handed to the orchestrator. */
|
|
20
|
+
export interface SentFirstTask {
|
|
21
|
+
/** ISO time it was handed over */
|
|
22
|
+
sentAt: string;
|
|
23
|
+
/** Team it was meant for (null = the orchestrator itself) */
|
|
24
|
+
teamId: string | null;
|
|
25
|
+
/** Chat conversation it was recorded in */
|
|
26
|
+
conversationId: string | null;
|
|
27
|
+
}
|
|
28
|
+
/** A first task waiting for the backend to start. */
|
|
29
|
+
export interface PendingFirstTask {
|
|
30
|
+
/** The owner's words */
|
|
31
|
+
text: string;
|
|
32
|
+
/** Team it is meant for (null = the orchestrator itself) */
|
|
33
|
+
teamId: string | null;
|
|
34
|
+
/** ISO time it was typed */
|
|
35
|
+
createdAt: string;
|
|
36
|
+
}
|
|
37
|
+
/** Contents of `onboarding.json`. */
|
|
38
|
+
export interface OnboardingState {
|
|
39
|
+
dismissedAt: string | null;
|
|
40
|
+
blankChosenAt: string | null;
|
|
41
|
+
firstTask: SentFirstTask | null;
|
|
42
|
+
pendingFirstTask: PendingFirstTask | null;
|
|
43
|
+
}
|
|
44
|
+
/** State of a machine that never saw onboarding. */
|
|
45
|
+
export declare const EMPTY_ONBOARDING_STATE: OnboardingState;
|
|
46
|
+
/**
|
|
47
|
+
* Normalize parsed JSON into a complete state (unknown / malformed fields are dropped).
|
|
48
|
+
*
|
|
49
|
+
* @param raw - Parsed file contents
|
|
50
|
+
* @returns A complete state
|
|
51
|
+
*/
|
|
52
|
+
export declare function normalizeOnboardingState(raw: unknown): OnboardingState;
|
|
53
|
+
/**
|
|
54
|
+
* File-backed onboarding state.
|
|
55
|
+
*/
|
|
56
|
+
export declare class OnboardingStateStore {
|
|
57
|
+
private readonly filePath;
|
|
58
|
+
/** Serializes read-modify-write cycles */
|
|
59
|
+
private chain;
|
|
60
|
+
/**
|
|
61
|
+
* @param crewlyHome - Crewly home dir (defaults to `CREWLY_HOME` / `~/.crewly`)
|
|
62
|
+
*/
|
|
63
|
+
constructor(crewlyHome?: string);
|
|
64
|
+
/**
|
|
65
|
+
* Path of the state file.
|
|
66
|
+
*
|
|
67
|
+
* @returns Absolute path
|
|
68
|
+
*/
|
|
69
|
+
getFilePath(): string;
|
|
70
|
+
/**
|
|
71
|
+
* Read the state. A missing or unreadable file reads as empty.
|
|
72
|
+
*
|
|
73
|
+
* @returns The state
|
|
74
|
+
*/
|
|
75
|
+
read(): Promise<OnboardingState>;
|
|
76
|
+
/**
|
|
77
|
+
* Apply a change and write the result atomically.
|
|
78
|
+
*
|
|
79
|
+
* @param change - Returns the fields to change
|
|
80
|
+
* @returns The state after the change
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* ```ts
|
|
84
|
+
* await store.update(() => ({ dismissedAt: new Date().toISOString() }));
|
|
85
|
+
* ```
|
|
86
|
+
*/
|
|
87
|
+
update(change: (current: OnboardingState) => Partial<OnboardingState>): Promise<OnboardingState>;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=onboarding-state.store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-state.store.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/onboarding-state.store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,+CAA+C;AAC/C,MAAM,WAAW,aAAa;IAC7B,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,2CAA2C;IAC3C,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,qDAAqD;AACrD,MAAM,WAAW,gBAAgB;IAChC,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,4DAA4D;IAC5D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,WAAW,eAAe;IAC/B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;CAC1C;AAED,oDAAoD;AACpD,eAAO,MAAM,sBAAsB,EAAE,eAKnC,CAAC;AAYH;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,CAiBtE;AAED;;GAEG;AACH,qBAAa,oBAAoB;IAChC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,0CAA0C;IAC1C,OAAO,CAAC,KAAK,CAAuC;IAEpD;;OAEG;gBACS,UAAU,GAAE,MAA4B;IAIpD;;;;OAIG;IACH,WAAW,IAAI,MAAM;IAIrB;;;;OAIG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,CAAC;IAQtC;;;;;;;;;;OAUG;IACH,MAAM,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,OAAO,CAAC,eAAe,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;CAchG"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Onboarding state store — `<crewlyHome>/onboarding.json`.
|
|
3
|
+
*
|
|
4
|
+
* Holds the few things the first-run checklist cannot read from the rest of
|
|
5
|
+
* the system (specs/onboarding-harness-login.md, Phase 3):
|
|
6
|
+
*
|
|
7
|
+
* - `dismissedAt`: the owner hid the dashboard checklist card;
|
|
8
|
+
* - `blankChosenAt`: the owner chose "Blank" (the orchestrator only), which
|
|
9
|
+
* completes the team step without a team;
|
|
10
|
+
* - `firstTask`: a first task that was handed to the orchestrator;
|
|
11
|
+
* - `pendingFirstTask`: a first task typed in `crewly onboard` while the
|
|
12
|
+
* backend was down, delivered when the backend starts.
|
|
13
|
+
*
|
|
14
|
+
* Everything else (harness login, teams, Cloud, Slack) is read live.
|
|
15
|
+
* Writes are atomic (temp file + rename) and serialized per store.
|
|
16
|
+
*
|
|
17
|
+
* @module services/onboarding/onboarding-state.store
|
|
18
|
+
*/
|
|
19
|
+
import { promises as fs } from 'fs';
|
|
20
|
+
import * as path from 'path';
|
|
21
|
+
import { ONBOARDING_CONSTANTS } from '../../constants.js';
|
|
22
|
+
import { getCrewlyHomePath } from '../core/crewly-home.utils.js';
|
|
23
|
+
/** State of a machine that never saw onboarding. */
|
|
24
|
+
export const EMPTY_ONBOARDING_STATE = Object.freeze({
|
|
25
|
+
dismissedAt: null,
|
|
26
|
+
blankChosenAt: null,
|
|
27
|
+
firstTask: null,
|
|
28
|
+
pendingFirstTask: null,
|
|
29
|
+
});
|
|
30
|
+
/**
|
|
31
|
+
* Read an ISO string field, or null.
|
|
32
|
+
*
|
|
33
|
+
* @param value - Candidate
|
|
34
|
+
* @returns The string, or null
|
|
35
|
+
*/
|
|
36
|
+
function asString(value) {
|
|
37
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Normalize parsed JSON into a complete state (unknown / malformed fields are dropped).
|
|
41
|
+
*
|
|
42
|
+
* @param raw - Parsed file contents
|
|
43
|
+
* @returns A complete state
|
|
44
|
+
*/
|
|
45
|
+
export function normalizeOnboardingState(raw) {
|
|
46
|
+
if (!raw || typeof raw !== 'object')
|
|
47
|
+
return { ...EMPTY_ONBOARDING_STATE };
|
|
48
|
+
const o = raw;
|
|
49
|
+
const task = o.firstTask;
|
|
50
|
+
const pending = o.pendingFirstTask;
|
|
51
|
+
return {
|
|
52
|
+
dismissedAt: asString(o.dismissedAt),
|
|
53
|
+
blankChosenAt: asString(o.blankChosenAt),
|
|
54
|
+
firstTask: task && typeof task === 'object' && asString(task.sentAt)
|
|
55
|
+
? { sentAt: task.sentAt, teamId: asString(task.teamId), conversationId: asString(task.conversationId) }
|
|
56
|
+
: null,
|
|
57
|
+
pendingFirstTask: pending && typeof pending === 'object' && asString(pending.text) && asString(pending.createdAt)
|
|
58
|
+
? { text: pending.text, teamId: asString(pending.teamId), createdAt: pending.createdAt }
|
|
59
|
+
: null,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* File-backed onboarding state.
|
|
64
|
+
*/
|
|
65
|
+
export class OnboardingStateStore {
|
|
66
|
+
filePath;
|
|
67
|
+
/** Serializes read-modify-write cycles */
|
|
68
|
+
chain = Promise.resolve();
|
|
69
|
+
/**
|
|
70
|
+
* @param crewlyHome - Crewly home dir (defaults to `CREWLY_HOME` / `~/.crewly`)
|
|
71
|
+
*/
|
|
72
|
+
constructor(crewlyHome = getCrewlyHomePath()) {
|
|
73
|
+
this.filePath = path.join(crewlyHome, ONBOARDING_CONSTANTS.STATE_FILE);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Path of the state file.
|
|
77
|
+
*
|
|
78
|
+
* @returns Absolute path
|
|
79
|
+
*/
|
|
80
|
+
getFilePath() {
|
|
81
|
+
return this.filePath;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Read the state. A missing or unreadable file reads as empty.
|
|
85
|
+
*
|
|
86
|
+
* @returns The state
|
|
87
|
+
*/
|
|
88
|
+
async read() {
|
|
89
|
+
try {
|
|
90
|
+
return normalizeOnboardingState(JSON.parse(await fs.readFile(this.filePath, 'utf-8')));
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { ...EMPTY_ONBOARDING_STATE };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Apply a change and write the result atomically.
|
|
98
|
+
*
|
|
99
|
+
* @param change - Returns the fields to change
|
|
100
|
+
* @returns The state after the change
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* await store.update(() => ({ dismissedAt: new Date().toISOString() }));
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
update(change) {
|
|
108
|
+
const run = async () => {
|
|
109
|
+
const current = await this.read();
|
|
110
|
+
const next = { ...current, ...change(current) };
|
|
111
|
+
await fs.mkdir(path.dirname(this.filePath), { recursive: true });
|
|
112
|
+
const tmp = `${this.filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
113
|
+
await fs.writeFile(tmp, `${JSON.stringify(next, null, 2)}\n`, 'utf-8');
|
|
114
|
+
await fs.rename(tmp, this.filePath);
|
|
115
|
+
return next;
|
|
116
|
+
};
|
|
117
|
+
const result = this.chain.then(run, run);
|
|
118
|
+
this.chain = result.catch(() => undefined);
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=onboarding-state.store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"onboarding-state.store.js","sourceRoot":"","sources":["../../../../../../backend/src/services/onboarding/onboarding-state.store.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* @module services/template/template
|
|
9
9
|
*/
|
|
10
|
-
import type { TeamTemplate } from '../../types/team-template.types.js';
|
|
10
|
+
import type { TeamTemplate, TemplateOnboarding } from '../../types/team-template.types.js';
|
|
11
11
|
import type { Team } from '../../types/index.js';
|
|
12
12
|
import { type CloudTier } from '../../constants.js';
|
|
13
13
|
/** Result of creating a team from a template */
|
|
@@ -36,6 +36,8 @@ export interface TemplateSummary {
|
|
|
36
36
|
source: TemplateSource;
|
|
37
37
|
/** Minimum tier required to use this template */
|
|
38
38
|
requiredTier?: CloudTier;
|
|
39
|
+
/** First-run starter metadata (only on onboarding starters) */
|
|
40
|
+
onboarding?: TemplateOnboarding;
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* TemplateService manages team templates.
|
|
@@ -78,6 +80,18 @@ export declare class TemplateService {
|
|
|
78
80
|
* @returns Array of local template summaries
|
|
79
81
|
*/
|
|
80
82
|
listTemplates(): TemplateSummary[];
|
|
83
|
+
/**
|
|
84
|
+
* The first-run starter templates (those with `onboarding` metadata),
|
|
85
|
+
* ordered by `onboarding.order`.
|
|
86
|
+
*
|
|
87
|
+
* @returns Starter templates, first-shown first
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* ```ts
|
|
91
|
+
* const [recommended] = TemplateService.getInstance().listOnboardingStarters();
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
listOnboardingStarters(): TeamTemplate[];
|
|
81
95
|
/**
|
|
82
96
|
* Get a specific template by ID.
|
|
83
97
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/template/template.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAgB,MAAM,oCAAoC,CAAC;
|
|
1
|
+
{"version":3,"file":"template.service.d.ts","sourceRoot":"","sources":["../../../../../../backend/src/services/template/template.service.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAOH,OAAO,KAAK,EAAE,YAAY,EAAgB,kBAAkB,EAAE,MAAM,oCAAoC,CAAC;AAEzG,OAAO,KAAK,EAAc,IAAI,EAAkB,MAAM,sBAAsB,CAAC;AAE7E,OAAO,EAAE,KAAK,SAAS,EAAmB,MAAM,oBAAoB,CAAC;AA8BrE,gDAAgD;AAChD,MAAM,WAAW,wBAAwB;IACvC,uBAAuB;IACvB,IAAI,EAAE,IAAI,CAAC;IACX,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mCAAmC;AACnC,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC;AAErC,2CAA2C;AAC3C,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,OAAO,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,MAAM,EAAE,cAAc,CAAC;IACvB,iDAAiD;IACjD,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,+DAA+D;IAC/D,UAAU,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAMD;;;;;;GAMG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAgC;IAEvD,qCAAqC;IACrC,OAAO,CAAC,SAAS,CAAwC;IAEzD,+BAA+B;IAC/B,OAAO,CAAC,YAAY,CAAS;IAE7B,yCAAyC;IACzC,OAAO,CAAC,MAAM,CAAkB;IAEhC,OAAO;IAIP;;;;;OAKG;IACH,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,eAAe;IAO1D;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,IAAI;IAI5B;;;;;;OAMG;IACH,aAAa,IAAI,MAAM;IA8BvB;;;;OAIG;IACH,aAAa,IAAI,eAAe,EAAE;IAmBlC;;;;;;;;;;OAUG;IACH,sBAAsB,IAAI,YAAY,EAAE;IAQxC;;;;;OAKG;IACH,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IAK5C;;;;;;;;;OASG;IACH,sBAAsB,CACpB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACtC,QAAQ,CAAC,EAAE,SAAS,GACnB,wBAAwB,GAAG,IAAI;IAyIlC;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAiDrB;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;;OAIG;IACH,gBAAgB,IAAI,MAAM;IAQ1B;;;;;OAKG;IACH,OAAO,CAAC,gBAAgB;IAkBxB;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;CAyG3B"}
|