@ever-works/contracts 1.0.0
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/README.md +62 -0
- package/dist/api/index.cjs +395 -0
- package/dist/api/index.d.cts +2171 -0
- package/dist/api/index.d.ts +2171 -0
- package/dist/api/index.js +335 -0
- package/dist/domain/index.cjs +335 -0
- package/dist/domain/index.d.cts +316 -0
- package/dist/domain/index.d.ts +316 -0
- package/dist/domain/index.js +317 -0
- package/dist/feed.types-BWk3CHqj.d.cts +355 -0
- package/dist/feed.types-BWk3CHqj.d.ts +355 -0
- package/dist/form/index.cjs +2 -0
- package/dist/form/index.d.cts +104 -0
- package/dist/form/index.d.ts +104 -0
- package/dist/form/index.js +1 -0
- package/dist/index.cjs +6968 -0
- package/dist/index.d.cts +11815 -0
- package/dist/index.d.ts +11815 -0
- package/dist/index.js +6019 -0
- package/dist/item/index.cjs +2 -0
- package/dist/item/index.d.cts +195 -0
- package/dist/item/index.d.ts +195 -0
- package/dist/item/index.js +1 -0
- package/dist/telemetry/index.cjs +15 -0
- package/dist/telemetry/index.d.cts +120 -0
- package/dist/telemetry/index.d.ts +120 -0
- package/dist/telemetry/index.js +13 -0
- package/package.json +81 -0
|
@@ -0,0 +1,2171 @@
|
|
|
1
|
+
import { ItemData, ItemHealth } from '../item/index.cjs';
|
|
2
|
+
import { M as MergePolicyOverride, O as OrganizationConnectionPolicy, F as FeedNarrationDto } from '../feed.types-BWk3CHqj.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Method used for item generation
|
|
6
|
+
*/
|
|
7
|
+
declare enum GenerationMethod {
|
|
8
|
+
CREATE_UPDATE = "create-update",
|
|
9
|
+
RECREATE = "recreate",
|
|
10
|
+
IMPORT = "import"
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Method used for website repository creation
|
|
14
|
+
*/
|
|
15
|
+
declare enum WebsiteRepositoryCreationMethod {
|
|
16
|
+
DUPLICATE = "duplicate",
|
|
17
|
+
CREATE_USING_TEMPLATE = "create-using-template"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Provider selection for each capability category
|
|
22
|
+
*/
|
|
23
|
+
interface ProvidersDto {
|
|
24
|
+
/** Search provider plugin ID */
|
|
25
|
+
search?: string;
|
|
26
|
+
/** Screenshot provider plugin ID */
|
|
27
|
+
screenshot?: string;
|
|
28
|
+
/** AI provider plugin ID */
|
|
29
|
+
ai?: string;
|
|
30
|
+
/** Content extractor provider plugin ID */
|
|
31
|
+
contentExtractor?: string;
|
|
32
|
+
/** Pipeline provider plugin ID */
|
|
33
|
+
pipeline?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Minimal core DTO for creating/triggering item generation.
|
|
38
|
+
* All pipeline-specific configuration is passed via pluginConfig.
|
|
39
|
+
*/
|
|
40
|
+
interface CreateItemsGeneratorDto {
|
|
41
|
+
/** Work name */
|
|
42
|
+
name: string;
|
|
43
|
+
/** Generation prompt */
|
|
44
|
+
prompt: string;
|
|
45
|
+
/** Optional AI model override */
|
|
46
|
+
model?: string;
|
|
47
|
+
/** Method for generation (create-update or recreate) */
|
|
48
|
+
generation_method?: GenerationMethod;
|
|
49
|
+
/** Whether to update with pull request */
|
|
50
|
+
update_with_pull_request?: boolean;
|
|
51
|
+
/** Website repository creation method */
|
|
52
|
+
website_repository_creation_method?: WebsiteRepositoryCreationMethod;
|
|
53
|
+
/** Provider selection */
|
|
54
|
+
providers?: ProvidersDto;
|
|
55
|
+
/** Plugin-specific configuration - structure defined by selected pipeline plugin */
|
|
56
|
+
pluginConfig?: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* DTO for updating items generator configuration
|
|
60
|
+
*/
|
|
61
|
+
interface UpdateItemsGeneratorDto {
|
|
62
|
+
/** Optional AI model override */
|
|
63
|
+
model?: string;
|
|
64
|
+
/** Method for generation (create-update or recreate) */
|
|
65
|
+
generation_method?: GenerationMethod;
|
|
66
|
+
/** Whether to update with pull request */
|
|
67
|
+
update_with_pull_request?: boolean;
|
|
68
|
+
/** Provider overrides (pipeline, ai, search, etc.) */
|
|
69
|
+
providers?: ProvidersDto;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* DTO for submitting a new item to a work
|
|
74
|
+
*
|
|
75
|
+
* Note: Either `category` (single) or `categories` (array) must be provided.
|
|
76
|
+
* The backend validates this with conditional validation.
|
|
77
|
+
*/
|
|
78
|
+
interface SubmitItemDto {
|
|
79
|
+
/** Item name */
|
|
80
|
+
name: string;
|
|
81
|
+
/** Item description */
|
|
82
|
+
description: string;
|
|
83
|
+
/** Source URL for the item */
|
|
84
|
+
source_url: string;
|
|
85
|
+
/** Primary category (required if categories is not provided) */
|
|
86
|
+
category?: string;
|
|
87
|
+
/** Additional categories (required if category is not provided) */
|
|
88
|
+
categories?: string[];
|
|
89
|
+
/** Tags for the item */
|
|
90
|
+
tags?: string[];
|
|
91
|
+
/** Whether item is featured */
|
|
92
|
+
featured?: boolean;
|
|
93
|
+
/** Display order */
|
|
94
|
+
order?: number;
|
|
95
|
+
/** Whether to pay and publish immediately */
|
|
96
|
+
pay_and_publish_now?: boolean;
|
|
97
|
+
/** URL-friendly slug */
|
|
98
|
+
slug?: string;
|
|
99
|
+
/** Brand name */
|
|
100
|
+
brand?: string;
|
|
101
|
+
/** Brand logo URL */
|
|
102
|
+
brand_logo_url?: string;
|
|
103
|
+
/** Item images */
|
|
104
|
+
images?: string[];
|
|
105
|
+
/** Whether to create a pull request */
|
|
106
|
+
create_pull_request?: boolean;
|
|
107
|
+
/** Long-form markdown body. Written to `data/<slug>/<slug>.md` and mirrored
|
|
108
|
+
* on the YAML `markdown` field. When omitted, the generator falls back
|
|
109
|
+
* to a stub built from name + description + source_url. */
|
|
110
|
+
markdown?: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* DTO for removing an item from a work
|
|
115
|
+
*/
|
|
116
|
+
interface RemoveItemDto {
|
|
117
|
+
/** Slug of the item to remove */
|
|
118
|
+
item_slug: string;
|
|
119
|
+
/** Reason for removal */
|
|
120
|
+
reason?: string;
|
|
121
|
+
/** Whether to create a pull request */
|
|
122
|
+
create_pull_request?: boolean;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* DTO for updating item metadata in a work
|
|
127
|
+
*/
|
|
128
|
+
interface UpdateItemDto {
|
|
129
|
+
/** Slug of the item to update */
|
|
130
|
+
item_slug: string;
|
|
131
|
+
/** Source URL */
|
|
132
|
+
source_url?: string;
|
|
133
|
+
/** Whether item is featured */
|
|
134
|
+
featured?: boolean;
|
|
135
|
+
/** Display order */
|
|
136
|
+
order?: number;
|
|
137
|
+
/** Whether to create a pull request */
|
|
138
|
+
create_pull_request?: boolean;
|
|
139
|
+
/** Long-form markdown body. When provided, replaces the existing
|
|
140
|
+
* `data/<slug>/<slug>.md` file and mirrors onto the YAML `markdown` field. */
|
|
141
|
+
markdown?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* DTO for manually checking a single item's source URL health.
|
|
146
|
+
*/
|
|
147
|
+
interface CheckItemHealthDto {
|
|
148
|
+
/** Slug of the item to check */
|
|
149
|
+
item_slug: string;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Response returned after checking a single item's source URL health.
|
|
153
|
+
*/
|
|
154
|
+
interface CheckItemHealthResponseDto {
|
|
155
|
+
status: 'success' | 'error';
|
|
156
|
+
item_slug: string;
|
|
157
|
+
item_name: string;
|
|
158
|
+
message: string;
|
|
159
|
+
item?: ItemData;
|
|
160
|
+
health?: ItemHealth;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* DTO for extracting item details from a URL
|
|
165
|
+
*/
|
|
166
|
+
interface ExtractItemDetailsDto {
|
|
167
|
+
/** Source URL to extract details from */
|
|
168
|
+
source_url: string;
|
|
169
|
+
/** Optional work context for provider resolution and usage attribution */
|
|
170
|
+
workId?: string;
|
|
171
|
+
/** Existing categories in the work for matching */
|
|
172
|
+
existing_categories?: string[];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Cadence options for work scheduled updates
|
|
177
|
+
*/
|
|
178
|
+
declare enum WorkScheduleCadence {
|
|
179
|
+
HOURLY = "hourly",
|
|
180
|
+
EVERY_3_HOURS = "every_3_hours",
|
|
181
|
+
EVERY_8_HOURS = "every_8_hours",
|
|
182
|
+
EVERY_12_HOURS = "every_12_hours",
|
|
183
|
+
DAILY = "daily",
|
|
184
|
+
WEEKLY = "weekly",
|
|
185
|
+
MONTHLY = "monthly"
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Status options for work schedule
|
|
189
|
+
*/
|
|
190
|
+
declare enum WorkScheduleStatus {
|
|
191
|
+
DISABLED = "disabled",
|
|
192
|
+
ACTIVE = "active",
|
|
193
|
+
PAUSED = "paused",
|
|
194
|
+
CANCELED = "canceled"
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Billing mode options for scheduled updates
|
|
198
|
+
*/
|
|
199
|
+
declare enum WorkScheduleBillingMode {
|
|
200
|
+
SUBSCRIPTION = "subscription",
|
|
201
|
+
USAGE = "usage"
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Status types for work generation
|
|
206
|
+
*/
|
|
207
|
+
declare enum GenerateStatusType {
|
|
208
|
+
GENERATING = "generating",
|
|
209
|
+
GENERATED = "generated",
|
|
210
|
+
ERROR = "error",
|
|
211
|
+
CANCELLED = "cancelled"
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Allowed cadence configuration for a work
|
|
216
|
+
*/
|
|
217
|
+
interface WorkScheduleAllowedCadence {
|
|
218
|
+
/** The cadence option */
|
|
219
|
+
cadence: WorkScheduleCadence;
|
|
220
|
+
/** Reason if not allowed */
|
|
221
|
+
reason?: string;
|
|
222
|
+
/** Whether this cadence uses pay-per-use billing */
|
|
223
|
+
payPerUse?: boolean;
|
|
224
|
+
/** Whether this cadence is allowed */
|
|
225
|
+
allowed: boolean;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Work schedule configuration and status
|
|
229
|
+
*/
|
|
230
|
+
interface WorkScheduleDto {
|
|
231
|
+
/** Current schedule status */
|
|
232
|
+
status: WorkScheduleStatus;
|
|
233
|
+
/** Whether the scheduled updates feature is currently available */
|
|
234
|
+
featureEnabled: boolean;
|
|
235
|
+
/** Whether this work is currently eligible to enable scheduled updates */
|
|
236
|
+
canEnable: boolean;
|
|
237
|
+
/** Machine-readable reason the schedule cannot currently be enabled */
|
|
238
|
+
blockingCode?: 'SCHEDULED_UPDATES_DISABLED' | 'INITIAL_WORK_SETUP_REQUIRED' | 'SOURCE_SYNC_UNSUPPORTED' | 'CONFIG_UNAVAILABLE';
|
|
239
|
+
/** Human-readable reason the schedule cannot currently be enabled */
|
|
240
|
+
blockingReason?: string;
|
|
241
|
+
/** Selected cadence (null if disabled) */
|
|
242
|
+
cadence: WorkScheduleCadence | null;
|
|
243
|
+
/** Billing mode */
|
|
244
|
+
billingMode: WorkScheduleBillingMode;
|
|
245
|
+
/** Next scheduled run time (ISO string) */
|
|
246
|
+
nextRunAt: string | null;
|
|
247
|
+
/** Last run time (ISO string) */
|
|
248
|
+
lastRunAt: string | null;
|
|
249
|
+
/** Status of last run */
|
|
250
|
+
lastRunStatus: GenerateStatusType | null;
|
|
251
|
+
/** Number of consecutive failures */
|
|
252
|
+
failureCount: number;
|
|
253
|
+
/** Max failures before auto-pause */
|
|
254
|
+
maxFailureBeforePause: number;
|
|
255
|
+
/** Whether to always create pull request */
|
|
256
|
+
alwaysCreatePullRequest: boolean;
|
|
257
|
+
/** Available cadence options */
|
|
258
|
+
allowedCadences: WorkScheduleAllowedCadence[];
|
|
259
|
+
/** User's plan code */
|
|
260
|
+
planCode?: string;
|
|
261
|
+
/** Whether subscriptions are enabled */
|
|
262
|
+
subscriptionsEnabled: boolean;
|
|
263
|
+
/** Provider overrides for scheduled runs (pipeline, ai, search, etc.) */
|
|
264
|
+
providerOverrides?: ProvidersDto | null;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Payload for updating work schedule
|
|
268
|
+
*/
|
|
269
|
+
interface UpdateWorkSchedulePayload {
|
|
270
|
+
/** Enable or disable schedule */
|
|
271
|
+
enable?: boolean;
|
|
272
|
+
/** Trigger an immediate run after saving the active schedule */
|
|
273
|
+
runImmediately?: boolean;
|
|
274
|
+
/** Schedule cadence */
|
|
275
|
+
cadence?: WorkScheduleCadence;
|
|
276
|
+
/** Billing mode */
|
|
277
|
+
billingMode?: WorkScheduleBillingMode;
|
|
278
|
+
/** Max failures before auto-pause */
|
|
279
|
+
maxFailureBeforePause?: number;
|
|
280
|
+
/** Always create pull request */
|
|
281
|
+
alwaysCreatePullRequest?: boolean;
|
|
282
|
+
/** Provider overrides for scheduled runs (pipeline, ai, search, etc.) */
|
|
283
|
+
providerOverrides?: ProvidersDto | null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
type WorkCurrentState = 'running' | 'paused' | 'idle';
|
|
287
|
+
type WorkDeploymentReadiness = 'ready' | 'pending' | 'unknown' | 'not_deployed';
|
|
288
|
+
type WorkDeploymentHealthSource = 'deployment_projection' | 'none';
|
|
289
|
+
interface WorkLastGenerationRunDto {
|
|
290
|
+
status: GenerateStatusType;
|
|
291
|
+
startedAt: string | null;
|
|
292
|
+
finishedAt: string | null;
|
|
293
|
+
}
|
|
294
|
+
interface WorkLastDeploymentRunDto {
|
|
295
|
+
status: string;
|
|
296
|
+
startedAt: string | null;
|
|
297
|
+
finishedAt: string | null;
|
|
298
|
+
}
|
|
299
|
+
interface WorkLastRunDto {
|
|
300
|
+
generation: WorkLastGenerationRunDto | null;
|
|
301
|
+
deployment: WorkLastDeploymentRunDto | null;
|
|
302
|
+
}
|
|
303
|
+
interface WorkCurrentDeploymentHealthDto {
|
|
304
|
+
readiness: WorkDeploymentReadiness;
|
|
305
|
+
source: WorkDeploymentHealthSource;
|
|
306
|
+
/** Null for legacy projections because they pre-date persisted probe timestamps. */
|
|
307
|
+
observedAt: string | null;
|
|
308
|
+
}
|
|
309
|
+
interface WorkCurrentHealthDto {
|
|
310
|
+
state: WorkCurrentState;
|
|
311
|
+
deployment: WorkCurrentDeploymentHealthDto;
|
|
312
|
+
}
|
|
313
|
+
interface WorkStatusProjectionDto {
|
|
314
|
+
lastRun: WorkLastRunDto;
|
|
315
|
+
currentHealth: WorkCurrentHealthDto;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Metrics from a generation run
|
|
320
|
+
*/
|
|
321
|
+
interface GenerationMetrics {
|
|
322
|
+
/** Number of URLs scanned */
|
|
323
|
+
urls_scanned?: number;
|
|
324
|
+
/** Number of pages processed */
|
|
325
|
+
pages_processed?: number;
|
|
326
|
+
/** Items extracted in current run */
|
|
327
|
+
items_extracted_current_run?: number;
|
|
328
|
+
/** New items added to store */
|
|
329
|
+
new_items_added_to_store?: number;
|
|
330
|
+
/** Total items in store */
|
|
331
|
+
total_items_in_store?: number;
|
|
332
|
+
/** Total tokens used */
|
|
333
|
+
total_tokens_used?: number;
|
|
334
|
+
/** Total cost */
|
|
335
|
+
total_cost?: number;
|
|
336
|
+
}
|
|
337
|
+
declare enum WorkHistoryActivityType {
|
|
338
|
+
GENERATION = "generation",
|
|
339
|
+
ITEM_ADDED = "item_added",
|
|
340
|
+
ITEM_UPDATED = "item_updated",
|
|
341
|
+
ITEM_REMOVED = "item_removed",
|
|
342
|
+
COMPARISON_ADDED = "comparison_added",
|
|
343
|
+
COMPARISON_REMOVED = "comparison_removed",
|
|
344
|
+
CATEGORY_CHANGE = "category_change",
|
|
345
|
+
TAG_CHANGE = "tag_change",
|
|
346
|
+
COLLECTION_CHANGE = "collection_change",
|
|
347
|
+
COMMUNITY_PR_MERGED = "community_pr_merged"
|
|
348
|
+
}
|
|
349
|
+
type WorkHistoryChangeEntityType = 'item' | 'comparison' | 'category' | 'tag' | 'collection';
|
|
350
|
+
type WorkHistoryChangeAction = 'added' | 'updated' | 'removed';
|
|
351
|
+
interface WorkHistoryChangeEntry {
|
|
352
|
+
entityType: WorkHistoryChangeEntityType;
|
|
353
|
+
action: WorkHistoryChangeAction;
|
|
354
|
+
name: string;
|
|
355
|
+
slug?: string;
|
|
356
|
+
fieldsChanged?: string[];
|
|
357
|
+
}
|
|
358
|
+
type GenerationLogLevel = 'info' | 'warn' | 'error' | 'debug';
|
|
359
|
+
type GenerationLogSource = 'pipeline' | 'orchestrator' | 'claude-code' | 'system';
|
|
360
|
+
interface GenerationStepLog {
|
|
361
|
+
timestamp: string;
|
|
362
|
+
level: GenerationLogLevel;
|
|
363
|
+
source: GenerationLogSource;
|
|
364
|
+
stepIndex?: number | null;
|
|
365
|
+
stepName?: string | null;
|
|
366
|
+
event: 'step_started' | 'step_completed' | 'step_failed' | 'step_skipped' | 'message';
|
|
367
|
+
message: string;
|
|
368
|
+
durationMs?: number | null;
|
|
369
|
+
}
|
|
370
|
+
interface WorkChangelog {
|
|
371
|
+
summary?: string | null;
|
|
372
|
+
addedCount: number;
|
|
373
|
+
updatedCount: number;
|
|
374
|
+
removedCount: number;
|
|
375
|
+
entries: WorkHistoryChangeEntry[];
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* Entry in work generation history
|
|
379
|
+
*/
|
|
380
|
+
interface WorkGenerationHistoryEntry {
|
|
381
|
+
/** History entry ID */
|
|
382
|
+
id: string;
|
|
383
|
+
/** Generation status */
|
|
384
|
+
status: GenerateStatusType;
|
|
385
|
+
/** Generation method used */
|
|
386
|
+
generationMethod?: GenerationMethod | null;
|
|
387
|
+
/** When generation started (ISO string) */
|
|
388
|
+
startedAt?: string | null;
|
|
389
|
+
/** When generation finished (ISO string) */
|
|
390
|
+
finishedAt?: string | null;
|
|
391
|
+
/** Duration in seconds */
|
|
392
|
+
durationInSeconds?: number | null;
|
|
393
|
+
/** Number of new items */
|
|
394
|
+
newItemsCount: number;
|
|
395
|
+
/** Number of updated items */
|
|
396
|
+
updatedItemsCount: number;
|
|
397
|
+
/** Total items count */
|
|
398
|
+
totalItemsCount: number;
|
|
399
|
+
/** Generation metrics */
|
|
400
|
+
metrics?: GenerationMetrics | null;
|
|
401
|
+
/** Error message if failed */
|
|
402
|
+
errorMessage?: string | null;
|
|
403
|
+
/** Generation parameters used */
|
|
404
|
+
parameters?: CreateItemsGeneratorDto | null;
|
|
405
|
+
/** Created timestamp (ISO string) */
|
|
406
|
+
createdAt: string;
|
|
407
|
+
/** Updated timestamp (ISO string) */
|
|
408
|
+
updatedAt: string;
|
|
409
|
+
/** Trigger.dev run ID */
|
|
410
|
+
triggerRunId?: string;
|
|
411
|
+
/** History activity type */
|
|
412
|
+
activityType: WorkHistoryActivityType;
|
|
413
|
+
/** Structured changelog details */
|
|
414
|
+
changelog?: WorkChangelog | null;
|
|
415
|
+
/** Step-level generation logs */
|
|
416
|
+
logs?: GenerationStepLog[] | null;
|
|
417
|
+
/** Warnings captured during generation */
|
|
418
|
+
warnings?: string[] | null;
|
|
419
|
+
/** What triggered this run */
|
|
420
|
+
triggeredBy?: 'user' | 'schedule' | 'api' | null;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Response for work generation history
|
|
424
|
+
*/
|
|
425
|
+
interface WorkGenerationHistoryResponse {
|
|
426
|
+
/** History entries */
|
|
427
|
+
history: WorkGenerationHistoryEntry[];
|
|
428
|
+
/** Total count */
|
|
429
|
+
total: number;
|
|
430
|
+
/** Pagination limit */
|
|
431
|
+
limit: number;
|
|
432
|
+
/** Pagination offset */
|
|
433
|
+
offset: number;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
interface UpdateSourceValidationPayload {
|
|
437
|
+
enabled: boolean;
|
|
438
|
+
cadence?: WorkScheduleCadence;
|
|
439
|
+
}
|
|
440
|
+
interface SourceValidationSettingsDto {
|
|
441
|
+
enabled: boolean;
|
|
442
|
+
cadence: WorkScheduleCadence | null;
|
|
443
|
+
nextRunAt: string | null;
|
|
444
|
+
lastRunAt: string | null;
|
|
445
|
+
allowedCadences: WorkScheduleAllowedCadence[];
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
declare const IMPORT_SOURCE_TYPES: readonly ["data_repo", "awesome_readme", "link_existing", "works_config"];
|
|
449
|
+
type ImportSourceType = (typeof IMPORT_SOURCE_TYPES)[number];
|
|
450
|
+
declare const AWESOME_README_IMPORT_MODES: readonly ["clone", "reuse_source"];
|
|
451
|
+
type AwesomeReadmeImportMode = (typeof AWESOME_README_IMPORT_MODES)[number];
|
|
452
|
+
type RepositoryRole = 'data' | 'work' | 'website';
|
|
453
|
+
interface RepositoryTarget {
|
|
454
|
+
owner?: string;
|
|
455
|
+
repo: string;
|
|
456
|
+
}
|
|
457
|
+
interface RelatedRepositories {
|
|
458
|
+
data?: RepositoryTarget;
|
|
459
|
+
work?: RepositoryTarget;
|
|
460
|
+
website?: RepositoryTarget;
|
|
461
|
+
}
|
|
462
|
+
interface WorksConfigSnapshot {
|
|
463
|
+
name?: string;
|
|
464
|
+
initialPrompt?: string;
|
|
465
|
+
model?: string;
|
|
466
|
+
websiteRepo?: string;
|
|
467
|
+
scheduleCadence?: WorkScheduleCadence | null;
|
|
468
|
+
providers?: ProvidersDto;
|
|
469
|
+
}
|
|
470
|
+
interface SourceRepository<TImportedAt = string> {
|
|
471
|
+
url: string;
|
|
472
|
+
owner: string;
|
|
473
|
+
repo: string;
|
|
474
|
+
type: ImportSourceType;
|
|
475
|
+
importedAt: TImportedAt;
|
|
476
|
+
relatedRepositories?: RelatedRepositories;
|
|
477
|
+
worksConfig?: WorksConfigSnapshot;
|
|
478
|
+
}
|
|
479
|
+
interface RepoVisibility {
|
|
480
|
+
data: boolean;
|
|
481
|
+
website: boolean;
|
|
482
|
+
work: boolean;
|
|
483
|
+
}
|
|
484
|
+
interface ImportEnrichmentConfig {
|
|
485
|
+
expansionFactor?: number;
|
|
486
|
+
}
|
|
487
|
+
interface AnalyzeRepositoryResponseDto {
|
|
488
|
+
sourceUrl: string;
|
|
489
|
+
owner: string;
|
|
490
|
+
repo: string;
|
|
491
|
+
detectedType: ImportSourceType | null;
|
|
492
|
+
isPublic: boolean;
|
|
493
|
+
requiresAuth: boolean;
|
|
494
|
+
structure?: {
|
|
495
|
+
hasDataFolder: boolean;
|
|
496
|
+
hasConfig: boolean;
|
|
497
|
+
hasReadme: boolean;
|
|
498
|
+
hasWorksConfig?: boolean;
|
|
499
|
+
isMultiFile?: boolean;
|
|
500
|
+
itemCount?: number;
|
|
501
|
+
categoryCount?: number;
|
|
502
|
+
};
|
|
503
|
+
worksConfig?: WorksConfigSnapshot;
|
|
504
|
+
relatedDataRepo?: {
|
|
505
|
+
name: string;
|
|
506
|
+
owner: string;
|
|
507
|
+
};
|
|
508
|
+
baseSlug?: string;
|
|
509
|
+
slugConflict?: {
|
|
510
|
+
hasConflict: boolean;
|
|
511
|
+
conflictingRepos: string[];
|
|
512
|
+
suggestedSlug: string;
|
|
513
|
+
};
|
|
514
|
+
hasDataRepoWriteAccess?: boolean;
|
|
515
|
+
error?: string;
|
|
516
|
+
}
|
|
517
|
+
interface ImportWorkDto {
|
|
518
|
+
sourceUrl: string;
|
|
519
|
+
sourceType: ImportSourceType;
|
|
520
|
+
awesomeReadmeImportMode?: AwesomeReadmeImportMode;
|
|
521
|
+
name: string;
|
|
522
|
+
owner?: string;
|
|
523
|
+
organization?: boolean;
|
|
524
|
+
gitProvider: string;
|
|
525
|
+
deployProvider?: string;
|
|
526
|
+
createMissingRepos?: boolean;
|
|
527
|
+
sync?: boolean;
|
|
528
|
+
providers?: ProvidersDto;
|
|
529
|
+
restoreWorksConfig?: boolean;
|
|
530
|
+
enrichmentConfig?: ImportEnrichmentConfig;
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Public request shape for POST /api/register-work and the equivalent
|
|
535
|
+
* register_work MCP tool. The GitHub credential is NOT part of this body —
|
|
536
|
+
* it travels in the X-GitHub-Token header (REST) or as a sibling tool
|
|
537
|
+
* argument that is redacted from logs (MCP).
|
|
538
|
+
*/
|
|
539
|
+
interface RegisterWorkRequest {
|
|
540
|
+
/** HTTPS GitHub repo URL containing .works/works.yml at root. */
|
|
541
|
+
repo: string;
|
|
542
|
+
/** Optional contact email. */
|
|
543
|
+
email?: string;
|
|
544
|
+
/** Optional opaque agent identifier (printable ASCII, ≤256 chars). */
|
|
545
|
+
agentId?: string;
|
|
546
|
+
/** Optional HTTPS URL for signed terminal-status webhooks. */
|
|
547
|
+
webhookUrl?: string;
|
|
548
|
+
/** Optional DNS-safe slug for the assigned subdomain. */
|
|
549
|
+
subdomain?: string;
|
|
550
|
+
/**
|
|
551
|
+
* Reserved for v2 paid plane — accepts x402, Skyfire, Crossmint, or
|
|
552
|
+
* Stripe Agent payment envelopes. Ignored at v1.
|
|
553
|
+
*/
|
|
554
|
+
agentPayment?: Record<string, unknown>;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Item-source variants understood by the manifest at v1. Mirrors the YAML
|
|
558
|
+
* shape documented in docs/specs/features/agent-zero-friction-onboarding/manifest-schema.md.
|
|
559
|
+
*/
|
|
560
|
+
type OnboardingRequestSource = OnboardingRequestSourceAwesomeReadme | OnboardingRequestSourceWebSearch | OnboardingRequestSourceDataRepo | OnboardingRequestSourceInline;
|
|
561
|
+
interface OnboardingRequestSourceAwesomeReadme {
|
|
562
|
+
type: 'awesome-readme';
|
|
563
|
+
url: string;
|
|
564
|
+
expansionFactor?: number;
|
|
565
|
+
}
|
|
566
|
+
interface OnboardingRequestSourceWebSearch {
|
|
567
|
+
type: 'web-search';
|
|
568
|
+
query: string;
|
|
569
|
+
max?: number;
|
|
570
|
+
}
|
|
571
|
+
interface OnboardingRequestSourceDataRepo {
|
|
572
|
+
type: 'data-repo';
|
|
573
|
+
url: string;
|
|
574
|
+
mode?: 'copy' | 'link';
|
|
575
|
+
}
|
|
576
|
+
interface OnboardingRequestSourceInline {
|
|
577
|
+
type: 'inline';
|
|
578
|
+
items: ReadonlyArray<{
|
|
579
|
+
name: string;
|
|
580
|
+
url?: string;
|
|
581
|
+
categories?: ReadonlyArray<string>;
|
|
582
|
+
tags?: ReadonlyArray<string>;
|
|
583
|
+
description?: string;
|
|
584
|
+
}>;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
type OnboardingStatus = 'received' | 'validating' | 'validated' | 'queued' | 'generating' | 'deployed' | 'failed' | 'rejected';
|
|
588
|
+
declare const ONBOARDING_TERMINAL_STATUSES: ReadonlyArray<OnboardingStatus>;
|
|
589
|
+
/**
|
|
590
|
+
* Whether an {@link OnboardingStatus} marks the end of the onboarding
|
|
591
|
+
* flow — i.e. the status will not transition further. Currently
|
|
592
|
+
* `'deployed'` (success), `'failed'` (generic error), and `'rejected'`
|
|
593
|
+
* (input refused upfront) per {@link ONBOARDING_TERMINAL_STATUSES}.
|
|
594
|
+
* Callers polling for completion should stop polling once this returns
|
|
595
|
+
* `true`.
|
|
596
|
+
*
|
|
597
|
+
* @param status - The status to test.
|
|
598
|
+
* @returns `true` when the onboarding flow has ended for this status.
|
|
599
|
+
*/
|
|
600
|
+
declare function isTerminalOnboardingStatus(status: OnboardingStatus): boolean;
|
|
601
|
+
|
|
602
|
+
type RegisterWorkStatus = OnboardingStatus;
|
|
603
|
+
interface RegisterWorkResponse {
|
|
604
|
+
onboardingId: string;
|
|
605
|
+
workId: string;
|
|
606
|
+
status: RegisterWorkStatus;
|
|
607
|
+
statusUrl: string;
|
|
608
|
+
subdomain: string;
|
|
609
|
+
deploymentUrl?: string;
|
|
610
|
+
warnings?: ReadonlyArray<string>;
|
|
611
|
+
}
|
|
612
|
+
type RegisterWorkErrorCode = 'validation_error' | 'gh_repo_access_denied' | 'gh_credential_invalid' | 'gh_insufficient_scope_for_repo_creation' | 'manifest_missing' | 'manifest_invalid' | 'unsupported_capability' | 'repo_already_owned' | 'subdomain_taken' | 'rate_limited' | 'internal_error';
|
|
613
|
+
interface ManifestValidationError {
|
|
614
|
+
path: string;
|
|
615
|
+
message: string;
|
|
616
|
+
subcode?: string;
|
|
617
|
+
}
|
|
618
|
+
interface RegisterWorkErrorBody {
|
|
619
|
+
statusCode: number;
|
|
620
|
+
code: RegisterWorkErrorCode;
|
|
621
|
+
message: string;
|
|
622
|
+
errors?: ReadonlyArray<ManifestValidationError>;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
type WebhookEvent = WebhookEventTerminal | WebhookEventManifestChanged | WebhookEventDeployFailed;
|
|
626
|
+
interface WebhookEventTerminal {
|
|
627
|
+
event: 'onboarding.terminal';
|
|
628
|
+
deliveryId: string;
|
|
629
|
+
occurredAt: string;
|
|
630
|
+
onboardingId: string;
|
|
631
|
+
workId: string;
|
|
632
|
+
status: Extract<OnboardingStatus, 'deployed' | 'failed' | 'rejected'>;
|
|
633
|
+
subdomain: string;
|
|
634
|
+
deploymentUrl?: string;
|
|
635
|
+
failureCode?: string;
|
|
636
|
+
failureMessage?: string;
|
|
637
|
+
}
|
|
638
|
+
interface WebhookEventManifestChanged {
|
|
639
|
+
event: 'work.regenerated';
|
|
640
|
+
deliveryId: string;
|
|
641
|
+
occurredAt: string;
|
|
642
|
+
workId: string;
|
|
643
|
+
commitSha: string;
|
|
644
|
+
}
|
|
645
|
+
interface WebhookEventDeployFailed {
|
|
646
|
+
event: 'work.deploy_failed';
|
|
647
|
+
deliveryId: string;
|
|
648
|
+
occurredAt: string;
|
|
649
|
+
workId: string;
|
|
650
|
+
failureCode: string;
|
|
651
|
+
failureMessage: string;
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
interface WorksManifestMetadata {
|
|
655
|
+
name: string;
|
|
656
|
+
slug?: string;
|
|
657
|
+
description?: string;
|
|
658
|
+
subdomain?: string;
|
|
659
|
+
}
|
|
660
|
+
interface WorksManifestSpec {
|
|
661
|
+
pipeline: string;
|
|
662
|
+
domain: 'software' | 'ecommerce' | 'services' | 'general';
|
|
663
|
+
taxonomy?: {
|
|
664
|
+
categories?: ReadonlyArray<string>;
|
|
665
|
+
tags?: ReadonlyArray<string>;
|
|
666
|
+
lockTaxonomy?: boolean;
|
|
667
|
+
};
|
|
668
|
+
items: {
|
|
669
|
+
sources: ReadonlyArray<OnboardingRequestSource>;
|
|
670
|
+
};
|
|
671
|
+
generators?: {
|
|
672
|
+
aiProvider?: string;
|
|
673
|
+
searchProvider?: string;
|
|
674
|
+
screenshot?: string;
|
|
675
|
+
model?: string;
|
|
676
|
+
};
|
|
677
|
+
deployment?: {
|
|
678
|
+
target?: string;
|
|
679
|
+
customDomain?: string;
|
|
680
|
+
};
|
|
681
|
+
output?: WorksManifestOutput;
|
|
682
|
+
}
|
|
683
|
+
interface WorksManifestOutput {
|
|
684
|
+
repos?: {
|
|
685
|
+
website?: 'managed' | 'none';
|
|
686
|
+
awesomeList?: 'managed' | 'none';
|
|
687
|
+
};
|
|
688
|
+
llmsTxt?: boolean;
|
|
689
|
+
itemsJson?: boolean;
|
|
690
|
+
markerFile?: string;
|
|
691
|
+
}
|
|
692
|
+
interface WorksManifestV1 {
|
|
693
|
+
apiVersion: 'works.ever.works/v1';
|
|
694
|
+
kind: 'Work';
|
|
695
|
+
metadata: WorksManifestMetadata;
|
|
696
|
+
spec: WorksManifestSpec;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* Wire format for the onboarding wizard's server-side state.
|
|
701
|
+
*
|
|
702
|
+
* Persisted on `users.onboarding_state` (jsonb / simple-json). The web
|
|
703
|
+
* wizard loads this on dashboard mount and PATCHes it on every step
|
|
704
|
+
* transition so progress survives a cookie wipe or device switch.
|
|
705
|
+
*/
|
|
706
|
+
type OnboardingAiChoice = 'ever-works' | 'openrouter' | 'claude-code' | 'codex' | 'gemini' | 'grok';
|
|
707
|
+
type OnboardingStorageChoice = 'ever-works-git' | 'user-github' | 'user-gitlab' | 'user-git';
|
|
708
|
+
/**
|
|
709
|
+
* Where a Work's database lives: the platform-managed "Ever Works DB" (shared,
|
|
710
|
+
* auto-provisioned) or a bring-your-own custom database (connection details are
|
|
711
|
+
* entered on the Deploy page after the Work is created — never stored in this
|
|
712
|
+
* onboarding-state blob).
|
|
713
|
+
*/
|
|
714
|
+
type OnboardingDbChoice = 'ever-works-db' | 'custom';
|
|
715
|
+
type OnboardingDeployChoice = 'ever-works' | 'vercel' | 'k8s';
|
|
716
|
+
/**
|
|
717
|
+
* A8 — where the user actually runs Ever Works, and therefore what their
|
|
718
|
+
* first run should look like.
|
|
719
|
+
*
|
|
720
|
+
* The other four buckets all ask "which provider": AI, storage, database,
|
|
721
|
+
* deployment. None of them ask the question a desktop-first user is actually
|
|
722
|
+
* living — "is this thing running on my machine, and are my machines part of
|
|
723
|
+
* it?" — so those users landed on a cloud-shaped first run and had to find
|
|
724
|
+
* Fleet and the node apps on their own.
|
|
725
|
+
*
|
|
726
|
+
* - `cloud` the hosted platform (default; unchanged behaviour)
|
|
727
|
+
* - `desktop` the all-in-one desktop app supervising a local stack
|
|
728
|
+
* - `own-nodes` the platform runs elsewhere, but this person's own
|
|
729
|
+
* machines execute the work (Fleet + node apps)
|
|
730
|
+
*/
|
|
731
|
+
type OnboardingDesktopChoice = 'cloud' | 'desktop' | 'own-nodes';
|
|
732
|
+
/**
|
|
733
|
+
* Wave 11 — "What do you do" onboarding step. A generic option row:
|
|
734
|
+
* stable kebab-case id + English display label + one-line description.
|
|
735
|
+
* The web wizard renders these through i18n keys keyed by `id`; the
|
|
736
|
+
* label/description here are the canonical English fallback used by
|
|
737
|
+
* non-web surfaces (desktop embeds, API docs).
|
|
738
|
+
*/
|
|
739
|
+
interface OnboardingProfileOption<Id extends string = string> {
|
|
740
|
+
readonly id: Id;
|
|
741
|
+
readonly label: string;
|
|
742
|
+
readonly description: string;
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Roles for the "What do you do" step (multi-select — picking several
|
|
746
|
+
* or all is fine). Selections are hints for suggestion surfaces, never
|
|
747
|
+
* gates: nothing is hidden based on them.
|
|
748
|
+
*/
|
|
749
|
+
declare const ROLE_OPTIONS: readonly [{
|
|
750
|
+
readonly id: "founder-ceo";
|
|
751
|
+
readonly label: "Founder / CEO";
|
|
752
|
+
readonly description: "I run the company and wear many hats";
|
|
753
|
+
}, {
|
|
754
|
+
readonly id: "engineering";
|
|
755
|
+
readonly label: "Engineering";
|
|
756
|
+
readonly description: "I build and ship software";
|
|
757
|
+
}, {
|
|
758
|
+
readonly id: "product";
|
|
759
|
+
readonly label: "Product";
|
|
760
|
+
readonly description: "I define what we build and why";
|
|
761
|
+
}, {
|
|
762
|
+
readonly id: "marketing";
|
|
763
|
+
readonly label: "Marketing";
|
|
764
|
+
readonly description: "I grow awareness, content, and campaigns";
|
|
765
|
+
}, {
|
|
766
|
+
readonly id: "sales";
|
|
767
|
+
readonly label: "Sales";
|
|
768
|
+
readonly description: "I find, pitch, and close customers";
|
|
769
|
+
}, {
|
|
770
|
+
readonly id: "consultant";
|
|
771
|
+
readonly label: "Consultant";
|
|
772
|
+
readonly description: "I deliver projects and advice for clients";
|
|
773
|
+
}, {
|
|
774
|
+
readonly id: "research";
|
|
775
|
+
readonly label: "Research";
|
|
776
|
+
readonly description: "I investigate, analyze, and synthesize";
|
|
777
|
+
}, {
|
|
778
|
+
readonly id: "operations";
|
|
779
|
+
readonly label: "Operations";
|
|
780
|
+
readonly description: "I keep the business running smoothly";
|
|
781
|
+
}, {
|
|
782
|
+
readonly id: "support";
|
|
783
|
+
readonly label: "Support";
|
|
784
|
+
readonly description: "I help customers succeed and resolve issues";
|
|
785
|
+
}, {
|
|
786
|
+
readonly id: "finance";
|
|
787
|
+
readonly label: "Finance";
|
|
788
|
+
readonly description: "I manage budgets, billing, and reporting";
|
|
789
|
+
}, {
|
|
790
|
+
readonly id: "hr";
|
|
791
|
+
readonly label: "HR";
|
|
792
|
+
readonly description: "I hire, onboard, and support our people";
|
|
793
|
+
}, {
|
|
794
|
+
readonly id: "legal";
|
|
795
|
+
readonly label: "Legal";
|
|
796
|
+
readonly description: "I handle contracts, compliance, and policy";
|
|
797
|
+
}, {
|
|
798
|
+
readonly id: "education";
|
|
799
|
+
readonly label: "Education";
|
|
800
|
+
readonly description: "I teach, train, or create learning content";
|
|
801
|
+
}, {
|
|
802
|
+
readonly id: "other";
|
|
803
|
+
readonly label: "Other";
|
|
804
|
+
readonly description: "Something else — tell us more later";
|
|
805
|
+
}];
|
|
806
|
+
type OnboardingRoleId = (typeof ROLE_OPTIONS)[number]['id'];
|
|
807
|
+
/** Team size for the "What do you do" step (single-select). */
|
|
808
|
+
declare const TEAM_SIZE_OPTIONS: readonly [{
|
|
809
|
+
readonly id: "solo";
|
|
810
|
+
readonly label: "Solo";
|
|
811
|
+
readonly description: "Just me";
|
|
812
|
+
}, {
|
|
813
|
+
readonly id: "small-2-10";
|
|
814
|
+
readonly label: "Small (2–10)";
|
|
815
|
+
readonly description: "2–10 people";
|
|
816
|
+
}, {
|
|
817
|
+
readonly id: "mid-11-50";
|
|
818
|
+
readonly label: "Mid (11–50)";
|
|
819
|
+
readonly description: "11–50 people";
|
|
820
|
+
}, {
|
|
821
|
+
readonly id: "large-51-200";
|
|
822
|
+
readonly label: "Large (51–200)";
|
|
823
|
+
readonly description: "51–200 people";
|
|
824
|
+
}, {
|
|
825
|
+
readonly id: "enterprise-200-plus";
|
|
826
|
+
readonly label: "Enterprise (200+)";
|
|
827
|
+
readonly description: "More than 200 people";
|
|
828
|
+
}];
|
|
829
|
+
type OnboardingTeamSizeId = (typeof TEAM_SIZE_OPTIONS)[number]['id'];
|
|
830
|
+
/**
|
|
831
|
+
* Wave 11 — persisted answers of the "What do you do" step. Values are
|
|
832
|
+
* plain strings (not the narrowed id unions) so older clients keep
|
|
833
|
+
* round-tripping payloads written by newer ones; consumers validate
|
|
834
|
+
* against ROLE_OPTIONS / TEAM_SIZE_OPTIONS and DROP unrecognised values
|
|
835
|
+
* (never default them).
|
|
836
|
+
*/
|
|
837
|
+
interface OnboardingProfile {
|
|
838
|
+
readonly roles?: readonly string[];
|
|
839
|
+
readonly teamSize?: string;
|
|
840
|
+
}
|
|
841
|
+
interface OnboardingWizardStateV2 {
|
|
842
|
+
readonly version: 2;
|
|
843
|
+
readonly lastStep: number;
|
|
844
|
+
readonly ai: {
|
|
845
|
+
readonly choice: OnboardingAiChoice;
|
|
846
|
+
};
|
|
847
|
+
readonly storage: {
|
|
848
|
+
readonly choice: OnboardingStorageChoice;
|
|
849
|
+
};
|
|
850
|
+
readonly db: {
|
|
851
|
+
readonly choice: OnboardingDbChoice;
|
|
852
|
+
};
|
|
853
|
+
readonly deploy: {
|
|
854
|
+
readonly choice: OnboardingDeployChoice;
|
|
855
|
+
};
|
|
856
|
+
/**
|
|
857
|
+
* A8 — desktop-first bucket. Optional in the persisted shape so a state
|
|
858
|
+
* blob written before this bucket existed keeps round-tripping; readers
|
|
859
|
+
* fall back to {@link ONBOARDING_DEFAULT_STATE}'s `cloud`.
|
|
860
|
+
*/
|
|
861
|
+
readonly desktop?: {
|
|
862
|
+
readonly choice: OnboardingDesktopChoice;
|
|
863
|
+
};
|
|
864
|
+
readonly skippedSteps: readonly string[];
|
|
865
|
+
readonly pluginsReviewed: boolean;
|
|
866
|
+
/**
|
|
867
|
+
* EW-617 G4: prompt carried over from the landing-page input
|
|
868
|
+
* (`ever.works/?prompt=…`) so the wizard's "Generate now" step can
|
|
869
|
+
* kick off generation without re-asking the user. Bounded by the
|
|
870
|
+
* same 5000-char limit as `CreateItemsGeneratorDto.prompt`.
|
|
871
|
+
*/
|
|
872
|
+
readonly prompt?: string;
|
|
873
|
+
/** Wave 11 — optional "What do you do" answers (roles + team size). */
|
|
874
|
+
readonly profile?: OnboardingProfile;
|
|
875
|
+
}
|
|
876
|
+
/** Wire shape of `GET /api/onboarding/state`. */
|
|
877
|
+
interface OnboardingStateResponse {
|
|
878
|
+
readonly completedAt: string | null;
|
|
879
|
+
readonly dismissedAt: string | null;
|
|
880
|
+
readonly state: OnboardingWizardStateV2;
|
|
881
|
+
/**
|
|
882
|
+
* Audit item A53 — the ORGANIZATION-level mirror of the "What do you
|
|
883
|
+
* do" answers, persisted on `organization_onboarding_profiles`.
|
|
884
|
+
*
|
|
885
|
+
* `state.profile` above stays the per-user answer that drives the
|
|
886
|
+
* wizard UI; this field is the org-wide read model (last writer
|
|
887
|
+
* inside the organization wins) so team-shaped suggestion surfaces
|
|
888
|
+
* can reason about the whole organization rather than one member.
|
|
889
|
+
*
|
|
890
|
+
* `null` when the request resolved no organization scope (e.g. a
|
|
891
|
+
* user who has not created an Organization yet) or when nobody in
|
|
892
|
+
* the organization has answered the step. Optional so older clients
|
|
893
|
+
* and the web fallback payloads keep type-checking unchanged.
|
|
894
|
+
*/
|
|
895
|
+
readonly organizationProfile?: OnboardingProfile | null;
|
|
896
|
+
}
|
|
897
|
+
/**
|
|
898
|
+
* Wire shape of `PATCH /api/onboarding/state`. All fields are optional;
|
|
899
|
+
* `state` accepts a partial object that the server deep-merges with the
|
|
900
|
+
* persisted version-2 shape (re-using existing values for missing keys).
|
|
901
|
+
*
|
|
902
|
+
* Security: `state.prompt` MUST be validated server-side with
|
|
903
|
+
* `@MaxLength(5000)` in `OnboardingStatePatchInnerDto` before it is
|
|
904
|
+
* persisted or forwarded to any LLM call. Do NOT wire user-controlled
|
|
905
|
+
* prompt text into agent generation without output constraints/sandboxing.
|
|
906
|
+
*/
|
|
907
|
+
interface OnboardingStatePatchRequest {
|
|
908
|
+
readonly state?: Partial<{
|
|
909
|
+
readonly lastStep: number;
|
|
910
|
+
readonly ai: Partial<{
|
|
911
|
+
choice: OnboardingAiChoice;
|
|
912
|
+
}>;
|
|
913
|
+
readonly storage: Partial<{
|
|
914
|
+
choice: OnboardingStorageChoice;
|
|
915
|
+
}>;
|
|
916
|
+
readonly db: Partial<{
|
|
917
|
+
choice: OnboardingDbChoice;
|
|
918
|
+
}>;
|
|
919
|
+
readonly deploy: Partial<{
|
|
920
|
+
choice: OnboardingDeployChoice;
|
|
921
|
+
}>;
|
|
922
|
+
/** A8 — desktop-first bucket. */
|
|
923
|
+
readonly desktop: Partial<{
|
|
924
|
+
choice: OnboardingDesktopChoice;
|
|
925
|
+
}>;
|
|
926
|
+
readonly skippedSteps: readonly string[];
|
|
927
|
+
readonly pluginsReviewed: boolean;
|
|
928
|
+
/** Max 5 000 chars — enforced by `@MaxLength(5000)` in the server DTO. */
|
|
929
|
+
readonly prompt: string;
|
|
930
|
+
/**
|
|
931
|
+
* Wave 11 — "What do you do" answers. `roles` entries are validated
|
|
932
|
+
* server-side against ROLE_OPTIONS ids, `teamSize` against
|
|
933
|
+
* TEAM_SIZE_OPTIONS ids (unknown values are rejected with 400).
|
|
934
|
+
*/
|
|
935
|
+
readonly profile: {
|
|
936
|
+
readonly roles?: readonly string[];
|
|
937
|
+
readonly teamSize?: string;
|
|
938
|
+
};
|
|
939
|
+
}>;
|
|
940
|
+
}
|
|
941
|
+
/** Wire shape of `GET /api/onboarding/catalog`. */
|
|
942
|
+
interface OnboardingCatalogResponse {
|
|
943
|
+
readonly ai: ReadonlyArray<OnboardingCard<OnboardingAiChoice>>;
|
|
944
|
+
readonly storage: ReadonlyArray<OnboardingCard<OnboardingStorageChoice>>;
|
|
945
|
+
readonly db: ReadonlyArray<OnboardingCard<OnboardingDbChoice>>;
|
|
946
|
+
readonly deploy: ReadonlyArray<OnboardingCard<OnboardingDeployChoice>>;
|
|
947
|
+
/** A8 — cards for the desktop-first bucket. */
|
|
948
|
+
readonly desktop: ReadonlyArray<OnboardingCard<OnboardingDesktopChoice>>;
|
|
949
|
+
/** Plugins to surface in the "Plugins & Integrations" wizard step. */
|
|
950
|
+
readonly plugins: ReadonlyArray<OnboardingPluginCard>;
|
|
951
|
+
}
|
|
952
|
+
interface OnboardingCard<Choice extends string> {
|
|
953
|
+
readonly choice: Choice;
|
|
954
|
+
readonly title: string;
|
|
955
|
+
readonly description: string;
|
|
956
|
+
readonly default: boolean;
|
|
957
|
+
readonly available: boolean;
|
|
958
|
+
readonly badges: ReadonlyArray<OnboardingCardBadge>;
|
|
959
|
+
/** Plugin id behind this card, when applicable. */
|
|
960
|
+
readonly pluginId?: string;
|
|
961
|
+
}
|
|
962
|
+
type OnboardingCardBadge = 'default' | 'byok' | 'planned';
|
|
963
|
+
interface OnboardingPluginCard {
|
|
964
|
+
readonly pluginId: string;
|
|
965
|
+
readonly name: string;
|
|
966
|
+
readonly category: string;
|
|
967
|
+
readonly description: string;
|
|
968
|
+
readonly onboardingPriority: number;
|
|
969
|
+
}
|
|
970
|
+
declare const ONBOARDING_DEFAULT_STATE: OnboardingWizardStateV2;
|
|
971
|
+
/**
|
|
972
|
+
* A8 — first-run guidance implied by the desktop bucket. Consumed by the web
|
|
973
|
+
* wizard's final step (and any other surface that wants to point a user at the
|
|
974
|
+
* right next thing) so "which shape am I running" actually changes what the
|
|
975
|
+
* user is told to do next, rather than being a stored preference nobody reads.
|
|
976
|
+
*/
|
|
977
|
+
interface OnboardingDesktopNextStep {
|
|
978
|
+
readonly choice: OnboardingDesktopChoice;
|
|
979
|
+
readonly title: string;
|
|
980
|
+
readonly description: string;
|
|
981
|
+
/** In-app route to send the user to, when there is one. */
|
|
982
|
+
readonly href?: string;
|
|
983
|
+
}
|
|
984
|
+
declare const ONBOARDING_DESKTOP_NEXT_STEPS: Readonly<Record<OnboardingDesktopChoice, OnboardingDesktopNextStep>>;
|
|
985
|
+
/** The guidance for a bucket choice, defaulting to the cloud path. */
|
|
986
|
+
declare function desktopNextStep(choice: OnboardingDesktopChoice | undefined): OnboardingDesktopNextStep;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* AW-20 P1 — the roster vocabulary shared by the API, the agent package
|
|
990
|
+
* and the web wizard step.
|
|
991
|
+
*
|
|
992
|
+
* A **roster** is not a new entity: it is the set of Agents the platform
|
|
993
|
+
* provisions for one person in one workspace scope, each carrying a
|
|
994
|
+
* **lane**. Everything here is a closed vocabulary so the wizard, the
|
|
995
|
+
* provisioning service and the DTO validators cannot drift apart — the
|
|
996
|
+
* same trick `ROLE_OPTIONS` / `TEAM_SIZE_OPTIONS` already use one file
|
|
997
|
+
* over.
|
|
998
|
+
*/
|
|
999
|
+
/**
|
|
1000
|
+
* A lane is a short, stable key naming the area of work one Agent owns
|
|
1001
|
+
* (FR-26). Seven ship with the build, and the catalogue is capped at 12
|
|
1002
|
+
* (FR-30) so the "add a lane" menu stays a menu rather than a directory.
|
|
1003
|
+
*
|
|
1004
|
+
* 🛑 A lane is a **label, not a permission** (FR-27). It grants nothing,
|
|
1005
|
+
* restricts nothing, and must never be consulted by an authorization
|
|
1006
|
+
* decision. It exists so a surface can ask "who owns research here?" and
|
|
1007
|
+
* get a stable answer instead of grepping free-text titles.
|
|
1008
|
+
*/
|
|
1009
|
+
declare const ROSTER_LANE_KEYS: readonly ["coordination", "research", "content", "outreach", "visibility", "social", "market-watch"];
|
|
1010
|
+
type RosterLaneKey = (typeof ROSTER_LANE_KEYS)[number];
|
|
1011
|
+
/**
|
|
1012
|
+
* Named starting rosters. Content that ships with the build, not data:
|
|
1013
|
+
* a blueprint changes when we deploy, never when a user acts, and it
|
|
1014
|
+
* must mean the same thing in a bug report as it does in production.
|
|
1015
|
+
*/
|
|
1016
|
+
declare const ROSTER_BLUEPRINT_SLUGS: readonly ["general", "growth", "revenue", "insight", "solo-starter"];
|
|
1017
|
+
type RosterBlueprintSlug = (typeof ROSTER_BLUEPRINT_SLUGS)[number];
|
|
1018
|
+
/**
|
|
1019
|
+
* The most lanes one provisioning run will set up (FR-6). A blueprint
|
|
1020
|
+
* may declare at most this many, and a user adding lanes by hand stops
|
|
1021
|
+
* here too — more agents than this in one go is a fleet, not a start.
|
|
1022
|
+
*/
|
|
1023
|
+
declare const ROSTER_MAX_LANES = 8;
|
|
1024
|
+
/** Longest agent name the roster step accepts, in characters (FR-7). */
|
|
1025
|
+
declare const ROSTER_NAME_MAX = 60;
|
|
1026
|
+
|
|
1027
|
+
/**
|
|
1028
|
+
* AW-20 — the first-hour vocabulary: what a new owner still has to do,
|
|
1029
|
+
* and what happened the last time we set their agents up.
|
|
1030
|
+
*
|
|
1031
|
+
* The milestone enum lands with P1 because the provisioning record it
|
|
1032
|
+
* sits beside is written by P1's roster run; the checklist surfaces that
|
|
1033
|
+
* read these milestones are P2. Nothing here is persisted twice: the
|
|
1034
|
+
* provisioning record is one JSON column on the checklist row.
|
|
1035
|
+
*/
|
|
1036
|
+
|
|
1037
|
+
/**
|
|
1038
|
+
* The five first-hour milestones, in the order they are shown (FR-34).
|
|
1039
|
+
* Order is part of the contract — the card renders this array.
|
|
1040
|
+
*/
|
|
1041
|
+
declare const ONBOARDING_MILESTONES: readonly ["connectProvider", "meetAgents", "shipTask", "resolveDecision", "scheduleJob"];
|
|
1042
|
+
type OnboardingMilestoneKey = (typeof ONBOARDING_MILESTONES)[number];
|
|
1043
|
+
/** `pending → done` is one-way; `pending ⇄ skipped` is reversible (FR-35, FR-40). */
|
|
1044
|
+
declare const MILESTONE_STATUSES: readonly ["pending", "done", "skipped"];
|
|
1045
|
+
type MilestoneStatus = (typeof MILESTONE_STATUSES)[number];
|
|
1046
|
+
/**
|
|
1047
|
+
* One milestone's state. A milestone is never marked done on the
|
|
1048
|
+
* client's word (FR-36): `evidenceKind` / `evidenceId` record which
|
|
1049
|
+
* platform fact satisfied it, so "how do I know this is true?" has an
|
|
1050
|
+
* answer that is not "the browser said so".
|
|
1051
|
+
*/
|
|
1052
|
+
interface MilestoneRecord {
|
|
1053
|
+
readonly status: MilestoneStatus;
|
|
1054
|
+
readonly completedAt?: string | null;
|
|
1055
|
+
/** What satisfied it: 'connection' | 'roster' | 'run' | 'approval' | 'escalation' | 'schedule'. */
|
|
1056
|
+
readonly evidenceKind?: string | null;
|
|
1057
|
+
/** Opaque id of the satisfying object. Never rendered; used for the "what completed it" line. */
|
|
1058
|
+
readonly evidenceId?: string | null;
|
|
1059
|
+
/**
|
|
1060
|
+
* FR-59 degradation flag. True when this milestone's completion fact
|
|
1061
|
+
* could not be read on the last evaluation. The milestone stays
|
|
1062
|
+
* `pending` and the row renders a quiet "couldn't check" marker —
|
|
1063
|
+
* an unreadable fact must never be allowed to look like a done one,
|
|
1064
|
+
* and must never fail the whole checklist.
|
|
1065
|
+
*/
|
|
1066
|
+
readonly unknown?: boolean;
|
|
1067
|
+
}
|
|
1068
|
+
/**
|
|
1069
|
+
* Provisioning run states (FR-10). There is no other state: a record
|
|
1070
|
+
* that is not one of these is a bug, not a new case to handle.
|
|
1071
|
+
*/
|
|
1072
|
+
declare const ROSTER_PROVISION_STATES: readonly ["idle", "queued", "creating", "binding", "ready", "partial", "failed"];
|
|
1073
|
+
type RosterProvisionState = (typeof ROSTER_PROVISION_STATES)[number];
|
|
1074
|
+
/**
|
|
1075
|
+
* What happened to one lane (FR-11). `reused` is a success: the point of
|
|
1076
|
+
* idempotent provisioning is that a second run fills gaps rather than
|
|
1077
|
+
* creating a second "Research".
|
|
1078
|
+
*/
|
|
1079
|
+
declare const LANE_OUTCOMES: readonly ["pending", "created", "reused", "skippedNoSeat", "failed"];
|
|
1080
|
+
type LaneOutcome = (typeof LANE_OUTCOMES)[number];
|
|
1081
|
+
/** Why one lane failed. Closed vocabulary — the UI maps each to its own copy. */
|
|
1082
|
+
declare const LANE_FAILURE_REASONS: readonly ["nameUnavailable", "noSeat", "permissionDenied", "timedOut", "unknown"];
|
|
1083
|
+
type LaneFailureReason = (typeof LANE_FAILURE_REASONS)[number];
|
|
1084
|
+
/** One lane's outcome inside a provisioning run. */
|
|
1085
|
+
interface RosterLaneResult {
|
|
1086
|
+
readonly laneKey: RosterLaneKey;
|
|
1087
|
+
readonly templateSlug: string;
|
|
1088
|
+
readonly requestedName: string;
|
|
1089
|
+
readonly outcome: LaneOutcome;
|
|
1090
|
+
readonly agentId?: string | null;
|
|
1091
|
+
/** Set when a numeric suffix was needed to find a free name (FR-18). */
|
|
1092
|
+
readonly finalName?: string | null;
|
|
1093
|
+
readonly failureReason?: LaneFailureReason | null;
|
|
1094
|
+
/** Skills that could not be attached (FR-23). A warning, never a failure. */
|
|
1095
|
+
readonly skillWarnings?: readonly string[];
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* The current or last roster provisioning attempt. Persisted as one JSON
|
|
1099
|
+
* object on the checklist row rather than its own table: it is bounded,
|
|
1100
|
+
* one-to-one with a row that already exists, written only by
|
|
1101
|
+
* provisioning and read only in the moments around it.
|
|
1102
|
+
*/
|
|
1103
|
+
interface RosterProvisionRecord {
|
|
1104
|
+
readonly runId: string;
|
|
1105
|
+
readonly blueprintSlug: RosterBlueprintSlug;
|
|
1106
|
+
readonly state: RosterProvisionState;
|
|
1107
|
+
readonly startedAt: string;
|
|
1108
|
+
readonly finishedAt?: string | null;
|
|
1109
|
+
readonly lanes: readonly RosterLaneResult[];
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
/**
|
|
1113
|
+
* Role-driven starter seeding for the onboarding "What do you do" step.
|
|
1114
|
+
*
|
|
1115
|
+
* The first cut of this feature resolved suggestions IN THE BROWSER: the
|
|
1116
|
+
* step fetched the whole prebuilt-agent catalog and intersected
|
|
1117
|
+
* `suggestedRoles` client-side. Three things were wrong with that.
|
|
1118
|
+
*
|
|
1119
|
+
* 1. Coverage was accidental. Only the roles that happened to appear in
|
|
1120
|
+
* a go-to-market template's `suggestedRoles` produced anything —
|
|
1121
|
+
* 3 of the 14 roles the step actually offers. The other 11 selected
|
|
1122
|
+
* a role and were shown nothing, which reads as "we have nothing
|
|
1123
|
+
* for you" rather than "nobody wrote the mapping".
|
|
1124
|
+
* 2. It was Agents-only. A role implies a starting KIT — the agents to
|
|
1125
|
+
* activate AND the skills that make them useful — and the skills
|
|
1126
|
+
* half simply did not exist.
|
|
1127
|
+
* 3. The mapping lived in the client bundle, so every non-web surface
|
|
1128
|
+
* (desktop shell, chat, API consumers) had no way to ask "what
|
|
1129
|
+
* should a Marketing person start with?".
|
|
1130
|
+
*
|
|
1131
|
+
* The mapping is therefore server-side (`@ever-works/agent/agents`,
|
|
1132
|
+
* `role-seeding.ts`), exposed over `/api/onboarding/suggestions`, and
|
|
1133
|
+
* pinned by a spec that fails if ANY role in `ROLE_OPTIONS` is missing.
|
|
1134
|
+
* These are the wire shapes for that surface.
|
|
1135
|
+
*/
|
|
1136
|
+
/** One prebuilt Agent template offered for the selected roles. */
|
|
1137
|
+
interface OnboardingSeedAgentSuggestion {
|
|
1138
|
+
/** Template slug — the id `POST /api/agents/from-template/:slug` takes. */
|
|
1139
|
+
readonly slug: string;
|
|
1140
|
+
readonly name: string;
|
|
1141
|
+
readonly title: string;
|
|
1142
|
+
readonly description: string;
|
|
1143
|
+
/** Template category, e.g. `marketing` / `sales` / `ops`. */
|
|
1144
|
+
readonly category: string;
|
|
1145
|
+
/** Role ids (from `ROLE_OPTIONS`) that caused this template to surface. */
|
|
1146
|
+
readonly matchedRoles: readonly string[];
|
|
1147
|
+
}
|
|
1148
|
+
/** One first-party Skill offered for the selected roles. */
|
|
1149
|
+
interface OnboardingSeedSkillSuggestion {
|
|
1150
|
+
/** Skill catalog slug. */
|
|
1151
|
+
readonly slug: string;
|
|
1152
|
+
readonly title: string;
|
|
1153
|
+
readonly description: string;
|
|
1154
|
+
/** Go-to-market stage the Skill powers. */
|
|
1155
|
+
readonly stage: string;
|
|
1156
|
+
/** Role ids (from `ROLE_OPTIONS`) that caused this Skill to surface. */
|
|
1157
|
+
readonly matchedRoles: readonly string[];
|
|
1158
|
+
}
|
|
1159
|
+
/**
|
|
1160
|
+
* Wire shape of `GET /api/onboarding/suggestions`.
|
|
1161
|
+
*
|
|
1162
|
+
* `roles` echoes the RECOGNISED subset of the request (unknown ids are
|
|
1163
|
+
* dropped, never defaulted, matching how the wizard state validates its
|
|
1164
|
+
* own `profile.roles`). An empty `roles` yields empty suggestion lists
|
|
1165
|
+
* rather than a "here is everything" dump.
|
|
1166
|
+
*/
|
|
1167
|
+
interface OnboardingSeedSuggestionsResponse {
|
|
1168
|
+
readonly roles: readonly string[];
|
|
1169
|
+
/** Ids that were sent but are not in `ROLE_OPTIONS` — echoed so the caller can notice a typo. */
|
|
1170
|
+
readonly unknownRoles: readonly string[];
|
|
1171
|
+
readonly agents: readonly OnboardingSeedAgentSuggestion[];
|
|
1172
|
+
readonly skills: readonly OnboardingSeedSkillSuggestion[];
|
|
1173
|
+
}
|
|
1174
|
+
/**
|
|
1175
|
+
* Request body of `POST /api/onboarding/suggestions/seed`.
|
|
1176
|
+
*
|
|
1177
|
+
* `roles` is optional: omitted, the server uses the roles already saved
|
|
1178
|
+
* on the caller's onboarding state, so the client never has to be the
|
|
1179
|
+
* authority on what the user picked.
|
|
1180
|
+
*/
|
|
1181
|
+
interface OnboardingSeedRequest {
|
|
1182
|
+
readonly roles?: readonly string[];
|
|
1183
|
+
}
|
|
1184
|
+
/** Per-template outcome of a seeding run. */
|
|
1185
|
+
type OnboardingSeedOutcome = 'created' | 'already-exists' | 'failed';
|
|
1186
|
+
interface OnboardingSeedResultEntry {
|
|
1187
|
+
readonly slug: string;
|
|
1188
|
+
readonly outcome: OnboardingSeedOutcome;
|
|
1189
|
+
/** Id of the Agent created by THIS run; null for every other outcome. */
|
|
1190
|
+
readonly agentId: string | null;
|
|
1191
|
+
/** Short, non-sensitive reason — present only for `failed`. */
|
|
1192
|
+
readonly reason?: string;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Wire shape of `POST /api/onboarding/suggestions/seed`.
|
|
1196
|
+
*
|
|
1197
|
+
* Seeding is idempotent and best-effort per template: a template that
|
|
1198
|
+
* is already activated reports `already-exists` instead of failing the
|
|
1199
|
+
* whole call, so re-running the step never produces duplicates and a
|
|
1200
|
+
* single bad template never blocks the rest of the kit.
|
|
1201
|
+
*/
|
|
1202
|
+
interface OnboardingSeedResponse {
|
|
1203
|
+
readonly roles: readonly string[];
|
|
1204
|
+
readonly agents: readonly OnboardingSeedResultEntry[];
|
|
1205
|
+
/** Skills recommended alongside the seeded agents (informational). */
|
|
1206
|
+
readonly skills: readonly OnboardingSeedSkillSuggestion[];
|
|
1207
|
+
readonly createdCount: number;
|
|
1208
|
+
readonly skippedCount: number;
|
|
1209
|
+
readonly failedCount: number;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
/**
|
|
1213
|
+
* EW-628 data-repo instant-sync — wire-format contract for the activity
|
|
1214
|
+
* row `details` payload emitted by the API and consumed by the web
|
|
1215
|
+
* `SyncEventRow` component.
|
|
1216
|
+
*
|
|
1217
|
+
* Spec: `docs/specs/features/data-repo-instant-sync/spec.md` §5.6.
|
|
1218
|
+
*
|
|
1219
|
+
* The discriminated union is the canonical source of truth for both
|
|
1220
|
+
* sides — `apps/api/src/data-sync/data-sync.service.ts` writes it into
|
|
1221
|
+
* `activity_log.details`, and `apps/web/src/components/works/detail/
|
|
1222
|
+
* activity/SyncEvent.types.ts` re-exports it as `SyncEvent` so the
|
|
1223
|
+
* row renderer's exhaustive switch stays in lock-step.
|
|
1224
|
+
*
|
|
1225
|
+
* `kind` (not `status`) discriminates row variants — the activity-feed
|
|
1226
|
+
* convention reserves `status` for HTTP / pipeline lifecycle values
|
|
1227
|
+
* (`COMPLETED` / `FAILED` / `CANCELLED`), which live on the parent
|
|
1228
|
+
* `activity_log` row.
|
|
1229
|
+
*/
|
|
1230
|
+
/** Which transport surfaced the sync attempt. */
|
|
1231
|
+
type SyncEventSource = 'webhook' | 'poll' | 'manual';
|
|
1232
|
+
/**
|
|
1233
|
+
* Skip reasons the dispatcher or the three gates emit. Locked to a
|
|
1234
|
+
* small literal union so dashboards can pivot on it without parsing
|
|
1235
|
+
* free-form text.
|
|
1236
|
+
*/
|
|
1237
|
+
type SyncEventSkipReason = 'retry-backoff' | 'sync-in-progress' | 'generation-in-progress' | 'no-changes' | 'app-not-installed-and-no-credentials';
|
|
1238
|
+
/**
|
|
1239
|
+
* Failure classes the render gate maps caught errors to. The set is
|
|
1240
|
+
* deliberately small — adding a new class is a deliberate schema
|
|
1241
|
+
* decision, not an autopilot fallback. `unknown` is the explicit
|
|
1242
|
+
* fallback when nothing matches.
|
|
1243
|
+
*/
|
|
1244
|
+
type SyncEventErrorClass = 'data-repo-unreachable' | 'main-repo-push-rejected' | 'work-not-found' | 'timeout' | 'unknown';
|
|
1245
|
+
interface SyncEventSuccess {
|
|
1246
|
+
kind: 'success';
|
|
1247
|
+
source: SyncEventSource;
|
|
1248
|
+
beforeSha?: string;
|
|
1249
|
+
afterSha?: string;
|
|
1250
|
+
filesChanged: number;
|
|
1251
|
+
durationMs?: number;
|
|
1252
|
+
}
|
|
1253
|
+
interface SyncEventSkipped {
|
|
1254
|
+
kind: 'skipped';
|
|
1255
|
+
source: SyncEventSource;
|
|
1256
|
+
reason: SyncEventSkipReason;
|
|
1257
|
+
}
|
|
1258
|
+
interface SyncEventFailed {
|
|
1259
|
+
kind: 'failed';
|
|
1260
|
+
source: SyncEventSource;
|
|
1261
|
+
errorClass: SyncEventErrorClass;
|
|
1262
|
+
errorTail: string;
|
|
1263
|
+
}
|
|
1264
|
+
/**
|
|
1265
|
+
* The discriminated union the API writes into `activity_log.details`
|
|
1266
|
+
* for every `data_sync_*` row, and the web reads back to render the
|
|
1267
|
+
* `SyncEventRow`.
|
|
1268
|
+
*/
|
|
1269
|
+
type SyncEventPayload = SyncEventSuccess | SyncEventSkipped | SyncEventFailed;
|
|
1270
|
+
/** Narrow `kind` values used as React keys + telemetry labels. */
|
|
1271
|
+
type SyncEventKind = SyncEventPayload['kind'];
|
|
1272
|
+
|
|
1273
|
+
/**
|
|
1274
|
+
* EW-658 (Tenants & Organizations Phase 6) — wire-types for the
|
|
1275
|
+
* Organization-create / list / update / upgrade-from-account API
|
|
1276
|
+
* surface.
|
|
1277
|
+
*
|
|
1278
|
+
* Plain TypeScript interfaces so the API package and the web package
|
|
1279
|
+
* speak the same shape over the wire without dragging NestJS / TypeORM
|
|
1280
|
+
* decorators across the workspace boundary.
|
|
1281
|
+
*/
|
|
1282
|
+
|
|
1283
|
+
interface CreateOrganizationRequest {
|
|
1284
|
+
/** Display name. 1-200 chars. */
|
|
1285
|
+
name: string;
|
|
1286
|
+
/** Optional slug override. If omitted, allocated from `name`. */
|
|
1287
|
+
slug?: string;
|
|
1288
|
+
/**
|
|
1289
|
+
* PR-6 (domain-model evolution §23.5) — optional company vision
|
|
1290
|
+
* statement. Trimmed + capped at 5000 chars server-side; empty /
|
|
1291
|
+
* whitespace-only collapses to null.
|
|
1292
|
+
*/
|
|
1293
|
+
vision?: string | null;
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* EW-662 (Tenants & Organizations Phase 10) — body for
|
|
1297
|
+
* `POST /api/organizations/register-company`.
|
|
1298
|
+
*
|
|
1299
|
+
* Driven by the Company chip on `+ New`. The service hard-codes
|
|
1300
|
+
* `registrationProvider = 'manual'` and `registrationStatus =
|
|
1301
|
+
* 'registered'` for v1 (Stripe Atlas integration is deferred); the
|
|
1302
|
+
* client only supplies the user-visible fields.
|
|
1303
|
+
*/
|
|
1304
|
+
interface RegisterCompanyRequest {
|
|
1305
|
+
/** Display name. 1-200 chars. */
|
|
1306
|
+
name: string;
|
|
1307
|
+
/** Registered legal name. Defaults to `name` when omitted. */
|
|
1308
|
+
legalName?: string;
|
|
1309
|
+
/** ISO 3166-1 alpha-2 country code (e.g. `'US'`). */
|
|
1310
|
+
countryCode?: string;
|
|
1311
|
+
/** Optional slug override. If omitted, allocated from `name`. */
|
|
1312
|
+
slug?: string;
|
|
1313
|
+
}
|
|
1314
|
+
interface UpdateOrganizationRequest {
|
|
1315
|
+
displayName?: string;
|
|
1316
|
+
legalName?: string;
|
|
1317
|
+
countryCode?: string;
|
|
1318
|
+
/**
|
|
1319
|
+
* PR-6 — company vision. Omit to leave unchanged; explicit `null`
|
|
1320
|
+
* clears it. Any present value (including `null`) bumps
|
|
1321
|
+
* `visionUpdatedAt` to now.
|
|
1322
|
+
*/
|
|
1323
|
+
vision?: string | null;
|
|
1324
|
+
/**
|
|
1325
|
+
* Merge-policy matrix (Wave 3, D4) — the organization-scoped PARTIAL.
|
|
1326
|
+
* Omit to leave unchanged; explicit `null` clears the override so
|
|
1327
|
+
* everything inherits the tenant, then the platform default. Fields
|
|
1328
|
+
* omitted INSIDE the object inherit individually.
|
|
1329
|
+
*/
|
|
1330
|
+
mergePolicy?: MergePolicyOverride | null;
|
|
1331
|
+
/**
|
|
1332
|
+
* AW-15 — connection safety settings. Omit to leave unchanged; explicit
|
|
1333
|
+
* `null` resets every setting to its default. Today one setting:
|
|
1334
|
+
* `requireHttpsForCredentials` ("Require https for connection
|
|
1335
|
+
* credentials", default off).
|
|
1336
|
+
*/
|
|
1337
|
+
connectionPolicy?: OrganizationConnectionPolicy | null;
|
|
1338
|
+
}
|
|
1339
|
+
interface OrganizationResponse {
|
|
1340
|
+
id: string;
|
|
1341
|
+
tenantId: string;
|
|
1342
|
+
slug: string;
|
|
1343
|
+
legalName: string | null;
|
|
1344
|
+
displayName: string | null;
|
|
1345
|
+
countryCode: string | null;
|
|
1346
|
+
registrationProvider: string | null;
|
|
1347
|
+
registrationStatus: string | null;
|
|
1348
|
+
linkedWorkId: string | null;
|
|
1349
|
+
/** PR-6 — company vision statement (null = never set / cleared). */
|
|
1350
|
+
vision: string | null;
|
|
1351
|
+
/** PR-6 — ISO timestamp of the last vision change (null = never set). */
|
|
1352
|
+
visionUpdatedAt: string | null;
|
|
1353
|
+
/**
|
|
1354
|
+
* Merge-policy matrix (Wave 3, D4) — the PARTIAL stored on this row.
|
|
1355
|
+
* `null` means the organization declares nothing. OPTIONAL rather than
|
|
1356
|
+
* required: the field is additive, so a response from an API build that
|
|
1357
|
+
* predates it simply omits the key, and every consumer already has to
|
|
1358
|
+
* treat "absent" and "null" the same way (both mean "inherit").
|
|
1359
|
+
*
|
|
1360
|
+
* The EFFECTIVE policy is a fold of four scopes and is never derivable
|
|
1361
|
+
* from this field alone — read `GET /api/merge-policy/resolve` for that.
|
|
1362
|
+
*/
|
|
1363
|
+
mergePolicy?: MergePolicyOverride | null;
|
|
1364
|
+
/**
|
|
1365
|
+
* AW-15 — the stored connection safety settings. `null` / absent = every
|
|
1366
|
+
* default (literal connection credentials over plain http are allowed,
|
|
1367
|
+
* with a warning).
|
|
1368
|
+
*/
|
|
1369
|
+
connectionPolicy?: OrganizationConnectionPolicy | null;
|
|
1370
|
+
createdAt: string;
|
|
1371
|
+
updatedAt: string;
|
|
1372
|
+
}
|
|
1373
|
+
interface CheckSlugAvailabilityResponse {
|
|
1374
|
+
/** True iff the slug collides with neither `users.slug` nor `organizations.slug`. */
|
|
1375
|
+
available: boolean;
|
|
1376
|
+
/** Echo of the normalized form of the input (for the caller to display). */
|
|
1377
|
+
normalized: string;
|
|
1378
|
+
/** If unavailable, a next-free `-N` suggestion. Omitted when available. */
|
|
1379
|
+
suggestion?: string;
|
|
1380
|
+
}
|
|
1381
|
+
interface UpgradeFromAccountResponse {
|
|
1382
|
+
organizationId: string;
|
|
1383
|
+
tenantId: string;
|
|
1384
|
+
/** Total Tier A rows updated across all enumerated tables. */
|
|
1385
|
+
tierARowsUpdated: number;
|
|
1386
|
+
/** Total Tier B rows updated. */
|
|
1387
|
+
tierBRowsUpdated: number;
|
|
1388
|
+
/**
|
|
1389
|
+
* EW-663 (Phase 11 follow-up) — total Tier C rows backfilled via the
|
|
1390
|
+
* parent-FK join walk (e.g. `conversation_messages` whose parent
|
|
1391
|
+
* `conversations` belongs to the user). Zero before Phase 11 ships
|
|
1392
|
+
* and on second-call idempotency.
|
|
1393
|
+
*/
|
|
1394
|
+
tierCRowsUpdated: number;
|
|
1395
|
+
}
|
|
1396
|
+
/**
|
|
1397
|
+
* Error code returned with 409 Conflict when `upgrade-from-account` is
|
|
1398
|
+
* called after the user has created additional Organizations (spec §5.2,
|
|
1399
|
+
* "first-Org guard"). The endpoint is only callable while the user has
|
|
1400
|
+
* **exactly one** Organization under their Tenant.
|
|
1401
|
+
*/
|
|
1402
|
+
declare const UPGRADE_NOT_AVAILABLE_AFTER_MULTIPLE_ORGS: "UPGRADE_NOT_AVAILABLE_AFTER_MULTIPLE_ORGS";
|
|
1403
|
+
|
|
1404
|
+
/** Reserved transport contract; Organization slugs can never collide with this value. */
|
|
1405
|
+
declare const ACTIVE_SCOPE_PERSONAL_SENTINEL: "@personal";
|
|
1406
|
+
declare const ACTIVE_SCOPE_API_HEADER: "x-scope-slug";
|
|
1407
|
+
declare const ACTIVE_SCOPE_BROWSER_HEADER: "x-ever-workspace";
|
|
1408
|
+
declare const ACTIVE_SCOPE_RESPONSE_PROPERTIES: {
|
|
1409
|
+
tenantId: {
|
|
1410
|
+
type: "string";
|
|
1411
|
+
format: "uuid";
|
|
1412
|
+
nullable: true;
|
|
1413
|
+
};
|
|
1414
|
+
organizationId: {
|
|
1415
|
+
type: "string";
|
|
1416
|
+
format: "uuid";
|
|
1417
|
+
nullable: true;
|
|
1418
|
+
};
|
|
1419
|
+
organizationSlug: {
|
|
1420
|
+
type: "string";
|
|
1421
|
+
nullable: true;
|
|
1422
|
+
};
|
|
1423
|
+
};
|
|
1424
|
+
type ActiveScopeResponseKey = keyof typeof ACTIVE_SCOPE_RESPONSE_PROPERTIES;
|
|
1425
|
+
/** Runtime OpenAPI schema and source of truth for the active-scope response keys. */
|
|
1426
|
+
declare const ACTIVE_SCOPE_RESPONSE_SCHEMA: {
|
|
1427
|
+
type: "object";
|
|
1428
|
+
properties: {
|
|
1429
|
+
tenantId: {
|
|
1430
|
+
type: "string";
|
|
1431
|
+
format: "uuid";
|
|
1432
|
+
nullable: true;
|
|
1433
|
+
};
|
|
1434
|
+
organizationId: {
|
|
1435
|
+
type: "string";
|
|
1436
|
+
format: "uuid";
|
|
1437
|
+
nullable: true;
|
|
1438
|
+
};
|
|
1439
|
+
organizationSlug: {
|
|
1440
|
+
type: "string";
|
|
1441
|
+
nullable: true;
|
|
1442
|
+
};
|
|
1443
|
+
};
|
|
1444
|
+
required: ActiveScopeResponseKey[];
|
|
1445
|
+
};
|
|
1446
|
+
/** Wire response shared by the API and every active-scope consumer. */
|
|
1447
|
+
type ActiveScopeResponse = {
|
|
1448
|
+
[Key in ActiveScopeResponseKey]: string | null;
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1451
|
+
/**
|
|
1452
|
+
* Dynamic plugin distribution (EW-693).
|
|
1453
|
+
*
|
|
1454
|
+
* Per-replica install lifecycle for a distributable plugin. Distinct
|
|
1455
|
+
* from `state` (load-lifecycle) and `enabled` (per-user/per-work) so
|
|
1456
|
+
* the UI can show all three independently.
|
|
1457
|
+
*
|
|
1458
|
+
* - `available`: known in the catalog but not yet installed on this node.
|
|
1459
|
+
* - `installing`: currently being resolved / downloaded / placed.
|
|
1460
|
+
* - `installed`: present on disk and importable; may or may not be enabled.
|
|
1461
|
+
* - `error`: last install attempt failed; `installError` carries the reason.
|
|
1462
|
+
*/
|
|
1463
|
+
type PluginInstallState = 'available' | 'installing' | 'installed' | 'error';
|
|
1464
|
+
/**
|
|
1465
|
+
* Source the plugin's code came from on this deployment. Denormalised
|
|
1466
|
+
* onto the row for listing; the manifest's `distribution` is the
|
|
1467
|
+
* source of truth for "could this plugin ever be installed at runtime?"
|
|
1468
|
+
*/
|
|
1469
|
+
type PluginInstallSource = 'bundled' | 'registry';
|
|
1470
|
+
/**
|
|
1471
|
+
* Wire payload describing where a plugin sits in the install lifecycle.
|
|
1472
|
+
* Returned by `GET /plugins/:id/install-status` and embedded in the
|
|
1473
|
+
* plugin list / catalog responses (see {@link PluginCatalogEntry}).
|
|
1474
|
+
*/
|
|
1475
|
+
interface PluginInstallStateDto {
|
|
1476
|
+
readonly pluginId: string;
|
|
1477
|
+
readonly installState: PluginInstallState;
|
|
1478
|
+
readonly source: PluginInstallSource;
|
|
1479
|
+
/** npm spec actually installed, e.g. `@ever-works/notion-extractor-plugin@1.2.0`. */
|
|
1480
|
+
readonly registrySpec?: string;
|
|
1481
|
+
readonly installedVersion?: string;
|
|
1482
|
+
/** Integrity used to verify the install (sha512 from the registry). */
|
|
1483
|
+
readonly integrity?: string;
|
|
1484
|
+
/** Last error message if `installState === 'error'`. */
|
|
1485
|
+
readonly installError?: string;
|
|
1486
|
+
readonly updatedAt?: string;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/**
|
|
1490
|
+
* Dynamic plugin distribution (EW-693).
|
|
1491
|
+
*
|
|
1492
|
+
* A single entry in `GET /plugins/catalog` — the listable set of
|
|
1493
|
+
* distributable plugins. Manifest summary only (id/name/category/...)
|
|
1494
|
+
* + the local install state so the UI can render an "available"
|
|
1495
|
+
* card before the plugin has ever been instantiated.
|
|
1496
|
+
*/
|
|
1497
|
+
interface PluginCatalogEntry {
|
|
1498
|
+
readonly pluginId: string;
|
|
1499
|
+
readonly name: string;
|
|
1500
|
+
readonly description: string;
|
|
1501
|
+
readonly category: string;
|
|
1502
|
+
readonly capabilities: readonly string[];
|
|
1503
|
+
readonly version: string;
|
|
1504
|
+
readonly distribution: 'core' | 'registry';
|
|
1505
|
+
/** npm package name (e.g. `@ever-works/notion-extractor-plugin`). */
|
|
1506
|
+
readonly packageName?: string;
|
|
1507
|
+
/** Most recent version published to the registry (catalog-side). */
|
|
1508
|
+
readonly latestVersion?: string;
|
|
1509
|
+
readonly homepage?: string;
|
|
1510
|
+
readonly author?: string;
|
|
1511
|
+
readonly deprecated?: boolean;
|
|
1512
|
+
/** Per-replica install state, merged from the local DB. */
|
|
1513
|
+
readonly install: PluginInstallStateDto;
|
|
1514
|
+
}
|
|
1515
|
+
/**
|
|
1516
|
+
* Catalog response envelope. Errors fetching the upstream catalog are
|
|
1517
|
+
* surfaced via {@link PluginCatalogResponse.fetchedAt} being absent
|
|
1518
|
+
* and {@link PluginCatalogResponse.degraded} being true, so the UI
|
|
1519
|
+
* can show "registry unreachable — only locally-known plugins listed".
|
|
1520
|
+
*/
|
|
1521
|
+
interface PluginCatalogResponse {
|
|
1522
|
+
readonly entries: readonly PluginCatalogEntry[];
|
|
1523
|
+
readonly fetchedAt?: string;
|
|
1524
|
+
/** True when the registry call failed and entries reflect local state only. */
|
|
1525
|
+
readonly degraded?: boolean;
|
|
1526
|
+
readonly degradedReason?: string;
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Request body for `POST /plugins/:id/install`.
|
|
1530
|
+
*
|
|
1531
|
+
* - `version` is optional; when omitted the server resolves the
|
|
1532
|
+
* latest matching version pinned via the allowlist (or the
|
|
1533
|
+
* `@ever-works/*` package's `latest` dist-tag for first-party).
|
|
1534
|
+
* - `integrity` is optional; when provided the server MUST refuse
|
|
1535
|
+
* if the downloaded integrity does not match (FR-10).
|
|
1536
|
+
* - `source` lets a self-hoster prefer `github-packages` over the
|
|
1537
|
+
* default public npm mirror, when both are configured.
|
|
1538
|
+
*/
|
|
1539
|
+
interface PluginInstallRequestDto {
|
|
1540
|
+
readonly version?: string;
|
|
1541
|
+
readonly integrity?: string;
|
|
1542
|
+
readonly source?: 'npm' | 'github-packages';
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Response body for `POST /plugins/:id/install` (sync 202-accepted
|
|
1546
|
+
* envelope). The actual install runs asynchronously; clients poll
|
|
1547
|
+
* `GET /plugins/:id/install-status` for terminal state.
|
|
1548
|
+
*/
|
|
1549
|
+
interface PluginInstallResponseDto {
|
|
1550
|
+
readonly pluginId: string;
|
|
1551
|
+
readonly install: PluginInstallStateDto;
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
/**
|
|
1555
|
+
* Dynamic plugin distribution (EW-693).
|
|
1556
|
+
*
|
|
1557
|
+
* Admin-managed list of non-first-party packages permitted for
|
|
1558
|
+
* runtime install. First-party `@ever-works/*` is implicitly allowed
|
|
1559
|
+
* (no row required); everything else must match an enabled
|
|
1560
|
+
* `plugin_allowlist` row by name + version range, otherwise the
|
|
1561
|
+
* installer refuses the package BEFORE any network fetch (FR-11).
|
|
1562
|
+
*/
|
|
1563
|
+
interface PluginAllowlistEntryDto {
|
|
1564
|
+
readonly id: string;
|
|
1565
|
+
/** Full npm package name, e.g. `@some-vendor/cool-plugin`. */
|
|
1566
|
+
readonly packageName: string;
|
|
1567
|
+
/** Semver range pinning what versions are allowed, e.g. `^2.0.0` or `2.1.3`. */
|
|
1568
|
+
readonly versionRange: string;
|
|
1569
|
+
/** Optional integrity (sha512); when set the install MUST match. */
|
|
1570
|
+
readonly integrity?: string;
|
|
1571
|
+
readonly source: 'npm' | 'github-packages';
|
|
1572
|
+
readonly enabled: boolean;
|
|
1573
|
+
readonly createdAt: string;
|
|
1574
|
+
}
|
|
1575
|
+
/** Body for `POST /admin/plugins/allowlist`. */
|
|
1576
|
+
interface CreatePluginAllowlistEntryDto {
|
|
1577
|
+
readonly packageName: string;
|
|
1578
|
+
readonly versionRange: string;
|
|
1579
|
+
readonly integrity?: string;
|
|
1580
|
+
readonly source?: 'npm' | 'github-packages';
|
|
1581
|
+
readonly enabled?: boolean;
|
|
1582
|
+
}
|
|
1583
|
+
/** Body for `PATCH /admin/plugins/allowlist/:id` (toggle / re-pin). */
|
|
1584
|
+
interface UpdatePluginAllowlistEntryDto {
|
|
1585
|
+
readonly versionRange?: string;
|
|
1586
|
+
readonly integrity?: string;
|
|
1587
|
+
readonly enabled?: boolean;
|
|
1588
|
+
}
|
|
1589
|
+
/** Response envelope for `GET /admin/plugins/allowlist`. */
|
|
1590
|
+
interface PluginAllowlistResponseDto {
|
|
1591
|
+
readonly entries: readonly PluginAllowlistEntryDto[];
|
|
1592
|
+
}
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* What's new (AW-14) — closed vocabularies for product changelog entries.
|
|
1596
|
+
*
|
|
1597
|
+
* Nothing persists a category or a kind: entries come from a content source
|
|
1598
|
+
* that ships with the build, and only per-person read state is stored. These
|
|
1599
|
+
* tuples are therefore the single definition both the API and the web app
|
|
1600
|
+
* validate against.
|
|
1601
|
+
*/
|
|
1602
|
+
/**
|
|
1603
|
+
* The product area an entry belongs to (spec FR-9). A closed set of six —
|
|
1604
|
+
* adding a seventh is a spec change, not an authoring decision. Drives the
|
|
1605
|
+
* filter chips in the What's new panel.
|
|
1606
|
+
*/
|
|
1607
|
+
declare const CHANGELOG_CATEGORIES: readonly ["agents", "decisions", "knowledge", "connections", "costs", "platform"];
|
|
1608
|
+
type ChangelogCategory = (typeof CHANGELOG_CATEGORIES)[number];
|
|
1609
|
+
/**
|
|
1610
|
+
* What kind of change an entry describes (spec FR-10). Rendered as a badge
|
|
1611
|
+
* only — kind is never a filter dimension.
|
|
1612
|
+
*/
|
|
1613
|
+
declare const CHANGELOG_KINDS: readonly ["new", "improved", "fixed", "security"];
|
|
1614
|
+
type ChangelogKind = (typeof CHANGELOG_KINDS)[number];
|
|
1615
|
+
/** Narrowing guard for a category read from an untrusted source (query string, content file). */
|
|
1616
|
+
declare function isChangelogCategory(value: unknown): value is ChangelogCategory;
|
|
1617
|
+
/** Narrowing guard for a kind read from an untrusted source. */
|
|
1618
|
+
declare function isChangelogKind(value: unknown): value is ChangelogKind;
|
|
1619
|
+
/**
|
|
1620
|
+
* Spec FR-39 — is `raw` an in-product path a call-to-action may navigate to?
|
|
1621
|
+
*
|
|
1622
|
+
* True only for a string that begins with exactly one `/` and carries no
|
|
1623
|
+
* backslash, whitespace or control character anywhere. That single rule
|
|
1624
|
+
* rejects every form FR-39 names: an absolute URL to another origin or any
|
|
1625
|
+
* scheme-bearing string (neither can start with `/`), a protocol-relative
|
|
1626
|
+
* `//host`, a backslash-obfuscated `/\host`, and `/<tab>/host`, which
|
|
1627
|
+
* browsers collapse to `//host` because they strip tabs and newlines from
|
|
1628
|
+
* URLs before parsing them.
|
|
1629
|
+
*
|
|
1630
|
+
* Shared so the API (which drops an unsafe call-to-action when it loads
|
|
1631
|
+
* entries) and every client (which re-checks before rendering the button)
|
|
1632
|
+
* apply the identical rule.
|
|
1633
|
+
*/
|
|
1634
|
+
declare function isSafeInAppPath(raw: unknown): raw is string;
|
|
1635
|
+
/**
|
|
1636
|
+
* Stable entry identifier grammar (spec FR-6): a lowercase slug of 3–64
|
|
1637
|
+
* characters. It is the permalink and is never reused for a different entry.
|
|
1638
|
+
*/
|
|
1639
|
+
declare const CHANGELOG_SLUG_PATTERN: RegExp;
|
|
1640
|
+
/** Authoring limits (spec FR-5, FR-17, FR-15, FR-26, FR-27). */
|
|
1641
|
+
declare const CHANGELOG_LIMITS: {
|
|
1642
|
+
readonly titleMaxLength: 80;
|
|
1643
|
+
readonly bodyMaxLength: 600;
|
|
1644
|
+
readonly bodyMaxParagraphs: 3;
|
|
1645
|
+
readonly ctaLabelMaxLength: 32;
|
|
1646
|
+
/** Most slugs one mark-read write may carry. */
|
|
1647
|
+
readonly markReadBatchMax: 25;
|
|
1648
|
+
/** The unread count only ever considers this many of the newest entries. */
|
|
1649
|
+
readonly unreadWindow: 50;
|
|
1650
|
+
/** Default page size for the panel and the full list. */
|
|
1651
|
+
readonly pageSize: 20;
|
|
1652
|
+
/** Largest page a client may request. */
|
|
1653
|
+
readonly pageSizeMax: 50;
|
|
1654
|
+
/** The deepest the list can be paged. */
|
|
1655
|
+
readonly listMax: 200;
|
|
1656
|
+
};
|
|
1657
|
+
|
|
1658
|
+
/**
|
|
1659
|
+
* What's new (AW-14) — wire contracts for `GET/POST /api/changelog/*`.
|
|
1660
|
+
*
|
|
1661
|
+
* Pure types, no decorators, so the API, the web app and any external client
|
|
1662
|
+
* can import them. Additive-only (these ship in a public package).
|
|
1663
|
+
*/
|
|
1664
|
+
/** An in-product call-to-action: a button label and the app path it opens. */
|
|
1665
|
+
interface ChangelogCtaDto {
|
|
1666
|
+
label: string;
|
|
1667
|
+
/** Always an in-product path beginning with exactly one `/` (spec FR-39). */
|
|
1668
|
+
href: string;
|
|
1669
|
+
}
|
|
1670
|
+
/**
|
|
1671
|
+
* One product changelog entry as a reader sees it.
|
|
1672
|
+
*
|
|
1673
|
+
* Title and body are authored in English and are content, not interface
|
|
1674
|
+
* chrome — they are never passed through the translation layer (spec FR-11).
|
|
1675
|
+
*/
|
|
1676
|
+
interface ChangelogEntryDto {
|
|
1677
|
+
/** Stable slug; the permalink (spec FR-6). */
|
|
1678
|
+
slug: string;
|
|
1679
|
+
/** ≤ 80 characters (spec FR-5). */
|
|
1680
|
+
title: string;
|
|
1681
|
+
/** Plain text, ≤ 600 characters, ≤ 3 paragraphs, line breaks preserved (spec FR-5). */
|
|
1682
|
+
body: string;
|
|
1683
|
+
category: ChangelogCategory;
|
|
1684
|
+
kind: ChangelogKind;
|
|
1685
|
+
/** ISO-8601 publish timestamp. Future-dated entries are never returned (spec FR-7). */
|
|
1686
|
+
publishedAt: string;
|
|
1687
|
+
/** At most one entry is pinned; it sorts first (spec FR-8). */
|
|
1688
|
+
pinned: boolean;
|
|
1689
|
+
/** `null` when the entry has no call-to-action OR its target is not a safe in-product path (spec FR-40). */
|
|
1690
|
+
cta: ChangelogCtaDto | null;
|
|
1691
|
+
/** Read for this person — explicitly, or because it predates their account (spec FR-14). */
|
|
1692
|
+
isRead: boolean;
|
|
1693
|
+
}
|
|
1694
|
+
/** `GET /api/changelog` */
|
|
1695
|
+
interface ChangelogListResponseDto {
|
|
1696
|
+
entries: ChangelogEntryDto[];
|
|
1697
|
+
/** Slug of the last returned entry when another page exists, otherwise `null`. */
|
|
1698
|
+
nextCursor: string | null;
|
|
1699
|
+
/** Visible entries in this build, ignoring any category filter. */
|
|
1700
|
+
total: number;
|
|
1701
|
+
/** Always the UNFILTERED unread count — a category filter never changes it (spec FR-38). */
|
|
1702
|
+
unreadCount: number;
|
|
1703
|
+
/** Categories that have at least one visible entry; the others render as disabled chips (spec FR-37). */
|
|
1704
|
+
categoriesWithEntries: ChangelogCategory[];
|
|
1705
|
+
}
|
|
1706
|
+
/** `GET /api/changelog/unread-count` */
|
|
1707
|
+
interface ChangelogUnreadCountResponseDto {
|
|
1708
|
+
count: number;
|
|
1709
|
+
}
|
|
1710
|
+
/** `POST /api/changelog/read` and `POST /api/changelog/read-all` */
|
|
1711
|
+
interface ChangelogMarkReadResponseDto {
|
|
1712
|
+
/** The reader's fresh unread count after the write (spec FR-18, FR-19). */
|
|
1713
|
+
unreadCount: number;
|
|
1714
|
+
}
|
|
1715
|
+
/** `POST /api/changelog/read` request body. */
|
|
1716
|
+
interface ChangelogMarkReadRequestDto {
|
|
1717
|
+
/** 1–25 entry slugs (spec FR-17). Slugs this build does not know are ignored. */
|
|
1718
|
+
slugs: string[];
|
|
1719
|
+
}
|
|
1720
|
+
/**
|
|
1721
|
+
* The authoring shape a changelog content source yields — what a person (or
|
|
1722
|
+
* a later non-file source) writes, before the API validates it and resolves
|
|
1723
|
+
* per-reader read state.
|
|
1724
|
+
*
|
|
1725
|
+
* Kept in contracts rather than inside the API so a content source that
|
|
1726
|
+
* lives outside `apps/api` can produce records of exactly this shape.
|
|
1727
|
+
*/
|
|
1728
|
+
interface ChangelogSourceEntry {
|
|
1729
|
+
readonly slug: string;
|
|
1730
|
+
readonly title: string;
|
|
1731
|
+
readonly body: string;
|
|
1732
|
+
readonly category: ChangelogCategory;
|
|
1733
|
+
readonly kind: ChangelogKind;
|
|
1734
|
+
/** ISO-8601 date or date-time. */
|
|
1735
|
+
readonly publishedAt: string;
|
|
1736
|
+
readonly pinned?: boolean;
|
|
1737
|
+
readonly cta?: {
|
|
1738
|
+
readonly label: string;
|
|
1739
|
+
readonly href: string;
|
|
1740
|
+
};
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
/**
|
|
1744
|
+
* AW-01 — wire-types for the workspace-wide search behind the dashboard
|
|
1745
|
+
* command palette (`GET /api/workspace-search`).
|
|
1746
|
+
*
|
|
1747
|
+
* Deliberately a different word from the existing `/api/search`, which means
|
|
1748
|
+
* "search the web through the configured search plugin". The two surfaces
|
|
1749
|
+
* never share a path, a controller or a type.
|
|
1750
|
+
*/
|
|
1751
|
+
/**
|
|
1752
|
+
* Every record kind the palette can return. The first ten ship with the live
|
|
1753
|
+
* fan-out; the remaining kinds are reserved so a later index-backed read can
|
|
1754
|
+
* add them without a wire change.
|
|
1755
|
+
*/
|
|
1756
|
+
declare const WORKSPACE_SEARCH_KINDS: readonly ["mission", "task", "agent", "work", "idea", "skill", "team", "knowledge", "run", "decision", "memory", "goal", "meeting", "node", "connection"];
|
|
1757
|
+
type WorkspaceSearchKind = (typeof WORKSPACE_SEARCH_KINDS)[number];
|
|
1758
|
+
/** How a hit matched the query — the band that produced its base score. */
|
|
1759
|
+
type WorkspaceSearchMatchReason = 'exact' | 'prefix' | 'wordPrefix' | 'contains' | 'identifier' | 'secondary' | 'fuzzy';
|
|
1760
|
+
/** Shortest trimmed query the server answers; shorter queries return no groups. */
|
|
1761
|
+
declare const WORKSPACE_SEARCH_MIN_QUERY_LENGTH = 2;
|
|
1762
|
+
/** Longest query the server matches; longer input is truncated, not rejected. */
|
|
1763
|
+
declare const WORKSPACE_SEARCH_MAX_QUERY_LENGTH = 128;
|
|
1764
|
+
/** Hard ceiling on rows across all groups in one response. */
|
|
1765
|
+
declare const WORKSPACE_SEARCH_MAX_TOTAL = 60;
|
|
1766
|
+
/** Default rows per group when no filter is applied. */
|
|
1767
|
+
declare const WORKSPACE_SEARCH_DEFAULT_PER_KIND = 5;
|
|
1768
|
+
/** Hard ceiling on rows for one group, reached when a group filter is applied. */
|
|
1769
|
+
declare const WORKSPACE_SEARCH_MAX_PER_KIND = 25;
|
|
1770
|
+
/** How many recently opened records a client may send to boost ranking. */
|
|
1771
|
+
declare const WORKSPACE_SEARCH_MAX_RECENT = 12;
|
|
1772
|
+
interface WorkspaceSearchHit {
|
|
1773
|
+
/** `${kind}:${sourceId}` — a stable client key. */
|
|
1774
|
+
id: string;
|
|
1775
|
+
kind: WorkspaceSearchKind;
|
|
1776
|
+
sourceId: string;
|
|
1777
|
+
title: string;
|
|
1778
|
+
/** Breadcrumb, path, identifier or owner. */
|
|
1779
|
+
subtitle: string | null;
|
|
1780
|
+
/** Raw status value of the source record (rendered as a badge). */
|
|
1781
|
+
statusLabel: string | null;
|
|
1782
|
+
/** Locale-agnostic dashboard route the row opens. */
|
|
1783
|
+
destination: string;
|
|
1784
|
+
/** Deterministic 0..100. */
|
|
1785
|
+
score: number;
|
|
1786
|
+
matchReason: WorkspaceSearchMatchReason;
|
|
1787
|
+
/** ISO 8601. */
|
|
1788
|
+
updatedAt: string | null;
|
|
1789
|
+
}
|
|
1790
|
+
interface WorkspaceSearchGroup {
|
|
1791
|
+
kind: WorkspaceSearchKind;
|
|
1792
|
+
/** Matches before the per-group cap — drives the "Show all" row. */
|
|
1793
|
+
total: number;
|
|
1794
|
+
hits: WorkspaceSearchHit[];
|
|
1795
|
+
}
|
|
1796
|
+
interface WorkspaceSearchResponse {
|
|
1797
|
+
query: string;
|
|
1798
|
+
groups: WorkspaceSearchGroup[];
|
|
1799
|
+
/** Kinds whose source failed; the client renders a partial-results notice. */
|
|
1800
|
+
degradedKinds: WorkspaceSearchKind[];
|
|
1801
|
+
servedBy: 'index' | 'fanout' | 'mixed';
|
|
1802
|
+
tookMs: number;
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
/**
|
|
1806
|
+
* Help centre (AW-25) — closed vocabularies and the structured article grammar.
|
|
1807
|
+
*
|
|
1808
|
+
* The in-product manual renders pages of the documentation site (`docs/`) that
|
|
1809
|
+
* ship with the build. Nothing here is persisted: a build-time generator turns
|
|
1810
|
+
* those Markdown pages into the structured blocks below, and the web app renders
|
|
1811
|
+
* the blocks without ever injecting raw markup (spec FR-28). These tuples and
|
|
1812
|
+
* types are the one definition the generator, the renderer and any later API
|
|
1813
|
+
* surface agree on.
|
|
1814
|
+
*/
|
|
1815
|
+
/**
|
|
1816
|
+
* The manual's sections, in reading order (spec FR-4). A closed set of six —
|
|
1817
|
+
* adding a seventh is a spec change, not an authoring decision.
|
|
1818
|
+
*/
|
|
1819
|
+
declare const HELP_SECTIONS: readonly ["start-here", "running-the-loop", "your-agents", "setup-and-connections", "money-and-limits", "when-something-goes-wrong"];
|
|
1820
|
+
type HelpSection = (typeof HELP_SECTIONS)[number];
|
|
1821
|
+
/**
|
|
1822
|
+
* Every block kind an article body may contain (spec FR-27). Closed — the
|
|
1823
|
+
* renderer switches over this set without a default branch, so a new kind is a
|
|
1824
|
+
* compile error until it is rendered. `table` is part of the set because the
|
|
1825
|
+
* documentation pages the manual reuses present reference material as tables.
|
|
1826
|
+
*/
|
|
1827
|
+
declare const HELP_BLOCK_KINDS: readonly ["paragraph", "heading", "orderedList", "unorderedList", "note", "shortcut", "code", "link", "table"];
|
|
1828
|
+
type HelpBlockKind = (typeof HELP_BLOCK_KINDS)[number];
|
|
1829
|
+
/** What a link may point at (spec FR-27a). Closed. */
|
|
1830
|
+
declare const HELP_LINK_TARGET_TYPES: readonly ["article", "screen", "external"];
|
|
1831
|
+
type HelpLinkTargetType = (typeof HELP_LINK_TARGET_TYPES)[number];
|
|
1832
|
+
/** Visual tone of a callout block. Closed. */
|
|
1833
|
+
declare const HELP_NOTE_TONES: readonly ["note", "tip", "info", "warning", "danger"];
|
|
1834
|
+
type HelpNoteTone = (typeof HELP_NOTE_TONES)[number];
|
|
1835
|
+
/**
|
|
1836
|
+
* Build-time limits (spec FR-3). Where the manual reuses an existing
|
|
1837
|
+
* documentation page, the body and heading ceilings are sized for those pages
|
|
1838
|
+
* rather than for short purpose-written articles.
|
|
1839
|
+
*/
|
|
1840
|
+
declare const HELP_LIMITS: {
|
|
1841
|
+
readonly maxArticles: 200;
|
|
1842
|
+
readonly titleChars: 70;
|
|
1843
|
+
readonly summaryChars: 200;
|
|
1844
|
+
readonly bodyChars: 60000;
|
|
1845
|
+
readonly maxHeadings: 80;
|
|
1846
|
+
readonly headingIdMinChars: 2;
|
|
1847
|
+
readonly headingIdMaxChars: 96;
|
|
1848
|
+
readonly maxKeywords: 12;
|
|
1849
|
+
readonly keywordChars: 32;
|
|
1850
|
+
readonly maxDocuments: 8;
|
|
1851
|
+
readonly maxRelated: 5;
|
|
1852
|
+
readonly linkLabelChars: 80;
|
|
1853
|
+
readonly externalHrefChars: 2048;
|
|
1854
|
+
};
|
|
1855
|
+
/** Article identifier: lowercase letters, digits and hyphens, 3–64 characters (spec FR-3). */
|
|
1856
|
+
declare const HELP_ARTICLE_ID_PATTERN: RegExp;
|
|
1857
|
+
type HelpLinkTarget =
|
|
1858
|
+
/** Another article, optionally at a heading. Resolved like a help link (spec FR-22). */
|
|
1859
|
+
{
|
|
1860
|
+
type: 'article';
|
|
1861
|
+
articleId: string;
|
|
1862
|
+
headingId: string | null;
|
|
1863
|
+
}
|
|
1864
|
+
/** A KEY of the web app's route map — never a literal path (spec FR-5.2). */
|
|
1865
|
+
| {
|
|
1866
|
+
type: 'screen';
|
|
1867
|
+
routeKey: string;
|
|
1868
|
+
}
|
|
1869
|
+
/** Absolute `https:` URL with no embedded credentials (spec FR-27a). */
|
|
1870
|
+
| {
|
|
1871
|
+
type: 'external';
|
|
1872
|
+
href: string;
|
|
1873
|
+
};
|
|
1874
|
+
/** Inline content inside a paragraph, list item, heading or table cell. */
|
|
1875
|
+
type HelpInline = {
|
|
1876
|
+
type: 'text';
|
|
1877
|
+
text: string;
|
|
1878
|
+
} | {
|
|
1879
|
+
type: 'strong';
|
|
1880
|
+
children: HelpInline[];
|
|
1881
|
+
} | {
|
|
1882
|
+
type: 'emphasis';
|
|
1883
|
+
children: HelpInline[];
|
|
1884
|
+
} | {
|
|
1885
|
+
type: 'code';
|
|
1886
|
+
text: string;
|
|
1887
|
+
} | {
|
|
1888
|
+
type: 'link';
|
|
1889
|
+
children: HelpInline[];
|
|
1890
|
+
target: HelpLinkTarget;
|
|
1891
|
+
};
|
|
1892
|
+
interface HelpListItem {
|
|
1893
|
+
content: HelpInline[];
|
|
1894
|
+
/** Nested blocks — a sub-list, a code sample or a callout inside the item. */
|
|
1895
|
+
children: HelpBlock[];
|
|
1896
|
+
}
|
|
1897
|
+
interface HelpLinkBlock {
|
|
1898
|
+
kind: 'link';
|
|
1899
|
+
/** Plain text, 1–80 characters, no inline markup. */
|
|
1900
|
+
label: string;
|
|
1901
|
+
target: HelpLinkTarget;
|
|
1902
|
+
}
|
|
1903
|
+
type HelpBlock = {
|
|
1904
|
+
kind: 'paragraph';
|
|
1905
|
+
content: HelpInline[];
|
|
1906
|
+
} | {
|
|
1907
|
+
kind: 'heading';
|
|
1908
|
+
level: 2 | 3 | 4;
|
|
1909
|
+
id: string;
|
|
1910
|
+
content: HelpInline[];
|
|
1911
|
+
} | {
|
|
1912
|
+
kind: 'orderedList';
|
|
1913
|
+
items: HelpListItem[];
|
|
1914
|
+
} | {
|
|
1915
|
+
kind: 'unorderedList';
|
|
1916
|
+
items: HelpListItem[];
|
|
1917
|
+
} | {
|
|
1918
|
+
kind: 'note';
|
|
1919
|
+
tone: HelpNoteTone;
|
|
1920
|
+
title: string | null;
|
|
1921
|
+
blocks: HelpBlock[];
|
|
1922
|
+
} | {
|
|
1923
|
+
kind: 'shortcut';
|
|
1924
|
+
keys: string[];
|
|
1925
|
+
label: string;
|
|
1926
|
+
} | {
|
|
1927
|
+
kind: 'code';
|
|
1928
|
+
language: string | null;
|
|
1929
|
+
text: string;
|
|
1930
|
+
} | HelpLinkBlock | {
|
|
1931
|
+
kind: 'table';
|
|
1932
|
+
header: HelpInline[][];
|
|
1933
|
+
rows: HelpInline[][][];
|
|
1934
|
+
};
|
|
1935
|
+
/** The body file the generator emits for one article. */
|
|
1936
|
+
interface HelpArticleBody {
|
|
1937
|
+
/** Format version of this file; bumped only on an incompatible grammar change. */
|
|
1938
|
+
version: 1;
|
|
1939
|
+
id: string;
|
|
1940
|
+
blocks: HelpBlock[];
|
|
1941
|
+
}
|
|
1942
|
+
/** Narrowing guard for a section read from an untrusted source. */
|
|
1943
|
+
declare function isHelpSection(value: unknown): value is HelpSection;
|
|
1944
|
+
/** Narrowing guard for an article identifier read from an untrusted source (a URL segment). */
|
|
1945
|
+
declare function isHelpArticleId(value: unknown): value is string;
|
|
1946
|
+
|
|
1947
|
+
/**
|
|
1948
|
+
* Shared view — the owner-facing wire contracts behind Settings → Sharing and
|
|
1949
|
+
* the public share-link exchange.
|
|
1950
|
+
*
|
|
1951
|
+
* A Shared view is one Workspace's read-only published face: a live,
|
|
1952
|
+
* revocable projection of its Task board reached by a share link. It holds
|
|
1953
|
+
* WHAT may be read and BY WHICH token, never a copy of the content.
|
|
1954
|
+
*
|
|
1955
|
+
* Pure types plus closed vocabularies, so the API, the web app and any other
|
|
1956
|
+
* client import one definition. Additive-only (this ships in a public package).
|
|
1957
|
+
*/
|
|
1958
|
+
/** `active` = the link resolves; `paused` = sharing is off but the link is kept. */
|
|
1959
|
+
type SharedViewStatus = 'active' | 'paused';
|
|
1960
|
+
declare const SHARED_VIEW_STATUSES: readonly SharedViewStatus[];
|
|
1961
|
+
declare function isSharedViewStatus(value: unknown): value is SharedViewStatus;
|
|
1962
|
+
/** Which sections a Shared view publishes. The board is on by default, knowledge off. */
|
|
1963
|
+
interface SharedViewSectionsDto {
|
|
1964
|
+
board: boolean;
|
|
1965
|
+
knowledge: boolean;
|
|
1966
|
+
}
|
|
1967
|
+
/** How a Shared view answers crawlers. `blocked` is the default. */
|
|
1968
|
+
type SharedViewIndexingMode = 'blocked' | 'allowed';
|
|
1969
|
+
/** Every number the Shared view contract promises, in one place. */
|
|
1970
|
+
declare const SHARED_VIEW_LIMITS: {
|
|
1971
|
+
/** 256 bits of randomness, base64url without padding. */
|
|
1972
|
+
readonly tokenBytes: 32;
|
|
1973
|
+
readonly tokenLength: 43;
|
|
1974
|
+
/** A view session lives this long before the client exchanges the token again. */
|
|
1975
|
+
readonly viewSessionTtlSeconds: number;
|
|
1976
|
+
/** Cards per published column. */
|
|
1977
|
+
readonly columnCardLimit: 50;
|
|
1978
|
+
/** Lines in the published activity strip. */
|
|
1979
|
+
readonly activityLineLimit: 20;
|
|
1980
|
+
/** Labels per published card. */
|
|
1981
|
+
readonly cardLabelLimit: 3;
|
|
1982
|
+
/** Exchanges and reads per token (or per view) per minute. */
|
|
1983
|
+
readonly requestsPerTokenPerMinute: 60;
|
|
1984
|
+
/** Public requests per client per hour. */
|
|
1985
|
+
readonly requestsPerClientPerHour: 600;
|
|
1986
|
+
/** Owner regenerations per Workspace per minute. */
|
|
1987
|
+
readonly regeneratePerMinute: 10;
|
|
1988
|
+
/** A client increments the view count at most once in this window. */
|
|
1989
|
+
readonly viewDedupeWindowSeconds: number;
|
|
1990
|
+
/** The `Retry-After` a throttled public request carries. */
|
|
1991
|
+
readonly retryAfterSeconds: 60;
|
|
1992
|
+
/** The live poll cadence of the published page. */
|
|
1993
|
+
readonly pollIntervalSeconds: 20;
|
|
1994
|
+
/** Knowledge class names a selection may hold. */
|
|
1995
|
+
readonly knowledgeClassLimit: 32;
|
|
1996
|
+
};
|
|
1997
|
+
/** The one error message every refused share-link request carries. */
|
|
1998
|
+
declare const SHARED_VIEW_NOT_ACTIVE = "shared_view_not_active";
|
|
1999
|
+
/** The share link, returned only to the Tenant owner. */
|
|
2000
|
+
interface SharedViewLinkDto {
|
|
2001
|
+
/** The 43-character share token. The web app builds `/share/<token>` from it. */
|
|
2002
|
+
token: string;
|
|
2003
|
+
}
|
|
2004
|
+
/**
|
|
2005
|
+
* `GET /api/organizations/:orgId/shared-view` and every owner write.
|
|
2006
|
+
*
|
|
2007
|
+
* Every member of the Workspace may read the settings; only the Tenant owner
|
|
2008
|
+
* receives `link`. `exists: false` means sharing has never been turned on.
|
|
2009
|
+
*/
|
|
2010
|
+
interface SharedViewSettingsDto {
|
|
2011
|
+
exists: boolean;
|
|
2012
|
+
/** True when the caller is the Tenant owner and may change sharing. */
|
|
2013
|
+
canManage: boolean;
|
|
2014
|
+
status: SharedViewStatus | null;
|
|
2015
|
+
sections: SharedViewSectionsDto;
|
|
2016
|
+
/** Knowledge Base classes selected for publication. Empty publishes nothing. */
|
|
2017
|
+
knowledgeClasses: string[];
|
|
2018
|
+
searchIndexable: boolean;
|
|
2019
|
+
viewCount: number;
|
|
2020
|
+
/** ISO timestamp, or `null` when the link was never opened. */
|
|
2021
|
+
lastViewedAt: string | null;
|
|
2022
|
+
/** ISO timestamp of the last regenerate, or `null` when never regenerated. */
|
|
2023
|
+
tokenRotatedAt: string | null;
|
|
2024
|
+
rotationCount: number;
|
|
2025
|
+
/** ISO timestamp the Shared view was first turned on. */
|
|
2026
|
+
createdAt: string | null;
|
|
2027
|
+
/** Present only for the Tenant owner, and only when the stored token could be read. */
|
|
2028
|
+
link: SharedViewLinkDto | null;
|
|
2029
|
+
/** True for the owner when a stored token exists but could not be decrypted — regenerate to recover. */
|
|
2030
|
+
linkUnreadable: boolean;
|
|
2031
|
+
}
|
|
2032
|
+
/** `PATCH /api/organizations/:orgId/shared-view` — every field optional, one facet per field. */
|
|
2033
|
+
interface UpdateSharedViewDto {
|
|
2034
|
+
status?: SharedViewStatus;
|
|
2035
|
+
sections?: Partial<SharedViewSectionsDto>;
|
|
2036
|
+
knowledgeClasses?: string[];
|
|
2037
|
+
searchIndexable?: boolean;
|
|
2038
|
+
}
|
|
2039
|
+
/** `POST /api/public/shared-view/sessions` request body. The token never travels in a URL. */
|
|
2040
|
+
interface SharedViewSessionRequestDto {
|
|
2041
|
+
token: string;
|
|
2042
|
+
}
|
|
2043
|
+
/** `POST /api/public/shared-view/sessions` response. */
|
|
2044
|
+
interface SharedViewSessionDto {
|
|
2045
|
+
/** Opaque credential presented as `Authorization: Bearer <viewSession>` on every read. */
|
|
2046
|
+
viewSession: string;
|
|
2047
|
+
/** ISO timestamp after which the view session is refused. */
|
|
2048
|
+
expiresAt: string;
|
|
2049
|
+
/** Crawler posture of the resolved view, so the page can render its own robots directive. */
|
|
2050
|
+
searchIndexable: boolean;
|
|
2051
|
+
/** Sections the resolved view publishes. */
|
|
2052
|
+
sections: SharedViewSectionsDto;
|
|
2053
|
+
}
|
|
2054
|
+
/** Per-class publishable document counts for the knowledge confirm dialog. */
|
|
2055
|
+
interface SharedViewKnowledgeClassCountDto {
|
|
2056
|
+
documentClass: string;
|
|
2057
|
+
count: number;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
/**
|
|
2061
|
+
* Shared view — the published board: what a link visitor with no account is
|
|
2062
|
+
* allowed to read.
|
|
2063
|
+
*
|
|
2064
|
+
* Every type below is CLOSED: no index signature, no `Record<string, unknown>`
|
|
2065
|
+
* escape hatch, no optional passthrough. A field that is not declared here
|
|
2066
|
+
* cannot be serialised, so adding a field to a Task, an Agent or an activity
|
|
2067
|
+
* record can never leak it onto the published page.
|
|
2068
|
+
*
|
|
2069
|
+
* What is deliberately absent, and must stay absent: ids of any kind, costs,
|
|
2070
|
+
* budgets, token counts, model names, run references, error text, comments,
|
|
2071
|
+
* sub-tasks, the Mission / Work / Idea / Team / Goal a Task is filed against,
|
|
2072
|
+
* repositories, file paths, in-product URLs, and every human's name or email.
|
|
2073
|
+
*/
|
|
2074
|
+
/** The four published columns — the private Task board's Focus layout, minus Cancelled. */
|
|
2075
|
+
type PublishedColumnKey = 'backlog' | 'in_flight' | 'needs_you' | 'done';
|
|
2076
|
+
declare const PUBLISHED_COLUMN_KEYS: readonly PublishedColumnKey[];
|
|
2077
|
+
/** `p0` (Urgent) … `p4` (Low). */
|
|
2078
|
+
type PublishedTaskPriority = 'p0' | 'p1' | 'p2' | 'p3' | 'p4';
|
|
2079
|
+
/** The Agent working a card: a display name only. The page draws the avatar from it. */
|
|
2080
|
+
interface PublishedAgentRefDto {
|
|
2081
|
+
name: string;
|
|
2082
|
+
}
|
|
2083
|
+
interface PublishedTaskCardDto {
|
|
2084
|
+
title: string;
|
|
2085
|
+
column: PublishedColumnKey;
|
|
2086
|
+
priority: PublishedTaskPriority;
|
|
2087
|
+
/** At most three labels. */
|
|
2088
|
+
labels: string[];
|
|
2089
|
+
/** ISO timestamp the work last moved. */
|
|
2090
|
+
lastProgressAt: string;
|
|
2091
|
+
/** True when the work has stopped moving (the private board's stall rule). */
|
|
2092
|
+
stale: boolean;
|
|
2093
|
+
agent: PublishedAgentRefDto | null;
|
|
2094
|
+
}
|
|
2095
|
+
interface PublishedColumnDto {
|
|
2096
|
+
key: PublishedColumnKey;
|
|
2097
|
+
/** Cards in the column, at most fifty, ordered exactly as on the private board. */
|
|
2098
|
+
cards: PublishedTaskCardDto[];
|
|
2099
|
+
/** Cards the column holds beyond the published ones — rendered as `+N more`. */
|
|
2100
|
+
moreCount: number;
|
|
2101
|
+
}
|
|
2102
|
+
/** `working` = has work in flight or a run going; `paused` = paused by its owner; otherwise `idle`. */
|
|
2103
|
+
type PublishedAgentStatus = 'working' | 'idle' | 'paused';
|
|
2104
|
+
interface PublishedAgentDto {
|
|
2105
|
+
name: string;
|
|
2106
|
+
status: PublishedAgentStatus;
|
|
2107
|
+
/** Published cards this Agent is working in the In flight column. */
|
|
2108
|
+
inFlightCount: number;
|
|
2109
|
+
}
|
|
2110
|
+
/** Who an activity line is about. Only an Agent is ever named. */
|
|
2111
|
+
type PublishedActorKind = 'agent' | 'person' | 'system';
|
|
2112
|
+
interface PublishedActivityLineDto {
|
|
2113
|
+
actorKind: PublishedActorKind;
|
|
2114
|
+
/** The Agent's display name. Always `null` for a person or the system. */
|
|
2115
|
+
actorName: string | null;
|
|
2116
|
+
/** The same narration the Live Feed renders, with the actor param never naming a person. */
|
|
2117
|
+
narration: FeedNarrationDto;
|
|
2118
|
+
/** ISO timestamp. */
|
|
2119
|
+
at: string;
|
|
2120
|
+
}
|
|
2121
|
+
/** `GET /api/public/shared-view/board` */
|
|
2122
|
+
interface PublishedBoardDto {
|
|
2123
|
+
workspaceName: string;
|
|
2124
|
+
sections: SharedViewSectionsDto;
|
|
2125
|
+
columns: PublishedColumnDto[];
|
|
2126
|
+
agents: PublishedAgentDto[];
|
|
2127
|
+
recent: PublishedActivityLineDto[];
|
|
2128
|
+
/** ISO timestamp the projection was computed. */
|
|
2129
|
+
generatedAt: string;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
/**
|
|
2133
|
+
* Shared view — the published knowledge library.
|
|
2134
|
+
*
|
|
2135
|
+
* Declared with the rest of the published contract so the shape is settled
|
|
2136
|
+
* once; the knowledge section itself stays off (and its endpoints answer the
|
|
2137
|
+
* not-active response) until it ships. Closed types, like the board's.
|
|
2138
|
+
*
|
|
2139
|
+
* Never published: git history, citations, the retrieval trail, embedding
|
|
2140
|
+
* state, uploads and original source files.
|
|
2141
|
+
*/
|
|
2142
|
+
interface PublishedDocumentSummaryDto {
|
|
2143
|
+
/** An opaque, per-view document reference — never the stored document id. */
|
|
2144
|
+
ref: string;
|
|
2145
|
+
title: string;
|
|
2146
|
+
documentClass: string;
|
|
2147
|
+
wordCount: number;
|
|
2148
|
+
/** ISO timestamp. */
|
|
2149
|
+
updatedAt: string;
|
|
2150
|
+
}
|
|
2151
|
+
interface PublishedDocumentDto extends PublishedDocumentSummaryDto {
|
|
2152
|
+
/** The rendered document text. */
|
|
2153
|
+
body: string;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
/**
|
|
2157
|
+
* Shared view — the activity kinds the published strip may show.
|
|
2158
|
+
*
|
|
2159
|
+
* CLOSED BY DEFAULT: an activity kind is published only when it is named
|
|
2160
|
+
* here. A newly added kind stays off the published page until somebody adds
|
|
2161
|
+
* it deliberately; the agent-side classification spec fails until every kind
|
|
2162
|
+
* is on this list or on the never-publish list.
|
|
2163
|
+
*
|
|
2164
|
+
* Each entry is safe because its Live Feed narration reads nothing beyond a
|
|
2165
|
+
* Task title (already on a published card) or a status token: no path, no
|
|
2166
|
+
* repository, no Work name, no amount, no error text, no person.
|
|
2167
|
+
*/
|
|
2168
|
+
declare const PUBLISHABLE_ACTIVITY_ACTIONS: readonly string[];
|
|
2169
|
+
declare function isPublishableActivityAction(actionType: unknown): boolean;
|
|
2170
|
+
|
|
2171
|
+
export { ACTIVE_SCOPE_API_HEADER, ACTIVE_SCOPE_BROWSER_HEADER, ACTIVE_SCOPE_PERSONAL_SENTINEL, ACTIVE_SCOPE_RESPONSE_SCHEMA, AWESOME_README_IMPORT_MODES, type ActiveScopeResponse, type AnalyzeRepositoryResponseDto, type AwesomeReadmeImportMode, CHANGELOG_CATEGORIES, CHANGELOG_KINDS, CHANGELOG_LIMITS, CHANGELOG_SLUG_PATTERN, type ChangelogCategory, type ChangelogCtaDto, type ChangelogEntryDto, type ChangelogKind, type ChangelogListResponseDto, type ChangelogMarkReadRequestDto, type ChangelogMarkReadResponseDto, type ChangelogSourceEntry, type ChangelogUnreadCountResponseDto, type CheckItemHealthDto, type CheckItemHealthResponseDto, type CheckSlugAvailabilityResponse, type CreateItemsGeneratorDto, type CreateOrganizationRequest, type CreatePluginAllowlistEntryDto, type ExtractItemDetailsDto, GenerateStatusType, type GenerationLogLevel, type GenerationLogSource, GenerationMethod, type GenerationMetrics, type GenerationStepLog, HELP_ARTICLE_ID_PATTERN, HELP_BLOCK_KINDS, HELP_LIMITS, HELP_LINK_TARGET_TYPES, HELP_NOTE_TONES, HELP_SECTIONS, type HelpArticleBody, type HelpBlock, type HelpBlockKind, type HelpInline, type HelpLinkBlock, type HelpLinkTarget, type HelpLinkTargetType, type HelpListItem, type HelpNoteTone, type HelpSection, IMPORT_SOURCE_TYPES, type ImportEnrichmentConfig, type ImportSourceType, type ImportWorkDto, LANE_FAILURE_REASONS, LANE_OUTCOMES, type LaneFailureReason, type LaneOutcome, MILESTONE_STATUSES, type ManifestValidationError, type MilestoneRecord, type MilestoneStatus, ONBOARDING_DEFAULT_STATE, ONBOARDING_DESKTOP_NEXT_STEPS, ONBOARDING_MILESTONES, ONBOARDING_TERMINAL_STATUSES, type OnboardingAiChoice, type OnboardingCard, type OnboardingCardBadge, type OnboardingCatalogResponse, type OnboardingDbChoice, type OnboardingDeployChoice, type OnboardingDesktopChoice, type OnboardingDesktopNextStep, type OnboardingMilestoneKey, type OnboardingPluginCard, type OnboardingProfile, type OnboardingProfileOption, type OnboardingRequestSource, type OnboardingRequestSourceAwesomeReadme, type OnboardingRequestSourceDataRepo, type OnboardingRequestSourceInline, type OnboardingRequestSourceWebSearch, type OnboardingRoleId, type OnboardingSeedAgentSuggestion, type OnboardingSeedOutcome, type OnboardingSeedRequest, type OnboardingSeedResponse, type OnboardingSeedResultEntry, type OnboardingSeedSkillSuggestion, type OnboardingSeedSuggestionsResponse, type OnboardingStatePatchRequest, type OnboardingStateResponse, type OnboardingStatus, type OnboardingStorageChoice, type OnboardingTeamSizeId, type OnboardingWizardStateV2, type OrganizationResponse, PUBLISHABLE_ACTIVITY_ACTIONS, PUBLISHED_COLUMN_KEYS, type PluginAllowlistEntryDto, type PluginAllowlistResponseDto, type PluginCatalogEntry, type PluginCatalogResponse, type PluginInstallRequestDto, type PluginInstallResponseDto, type PluginInstallSource, type PluginInstallState, type PluginInstallStateDto, type ProvidersDto, type PublishedActivityLineDto, type PublishedActorKind, type PublishedAgentDto, type PublishedAgentRefDto, type PublishedAgentStatus, type PublishedBoardDto, type PublishedColumnDto, type PublishedColumnKey, type PublishedDocumentDto, type PublishedDocumentSummaryDto, type PublishedTaskCardDto, type PublishedTaskPriority, ROLE_OPTIONS, ROSTER_BLUEPRINT_SLUGS, ROSTER_LANE_KEYS, ROSTER_MAX_LANES, ROSTER_NAME_MAX, ROSTER_PROVISION_STATES, type RegisterCompanyRequest, type RegisterWorkErrorBody, type RegisterWorkErrorCode, type RegisterWorkRequest, type RegisterWorkResponse, type RegisterWorkStatus, type RelatedRepositories, type RemoveItemDto, type RepoVisibility, type RepositoryRole, type RepositoryTarget, type RosterBlueprintSlug, type RosterLaneKey, type RosterLaneResult, type RosterProvisionRecord, type RosterProvisionState, SHARED_VIEW_LIMITS, SHARED_VIEW_NOT_ACTIVE, SHARED_VIEW_STATUSES, type SharedViewIndexingMode, type SharedViewKnowledgeClassCountDto, type SharedViewLinkDto, type SharedViewSectionsDto, type SharedViewSessionDto, type SharedViewSessionRequestDto, type SharedViewSettingsDto, type SharedViewStatus, type SourceRepository, type SourceValidationSettingsDto, type SubmitItemDto, type SyncEventErrorClass, type SyncEventFailed, type SyncEventKind, type SyncEventPayload, type SyncEventSkipReason, type SyncEventSkipped, type SyncEventSource, type SyncEventSuccess, TEAM_SIZE_OPTIONS, UPGRADE_NOT_AVAILABLE_AFTER_MULTIPLE_ORGS, type UpdateItemDto, type UpdateItemsGeneratorDto, type UpdateOrganizationRequest, type UpdatePluginAllowlistEntryDto, type UpdateSharedViewDto, type UpdateSourceValidationPayload, type UpdateWorkSchedulePayload, type UpgradeFromAccountResponse, WORKSPACE_SEARCH_DEFAULT_PER_KIND, WORKSPACE_SEARCH_KINDS, WORKSPACE_SEARCH_MAX_PER_KIND, WORKSPACE_SEARCH_MAX_QUERY_LENGTH, WORKSPACE_SEARCH_MAX_RECENT, WORKSPACE_SEARCH_MAX_TOTAL, WORKSPACE_SEARCH_MIN_QUERY_LENGTH, type WebhookEvent, type WebhookEventDeployFailed, type WebhookEventManifestChanged, type WebhookEventTerminal, WebsiteRepositoryCreationMethod, type WorkChangelog, type WorkCurrentDeploymentHealthDto, type WorkCurrentHealthDto, type WorkCurrentState, type WorkDeploymentHealthSource, type WorkDeploymentReadiness, type WorkGenerationHistoryEntry, type WorkGenerationHistoryResponse, WorkHistoryActivityType, type WorkHistoryChangeAction, type WorkHistoryChangeEntityType, type WorkHistoryChangeEntry, type WorkLastDeploymentRunDto, type WorkLastGenerationRunDto, type WorkLastRunDto, type WorkScheduleAllowedCadence, WorkScheduleBillingMode, WorkScheduleCadence, type WorkScheduleDto, WorkScheduleStatus, type WorkStatusProjectionDto, type WorksConfigSnapshot, type WorksManifestMetadata, type WorksManifestOutput, type WorksManifestSpec, type WorksManifestV1, type WorkspaceSearchGroup, type WorkspaceSearchHit, type WorkspaceSearchKind, type WorkspaceSearchMatchReason, type WorkspaceSearchResponse, desktopNextStep, isChangelogCategory, isChangelogKind, isHelpArticleId, isHelpSection, isPublishableActivityAction, isSafeInAppPath, isSharedViewStatus, isTerminalOnboardingStatus };
|