@agent-native/creative-context 0.4.0 → 0.5.1
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 +51 -9
- package/agent-native.package.json +4 -0
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -0
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/list-context-memberships.d.ts +11 -0
- package/dist/actions/list-context-memberships.d.ts.map +1 -0
- package/dist/actions/list-context-memberships.js +47 -0
- package/dist/actions/list-context-memberships.js.map +1 -0
- package/dist/actions/list-creative-contexts.d.ts +12 -0
- package/dist/actions/list-creative-contexts.d.ts.map +1 -0
- package/dist/actions/list-creative-contexts.js +28 -0
- package/dist/actions/list-creative-contexts.js.map +1 -0
- package/dist/actions/manage-context-membership.d.ts +64 -0
- package/dist/actions/manage-context-membership.d.ts.map +1 -0
- package/dist/actions/manage-context-membership.js +70 -0
- package/dist/actions/manage-context-membership.js.map +1 -0
- package/dist/actions/manage-context-pack.d.ts +3 -0
- package/dist/actions/manage-context-pack.js +6 -0
- package/dist/actions/manage-context-pack.js.map +1 -1
- package/dist/actions/manage-context-source.js +4 -11
- package/dist/actions/manage-context-source.js.map +1 -1
- package/dist/actions/manage-creative-context.d.ts +28 -0
- package/dist/actions/manage-creative-context.d.ts.map +1 -0
- package/dist/actions/manage-creative-context.js +65 -0
- package/dist/actions/manage-creative-context.js.map +1 -0
- package/dist/actions/process-context-purge.d.ts +16 -1
- package/dist/actions/process-context-purge.js +2 -1
- package/dist/actions/process-context-purge.js.map +1 -1
- package/dist/actions/search-creative-context.d.ts +1 -0
- package/dist/actions/search-creative-context.js +2 -1
- package/dist/actions/search-creative-context.js.map +1 -1
- package/dist/client/CreativeContextChip.d.ts +7 -2
- package/dist/client/CreativeContextChip.d.ts.map +1 -1
- package/dist/client/CreativeContextChip.js +42 -7
- package/dist/client/CreativeContextChip.js.map +1 -1
- package/dist/client/CreativeContextPanel.d.ts.map +1 -1
- package/dist/client/CreativeContextPanel.js +406 -89
- package/dist/client/CreativeContextPanel.js.map +1 -1
- package/dist/client/CreativeContextShareTab.d.ts +56 -0
- package/dist/client/CreativeContextShareTab.d.ts.map +1 -0
- package/dist/client/CreativeContextShareTab.js +213 -0
- package/dist/client/CreativeContextShareTab.js.map +1 -0
- package/dist/client/actions.d.ts +210 -0
- package/dist/client/actions.d.ts.map +1 -1
- package/dist/client/actions.js +318 -0
- package/dist/client/actions.js.map +1 -1
- package/dist/client/application-state.d.ts +2 -0
- package/dist/client/application-state.d.ts.map +1 -1
- package/dist/client/application-state.js +25 -2
- package/dist/client/application-state.js.map +1 -1
- package/dist/client/index.d.ts +4 -3
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +4 -3
- package/dist/client/index.js.map +1 -1
- package/dist/client/messages.d.ts +1 -1
- package/dist/client/messages.d.ts.map +1 -1
- package/dist/client/messages.js +77 -0
- package/dist/client/messages.js.map +1 -1
- package/dist/connectors/types.d.ts +2 -2
- package/dist/connectors/types.d.ts.map +1 -1
- package/dist/schema/index.d.ts +1592 -0
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +95 -0
- package/dist/schema/index.js.map +1 -1
- package/dist/schema/migrations.d.ts.map +1 -1
- package/dist/schema/migrations.js +80 -0
- package/dist/schema/migrations.js.map +1 -1
- package/dist/server/generation-artifact-access.js +2 -0
- package/dist/server/generation-artifact-access.js.map +1 -1
- package/dist/server/generation-context.d.ts +12 -4
- package/dist/server/generation-context.d.ts.map +1 -1
- package/dist/server/generation-context.js +129 -7
- package/dist/server/generation-context.js.map +1 -1
- package/dist/server/index.d.ts +4 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +16 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/isolated-a2a.d.ts +3 -0
- package/dist/server/isolated-a2a.d.ts.map +1 -1
- package/dist/server/isolated-a2a.js +3 -1
- package/dist/server/isolated-a2a.js.map +1 -1
- package/dist/server/media.d.ts +1 -1
- package/dist/server/media.d.ts.map +1 -1
- package/dist/server/media.js +24 -9
- package/dist/server/media.js.map +1 -1
- package/dist/server/native-resource-capture.d.ts +78 -0
- package/dist/server/native-resource-capture.d.ts.map +1 -0
- package/dist/server/native-resource-capture.js +94 -0
- package/dist/server/native-resource-capture.js.map +1 -0
- package/dist/server/public-serialization.js +1 -1
- package/dist/server/public-serialization.js.map +1 -1
- package/dist/server/retrieval.d.ts +1 -0
- package/dist/server/retrieval.d.ts.map +1 -1
- package/dist/server/retrieval.js +2 -0
- package/dist/server/retrieval.js.map +1 -1
- package/dist/server/safe-native-preview.d.ts +15 -0
- package/dist/server/safe-native-preview.d.ts.map +1 -0
- package/dist/server/safe-native-preview.js +149 -0
- package/dist/server/safe-native-preview.js.map +1 -0
- package/dist/store/brand.d.ts.map +1 -1
- package/dist/store/brand.js +2 -16
- package/dist/store/brand.js.map +1 -1
- package/dist/store/content.d.ts +1 -0
- package/dist/store/content.d.ts.map +1 -1
- package/dist/store/content.js +84 -20
- package/dist/store/content.js.map +1 -1
- package/dist/store/contexts.d.ts +216 -0
- package/dist/store/contexts.d.ts.map +1 -0
- package/dist/store/contexts.js +1341 -0
- package/dist/store/contexts.js.map +1 -0
- package/dist/store/index.d.ts +1 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +1 -0
- package/dist/store/index.js.map +1 -1
- package/dist/store/packs.d.ts +3 -0
- package/dist/store/packs.d.ts.map +1 -1
- package/dist/store/packs.js +126 -9
- package/dist/store/packs.js.map +1 -1
- package/dist/store/purge.d.ts.map +1 -1
- package/dist/store/purge.js +103 -6
- package/dist/store/purge.js.map +1 -1
- package/dist/store/sources.d.ts.map +1 -1
- package/dist/store/sources.js +2 -15
- package/dist/store/sources.js.map +1 -1
- package/dist/store/suggestions.d.ts.map +1 -1
- package/dist/store/suggestions.js +3 -1
- package/dist/store/suggestions.js.map +1 -1
- package/dist/types.d.ts +77 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +9 -1
- package/dist/types.js.map +1 -1
- package/docs/skills/creative-context/SKILL.md +13 -5
- package/package.json +2 -2
- package/src/actions/index.ts +8 -0
- package/src/actions/job-public-serialization.spec.ts +21 -0
- package/src/actions/list-context-memberships.ts +56 -0
- package/src/actions/list-creative-contexts.spec.ts +38 -0
- package/src/actions/list-creative-contexts.ts +32 -0
- package/src/actions/manage-context-membership.ts +80 -0
- package/src/actions/manage-context-pack.ts +6 -0
- package/src/actions/manage-context-source.ts +8 -11
- package/src/actions/manage-creative-context.ts +73 -0
- package/src/actions/process-context-purge.ts +4 -1
- package/src/actions/search-creative-context.ts +2 -1
- package/src/client/CreativeContextChip.spec.ts +59 -0
- package/src/client/CreativeContextChip.tsx +95 -14
- package/src/client/CreativeContextPanel.tsx +1947 -885
- package/src/client/CreativeContextShareTab.spec.ts +70 -0
- package/src/client/CreativeContextShareTab.tsx +657 -0
- package/src/client/actions.spec.ts +177 -0
- package/src/client/actions.ts +566 -0
- package/src/client/application-state.spec.ts +5 -0
- package/src/client/application-state.ts +30 -2
- package/src/client/index.ts +33 -0
- package/src/client/messages.ts +95 -0
- package/src/connectors/types.ts +6 -8
- package/src/eval/library-flow.acceptance.spec.tsx +1 -0
- package/src/schema/index.ts +116 -0
- package/src/schema/migrations.ts +80 -0
- package/src/server/generation-artifact-access.ts +1 -0
- package/src/server/generation-context-a2a.spec.ts +133 -0
- package/src/server/generation-context.ts +153 -7
- package/src/server/index.spec.ts +15 -0
- package/src/server/index.ts +16 -0
- package/src/server/isolated-a2a.ts +4 -1
- package/src/server/media.spec.ts +30 -2
- package/src/server/media.ts +31 -12
- package/src/server/native-resource-capture.spec.ts +121 -0
- package/src/server/native-resource-capture.ts +198 -0
- package/src/server/public-serialization.spec.ts +1 -0
- package/src/server/public-serialization.ts +1 -1
- package/src/server/retrieval.ts +3 -0
- package/src/server/safe-native-preview.spec.ts +29 -0
- package/src/server/safe-native-preview.ts +200 -0
- package/src/store/access.integration.spec.ts +1116 -0
- package/src/store/brand.ts +2 -21
- package/src/store/content.ts +217 -17
- package/src/store/contexts.ts +1826 -0
- package/src/store/index.ts +1 -0
- package/src/store/packs.ts +279 -24
- package/src/store/purge.ts +139 -6
- package/src/store/sources.ts +2 -18
- package/src/store/suggestions.ts +3 -1
- package/src/types.ts +95 -0
package/src/client/actions.ts
CHANGED
|
@@ -18,6 +18,10 @@ import type {
|
|
|
18
18
|
} from "../types.js";
|
|
19
19
|
|
|
20
20
|
export const CREATIVE_CONTEXT_ACTIONS = {
|
|
21
|
+
listContexts: "list-creative-contexts",
|
|
22
|
+
manageContext: "manage-creative-context",
|
|
23
|
+
listMemberships: "list-context-memberships",
|
|
24
|
+
manageMembership: "manage-context-membership",
|
|
21
25
|
listSources: "list-context-sources",
|
|
22
26
|
manageSource: "manage-context-source",
|
|
23
27
|
previewImport: "preview-context-import",
|
|
@@ -41,6 +45,536 @@ export const CREATIVE_CONTEXT_ACTIONS = {
|
|
|
41
45
|
manageLayoutTemplate: "manage-layout-template",
|
|
42
46
|
} as const;
|
|
43
47
|
|
|
48
|
+
export type CreativeContextPolicy = "open" | "review" | "admins-only";
|
|
49
|
+
export type CreativeContextMembershipRank = "canonical" | "exemplar" | "normal";
|
|
50
|
+
|
|
51
|
+
export type CreativeContextSafePreview =
|
|
52
|
+
| {
|
|
53
|
+
type: "slides";
|
|
54
|
+
slideCount: number;
|
|
55
|
+
slides: Array<{ index: number; title: string; excerpt: string }>;
|
|
56
|
+
}
|
|
57
|
+
| { type: "slide"; index: number; title: string; excerpt: string }
|
|
58
|
+
| {
|
|
59
|
+
type: "design";
|
|
60
|
+
fileCount: number;
|
|
61
|
+
frames: Array<{ title: string; fileType: string; excerpt: string }>;
|
|
62
|
+
}
|
|
63
|
+
| {
|
|
64
|
+
type: "design-frame";
|
|
65
|
+
title: string;
|
|
66
|
+
fileType: string;
|
|
67
|
+
excerpt: string;
|
|
68
|
+
}
|
|
69
|
+
| {
|
|
70
|
+
type: "document";
|
|
71
|
+
headings: string[];
|
|
72
|
+
excerpt: string;
|
|
73
|
+
blocks: Array<{
|
|
74
|
+
kind: "heading" | "paragraph" | "bullet" | "quote" | "code";
|
|
75
|
+
text: string;
|
|
76
|
+
level?: number;
|
|
77
|
+
}>;
|
|
78
|
+
}
|
|
79
|
+
| {
|
|
80
|
+
type: "asset";
|
|
81
|
+
mediaType: "image" | "video";
|
|
82
|
+
width: number | null;
|
|
83
|
+
height: number | null;
|
|
84
|
+
durationSeconds: number | null;
|
|
85
|
+
}
|
|
86
|
+
| {
|
|
87
|
+
type: "dashboard";
|
|
88
|
+
data: "synthetic";
|
|
89
|
+
panels: Array<{ id: string; title: string; visualization: string }>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export interface CreativeContextSummary {
|
|
93
|
+
id: string;
|
|
94
|
+
name: string;
|
|
95
|
+
description?: string | null;
|
|
96
|
+
kind: "default" | "specialty";
|
|
97
|
+
memberCount: number;
|
|
98
|
+
updatedAt?: string | null;
|
|
99
|
+
approvalPolicy: CreativeContextPolicy;
|
|
100
|
+
visibility: "private" | "org" | "public";
|
|
101
|
+
access: {
|
|
102
|
+
role: "viewer" | "editor" | "admin" | "owner";
|
|
103
|
+
canSubmit: boolean;
|
|
104
|
+
canReview: boolean;
|
|
105
|
+
canAdmin: boolean;
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export interface CreativeContextPreviewItem {
|
|
110
|
+
id: string;
|
|
111
|
+
itemVersionId: string;
|
|
112
|
+
title: string;
|
|
113
|
+
kind: string;
|
|
114
|
+
status: string;
|
|
115
|
+
sourceModifiedAt: string | null;
|
|
116
|
+
preview: CreativeContextSafePreview | null;
|
|
117
|
+
media: Array<{
|
|
118
|
+
id: string;
|
|
119
|
+
kind: string;
|
|
120
|
+
mimeType: string | null;
|
|
121
|
+
url: string;
|
|
122
|
+
}>;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export interface CreativeContextMembership {
|
|
126
|
+
id: string;
|
|
127
|
+
contextId: string;
|
|
128
|
+
publishedItemId: string | null;
|
|
129
|
+
publishedItemVersionId: string | null;
|
|
130
|
+
pendingSubmissionId: string | null;
|
|
131
|
+
rank: CreativeContextMembershipRank;
|
|
132
|
+
purpose: string | null;
|
|
133
|
+
status: "active" | "removed";
|
|
134
|
+
updatedAt?: string | null;
|
|
135
|
+
nativeUpdateStatus?: {
|
|
136
|
+
state: "current" | "update-available" | "unknown";
|
|
137
|
+
} | null;
|
|
138
|
+
publishedItem?: CreativeContextPreviewItem | null;
|
|
139
|
+
pendingSubmission?: {
|
|
140
|
+
id: string;
|
|
141
|
+
status: string;
|
|
142
|
+
note: string | null;
|
|
143
|
+
submittedBy: string;
|
|
144
|
+
proposedItem: CreativeContextPreviewItem | null;
|
|
145
|
+
} | null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface ListCreativeContextsParams {
|
|
149
|
+
limit?: number;
|
|
150
|
+
cursor?: string;
|
|
151
|
+
includeArchived?: boolean;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export interface ListCreativeContextsResult {
|
|
155
|
+
contexts: CreativeContextSummary[];
|
|
156
|
+
appId?: string;
|
|
157
|
+
appDefaultContextId?: string | null;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export type ManageCreativeContextParams =
|
|
161
|
+
| {
|
|
162
|
+
operation: "create";
|
|
163
|
+
name: string;
|
|
164
|
+
description?: string | null;
|
|
165
|
+
kind: "default" | "specialty";
|
|
166
|
+
brandProfileId?: string | null;
|
|
167
|
+
approvalPolicy?: CreativeContextPolicy;
|
|
168
|
+
}
|
|
169
|
+
| {
|
|
170
|
+
operation: "update";
|
|
171
|
+
contextId: string;
|
|
172
|
+
patch: {
|
|
173
|
+
name?: string;
|
|
174
|
+
description?: string | null;
|
|
175
|
+
brandProfileId?: string | null;
|
|
176
|
+
approvalPolicy?: CreativeContextPolicy;
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
| { operation: "archive"; contextId: string }
|
|
180
|
+
| { operation: "set-app-default"; contextId: string; appId: string };
|
|
181
|
+
|
|
182
|
+
export interface ManageCreativeContextResult {
|
|
183
|
+
context: CreativeContextSummary | null;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
export interface ListContextMembershipsParams {
|
|
187
|
+
contextId: string;
|
|
188
|
+
status?: "active" | "removed";
|
|
189
|
+
limit?: number;
|
|
190
|
+
cursor?: string;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface ListContextMembershipsResult {
|
|
194
|
+
memberships: CreativeContextMembership[];
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export type ManageContextMembershipParams =
|
|
198
|
+
| {
|
|
199
|
+
operation: "submit";
|
|
200
|
+
contextId: string;
|
|
201
|
+
itemId?: string;
|
|
202
|
+
itemVersionId?: string;
|
|
203
|
+
nativeResource?: {
|
|
204
|
+
appId: string;
|
|
205
|
+
resourceType: string;
|
|
206
|
+
resourceId: string;
|
|
207
|
+
expectedUpdatedAt?: string;
|
|
208
|
+
};
|
|
209
|
+
rank?: CreativeContextMembershipRank;
|
|
210
|
+
purpose?: string;
|
|
211
|
+
note?: string;
|
|
212
|
+
confirmBroaderPublication?: true;
|
|
213
|
+
}
|
|
214
|
+
| {
|
|
215
|
+
operation: "submit-latest";
|
|
216
|
+
contextId: string;
|
|
217
|
+
membershipId: string;
|
|
218
|
+
note?: string;
|
|
219
|
+
confirmBroaderPublication?: true;
|
|
220
|
+
}
|
|
221
|
+
| {
|
|
222
|
+
operation: "approve" | "request-changes" | "withdraw" | "remove";
|
|
223
|
+
contextId: string;
|
|
224
|
+
membershipId: string;
|
|
225
|
+
note?: string | null;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export interface ManageContextMembershipResult {
|
|
229
|
+
membership: CreativeContextMembership | null;
|
|
230
|
+
membershipId?: string;
|
|
231
|
+
submission?: { id: string; status: string };
|
|
232
|
+
withdrawn?: boolean;
|
|
233
|
+
approved?: boolean;
|
|
234
|
+
requestChanges?: boolean;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
function record(value: unknown): Record<string, unknown> | null {
|
|
238
|
+
return value && typeof value === "object"
|
|
239
|
+
? (value as Record<string, unknown>)
|
|
240
|
+
: null;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
function previewString(value: unknown, limit: number) {
|
|
244
|
+
return typeof value === "string" ? value.slice(0, limit) : "";
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function previewNumber(value: unknown) {
|
|
248
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Accept only the compact structured preview contract. Native payloads and
|
|
253
|
+
* arbitrary item metadata deliberately never cross into the shared client.
|
|
254
|
+
*/
|
|
255
|
+
export function parseCreativeContextSafePreview(
|
|
256
|
+
value: unknown,
|
|
257
|
+
): CreativeContextSafePreview | null {
|
|
258
|
+
const preview = record(value);
|
|
259
|
+
if (!preview || typeof preview.type !== "string") return null;
|
|
260
|
+
if (preview.type === "slides") {
|
|
261
|
+
const slides = Array.isArray(preview.slides)
|
|
262
|
+
? preview.slides.slice(0, 24).flatMap((entry, index) => {
|
|
263
|
+
const slide = record(entry);
|
|
264
|
+
if (!slide) return [];
|
|
265
|
+
return [
|
|
266
|
+
{
|
|
267
|
+
index:
|
|
268
|
+
typeof slide.index === "number" && slide.index > 0
|
|
269
|
+
? Math.floor(slide.index)
|
|
270
|
+
: index + 1,
|
|
271
|
+
title: previewString(slide.title, 160) || `Slide ${index + 1}`,
|
|
272
|
+
excerpt: previewString(slide.excerpt, 320),
|
|
273
|
+
},
|
|
274
|
+
];
|
|
275
|
+
})
|
|
276
|
+
: [];
|
|
277
|
+
return {
|
|
278
|
+
type: "slides",
|
|
279
|
+
slideCount:
|
|
280
|
+
typeof preview.slideCount === "number" && preview.slideCount >= 0
|
|
281
|
+
? Math.floor(preview.slideCount)
|
|
282
|
+
: slides.length,
|
|
283
|
+
slides,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (preview.type === "slide") {
|
|
287
|
+
return {
|
|
288
|
+
type: "slide",
|
|
289
|
+
index:
|
|
290
|
+
typeof preview.index === "number" && preview.index > 0
|
|
291
|
+
? Math.floor(preview.index)
|
|
292
|
+
: 1,
|
|
293
|
+
title: previewString(preview.title, 160) || "Slide",
|
|
294
|
+
excerpt: previewString(preview.excerpt, 500),
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
if (preview.type === "design") {
|
|
298
|
+
const frames = Array.isArray(preview.frames)
|
|
299
|
+
? preview.frames.slice(0, 24).flatMap((entry) => {
|
|
300
|
+
const frame = record(entry);
|
|
301
|
+
if (!frame) return [];
|
|
302
|
+
return [
|
|
303
|
+
{
|
|
304
|
+
title: previewString(frame.title, 160) || "Untitled frame",
|
|
305
|
+
fileType: previewString(frame.fileType, 80) || "design",
|
|
306
|
+
excerpt: previewString(frame.excerpt, 320),
|
|
307
|
+
},
|
|
308
|
+
];
|
|
309
|
+
})
|
|
310
|
+
: [];
|
|
311
|
+
return {
|
|
312
|
+
type: "design",
|
|
313
|
+
fileCount:
|
|
314
|
+
typeof preview.fileCount === "number" && preview.fileCount >= 0
|
|
315
|
+
? Math.floor(preview.fileCount)
|
|
316
|
+
: frames.length,
|
|
317
|
+
frames,
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
if (preview.type === "design-frame") {
|
|
321
|
+
return {
|
|
322
|
+
type: "design-frame",
|
|
323
|
+
title: previewString(preview.title, 160) || "Untitled frame",
|
|
324
|
+
fileType: previewString(preview.fileType, 80) || "design",
|
|
325
|
+
excerpt: previewString(preview.excerpt, 500),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
if (preview.type === "document" || preview.type === "markdown") {
|
|
329
|
+
const headings = Array.isArray(preview.headings)
|
|
330
|
+
? preview.headings
|
|
331
|
+
.slice(0, 8)
|
|
332
|
+
.map((heading) => previewString(heading, 160))
|
|
333
|
+
.filter(Boolean)
|
|
334
|
+
: [];
|
|
335
|
+
const blocks = Array.isArray(preview.blocks)
|
|
336
|
+
? preview.blocks.slice(0, 40).flatMap((entry) => {
|
|
337
|
+
const block = record(entry);
|
|
338
|
+
if (!block) return [];
|
|
339
|
+
const kind: "heading" | "paragraph" | "bullet" | "quote" | "code" =
|
|
340
|
+
block.kind === "heading" ||
|
|
341
|
+
block.kind === "bullet" ||
|
|
342
|
+
block.kind === "quote" ||
|
|
343
|
+
block.kind === "code"
|
|
344
|
+
? block.kind
|
|
345
|
+
: "paragraph";
|
|
346
|
+
const text = previewString(block.text, 600);
|
|
347
|
+
if (!text) return [];
|
|
348
|
+
const level =
|
|
349
|
+
kind === "heading" &&
|
|
350
|
+
typeof block.level === "number" &&
|
|
351
|
+
block.level >= 1 &&
|
|
352
|
+
block.level <= 6
|
|
353
|
+
? Math.floor(block.level)
|
|
354
|
+
: undefined;
|
|
355
|
+
return [{ kind, text, ...(level ? { level } : {}) }];
|
|
356
|
+
})
|
|
357
|
+
: [];
|
|
358
|
+
return {
|
|
359
|
+
type: "document",
|
|
360
|
+
headings,
|
|
361
|
+
excerpt: previewString(preview.excerpt, 1_500),
|
|
362
|
+
blocks,
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
if (preview.type === "asset") {
|
|
366
|
+
return {
|
|
367
|
+
type: "asset",
|
|
368
|
+
mediaType: preview.mediaType === "video" ? "video" : "image",
|
|
369
|
+
width: previewNumber(preview.width),
|
|
370
|
+
height: previewNumber(preview.height),
|
|
371
|
+
durationSeconds: previewNumber(preview.durationSeconds),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
if (preview.type === "dashboard") {
|
|
375
|
+
const panels = Array.isArray(preview.panels)
|
|
376
|
+
? preview.panels.slice(0, 24).flatMap((entry, index) => {
|
|
377
|
+
const panel = record(entry);
|
|
378
|
+
if (!panel) return [];
|
|
379
|
+
return [
|
|
380
|
+
{
|
|
381
|
+
id: previewString(panel.id, 120) || String(index + 1),
|
|
382
|
+
title: previewString(panel.title, 160) || `Panel ${index + 1}`,
|
|
383
|
+
visualization: previewString(panel.visualization, 80) || "chart",
|
|
384
|
+
},
|
|
385
|
+
];
|
|
386
|
+
})
|
|
387
|
+
: [];
|
|
388
|
+
return { type: "dashboard", data: "synthetic", panels };
|
|
389
|
+
}
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
function contextSummary(value: unknown): CreativeContextSummary | null {
|
|
394
|
+
const source = record(value);
|
|
395
|
+
if (
|
|
396
|
+
!source ||
|
|
397
|
+
typeof source.id !== "string" ||
|
|
398
|
+
typeof source.name !== "string"
|
|
399
|
+
) {
|
|
400
|
+
return null;
|
|
401
|
+
}
|
|
402
|
+
const access = record(source.access);
|
|
403
|
+
const role =
|
|
404
|
+
access?.role === "owner" ||
|
|
405
|
+
access?.role === "admin" ||
|
|
406
|
+
access?.role === "editor"
|
|
407
|
+
? access.role
|
|
408
|
+
: "viewer";
|
|
409
|
+
return {
|
|
410
|
+
id: source.id,
|
|
411
|
+
name: source.name,
|
|
412
|
+
description:
|
|
413
|
+
typeof source.description === "string" ? source.description : null,
|
|
414
|
+
kind: source.kind === "specialty" ? "specialty" : "default",
|
|
415
|
+
memberCount:
|
|
416
|
+
typeof source.memberCount === "number" ? source.memberCount : 0,
|
|
417
|
+
updatedAt: typeof source.updatedAt === "string" ? source.updatedAt : null,
|
|
418
|
+
approvalPolicy:
|
|
419
|
+
source.approvalPolicy === "review" ||
|
|
420
|
+
source.approvalPolicy === "admins-only"
|
|
421
|
+
? source.approvalPolicy
|
|
422
|
+
: "open",
|
|
423
|
+
visibility:
|
|
424
|
+
source.visibility === "org" || source.visibility === "public"
|
|
425
|
+
? source.visibility
|
|
426
|
+
: "private",
|
|
427
|
+
access: {
|
|
428
|
+
role,
|
|
429
|
+
canSubmit: access?.canSubmit === true,
|
|
430
|
+
canReview: access?.canReview === true,
|
|
431
|
+
canAdmin: access?.canAdmin === true,
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
export function parseCreativeContexts(
|
|
437
|
+
value: unknown,
|
|
438
|
+
): CreativeContextSummary[] {
|
|
439
|
+
const source = Array.isArray(value)
|
|
440
|
+
? value
|
|
441
|
+
: (record(value)?.contexts ?? record(value)?.items ?? []);
|
|
442
|
+
return Array.isArray(source)
|
|
443
|
+
? source
|
|
444
|
+
.map(contextSummary)
|
|
445
|
+
.filter((item): item is CreativeContextSummary => Boolean(item))
|
|
446
|
+
: [];
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
function parseContextPreviewItem(
|
|
450
|
+
value: unknown,
|
|
451
|
+
): CreativeContextPreviewItem | null {
|
|
452
|
+
const item = record(value);
|
|
453
|
+
if (
|
|
454
|
+
!item ||
|
|
455
|
+
typeof item.id !== "string" ||
|
|
456
|
+
typeof item.itemVersionId !== "string" ||
|
|
457
|
+
typeof item.title !== "string" ||
|
|
458
|
+
typeof item.kind !== "string"
|
|
459
|
+
)
|
|
460
|
+
return null;
|
|
461
|
+
const media = Array.isArray(item.media)
|
|
462
|
+
? item.media.flatMap((value) => {
|
|
463
|
+
const medium = record(value);
|
|
464
|
+
return medium &&
|
|
465
|
+
typeof medium.id === "string" &&
|
|
466
|
+
typeof medium.kind === "string" &&
|
|
467
|
+
typeof medium.url === "string"
|
|
468
|
+
? [
|
|
469
|
+
{
|
|
470
|
+
id: medium.id,
|
|
471
|
+
kind: medium.kind,
|
|
472
|
+
mimeType:
|
|
473
|
+
typeof medium.mimeType === "string" ? medium.mimeType : null,
|
|
474
|
+
url: medium.url,
|
|
475
|
+
},
|
|
476
|
+
]
|
|
477
|
+
: [];
|
|
478
|
+
})
|
|
479
|
+
: [];
|
|
480
|
+
return {
|
|
481
|
+
id: item.id,
|
|
482
|
+
itemVersionId: item.itemVersionId,
|
|
483
|
+
title: item.title,
|
|
484
|
+
kind: item.kind,
|
|
485
|
+
status: typeof item.status === "string" ? item.status : "active",
|
|
486
|
+
sourceModifiedAt:
|
|
487
|
+
typeof item.sourceModifiedAt === "string" ? item.sourceModifiedAt : null,
|
|
488
|
+
preview: parseCreativeContextSafePreview(item.preview),
|
|
489
|
+
media,
|
|
490
|
+
};
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export function parseContextMemberships(
|
|
494
|
+
value: unknown,
|
|
495
|
+
): CreativeContextMembership[] {
|
|
496
|
+
const source = Array.isArray(value)
|
|
497
|
+
? value
|
|
498
|
+
: (record(value)?.memberships ?? record(value)?.items ?? []);
|
|
499
|
+
if (!Array.isArray(source)) return [];
|
|
500
|
+
return source.flatMap((value) => {
|
|
501
|
+
const item = record(value);
|
|
502
|
+
if (
|
|
503
|
+
!item ||
|
|
504
|
+
typeof item.id !== "string" ||
|
|
505
|
+
typeof item.contextId !== "string"
|
|
506
|
+
) {
|
|
507
|
+
return [];
|
|
508
|
+
}
|
|
509
|
+
return [
|
|
510
|
+
{
|
|
511
|
+
id: item.id,
|
|
512
|
+
contextId: item.contextId,
|
|
513
|
+
publishedItemId:
|
|
514
|
+
typeof item.publishedItemId === "string"
|
|
515
|
+
? item.publishedItemId
|
|
516
|
+
: null,
|
|
517
|
+
publishedItemVersionId:
|
|
518
|
+
typeof item.publishedItemVersionId === "string"
|
|
519
|
+
? item.publishedItemVersionId
|
|
520
|
+
: null,
|
|
521
|
+
pendingSubmissionId:
|
|
522
|
+
typeof item.pendingSubmissionId === "string"
|
|
523
|
+
? item.pendingSubmissionId
|
|
524
|
+
: null,
|
|
525
|
+
rank:
|
|
526
|
+
item.rank === "canonical" || item.rank === "exemplar"
|
|
527
|
+
? item.rank
|
|
528
|
+
: "normal",
|
|
529
|
+
purpose: typeof item.purpose === "string" ? item.purpose : null,
|
|
530
|
+
status: item.status === "removed" ? "removed" : "active",
|
|
531
|
+
updatedAt: typeof item.updatedAt === "string" ? item.updatedAt : null,
|
|
532
|
+
nativeUpdateStatus: (() => {
|
|
533
|
+
const status = record(item.nativeUpdateStatus)?.state;
|
|
534
|
+
return status === "current" ||
|
|
535
|
+
status === "update-available" ||
|
|
536
|
+
status === "unknown"
|
|
537
|
+
? { state: status }
|
|
538
|
+
: null;
|
|
539
|
+
})(),
|
|
540
|
+
pendingSubmission: (() => {
|
|
541
|
+
const submission = record(item.pendingSubmission);
|
|
542
|
+
return submission &&
|
|
543
|
+
typeof submission.id === "string" &&
|
|
544
|
+
typeof submission.status === "string"
|
|
545
|
+
? {
|
|
546
|
+
id: submission.id,
|
|
547
|
+
status: submission.status,
|
|
548
|
+
note:
|
|
549
|
+
typeof submission.note === "string" ? submission.note : null,
|
|
550
|
+
submittedBy:
|
|
551
|
+
typeof submission.submittedBy === "string"
|
|
552
|
+
? submission.submittedBy
|
|
553
|
+
: "",
|
|
554
|
+
proposedItem: parseContextPreviewItem(submission.proposedItem),
|
|
555
|
+
}
|
|
556
|
+
: null;
|
|
557
|
+
})(),
|
|
558
|
+
publishedItem: parseContextPreviewItem(item.publishedItem),
|
|
559
|
+
},
|
|
560
|
+
];
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export function parseContextMembershipsForResource(
|
|
565
|
+
value: unknown,
|
|
566
|
+
resource: { appId: string; resourceType: string; resourceId: string },
|
|
567
|
+
): CreativeContextMembership[] {
|
|
568
|
+
const source = record(value)?.memberships;
|
|
569
|
+
if (!Array.isArray(source)) return [];
|
|
570
|
+
const artifactKey = `${resource.appId}:${resource.resourceType}:${resource.resourceId}`;
|
|
571
|
+
return parseContextMemberships({
|
|
572
|
+
memberships: source.filter(
|
|
573
|
+
(value) => record(value)?.artifactKey === artifactKey,
|
|
574
|
+
),
|
|
575
|
+
});
|
|
576
|
+
}
|
|
577
|
+
|
|
44
578
|
export interface CanonicalLogoCandidate {
|
|
45
579
|
mediaId: string;
|
|
46
580
|
itemId: string;
|
|
@@ -80,6 +614,7 @@ export interface SearchCreativeContextParams {
|
|
|
80
614
|
query: string;
|
|
81
615
|
sourceIds?: string[];
|
|
82
616
|
packId?: string;
|
|
617
|
+
contextId?: string;
|
|
83
618
|
kinds?: string[];
|
|
84
619
|
limit?: number;
|
|
85
620
|
cursor?: string;
|
|
@@ -294,6 +829,37 @@ export function useCreativeContextSources(
|
|
|
294
829
|
);
|
|
295
830
|
}
|
|
296
831
|
|
|
832
|
+
export function useCreativeContexts(params: ListCreativeContextsParams = {}) {
|
|
833
|
+
return useActionQuery<ListCreativeContextsResult>(
|
|
834
|
+
CREATIVE_CONTEXT_ACTIONS.listContexts,
|
|
835
|
+
{ limit: 50, ...params },
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
export function useManageCreativeContext() {
|
|
840
|
+
return useActionMutation<
|
|
841
|
+
ManageCreativeContextResult,
|
|
842
|
+
ManageCreativeContextParams
|
|
843
|
+
>(CREATIVE_CONTEXT_ACTIONS.manageContext);
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
export function useContextMemberships(
|
|
847
|
+
params: ListContextMembershipsParams | null,
|
|
848
|
+
) {
|
|
849
|
+
return useActionQuery<ListContextMembershipsResult>(
|
|
850
|
+
CREATIVE_CONTEXT_ACTIONS.listMemberships,
|
|
851
|
+
params ? { limit: 50, ...params } : undefined,
|
|
852
|
+
{ enabled: Boolean(params) },
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
export function useManageContextMembership() {
|
|
857
|
+
return useActionMutation<
|
|
858
|
+
ManageContextMembershipResult,
|
|
859
|
+
ManageContextMembershipParams
|
|
860
|
+
>(CREATIVE_CONTEXT_ACTIONS.manageMembership);
|
|
861
|
+
}
|
|
862
|
+
|
|
297
863
|
export function useCreativeContextSearch() {
|
|
298
864
|
return useActionMutation<
|
|
299
865
|
SearchCreativeContextResult,
|
|
@@ -6,6 +6,7 @@ describe("normalizeCreativeContextState", () => {
|
|
|
6
6
|
it("defaults missing state to automatic context", () => {
|
|
7
7
|
expect(normalizeCreativeContextState(null)).toEqual({
|
|
8
8
|
contextMode: "auto",
|
|
9
|
+
selectedContextId: null,
|
|
9
10
|
currentPackId: null,
|
|
10
11
|
pinnedPackId: null,
|
|
11
12
|
});
|
|
@@ -15,11 +16,13 @@ describe("normalizeCreativeContextState", () => {
|
|
|
15
16
|
expect(
|
|
16
17
|
normalizeCreativeContextState({
|
|
17
18
|
contextMode: "off",
|
|
19
|
+
selectedContextId: "selected-context",
|
|
18
20
|
currentPackId: "current-pack",
|
|
19
21
|
pinnedPackId: "pinned-pack",
|
|
20
22
|
}),
|
|
21
23
|
).toEqual({
|
|
22
24
|
contextMode: "off",
|
|
25
|
+
selectedContextId: null,
|
|
23
26
|
currentPackId: null,
|
|
24
27
|
pinnedPackId: null,
|
|
25
28
|
});
|
|
@@ -29,11 +32,13 @@ describe("normalizeCreativeContextState", () => {
|
|
|
29
32
|
expect(
|
|
30
33
|
normalizeCreativeContextState({
|
|
31
34
|
contextMode: "auto",
|
|
35
|
+
selectedContextId: " selected-context ",
|
|
32
36
|
currentPackId: " current-pack ",
|
|
33
37
|
pinnedPackId: "pinned-pack",
|
|
34
38
|
}),
|
|
35
39
|
).toEqual({
|
|
36
40
|
contextMode: "auto",
|
|
41
|
+
selectedContextId: "selected-context",
|
|
37
42
|
currentPackId: "current-pack",
|
|
38
43
|
pinnedPackId: "pinned-pack",
|
|
39
44
|
});
|
|
@@ -12,12 +12,14 @@ export type CreativeContextMode = "auto" | "off";
|
|
|
12
12
|
|
|
13
13
|
export interface CreativeContextApplicationState {
|
|
14
14
|
contextMode: CreativeContextMode;
|
|
15
|
+
selectedContextId?: string | null;
|
|
15
16
|
currentPackId?: string | null;
|
|
16
17
|
pinnedPackId?: string | null;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export const DEFAULT_CREATIVE_CONTEXT_STATE: CreativeContextApplicationState = {
|
|
20
21
|
contextMode: "auto",
|
|
22
|
+
selectedContextId: null,
|
|
21
23
|
currentPackId: null,
|
|
22
24
|
pinnedPackId: null,
|
|
23
25
|
};
|
|
@@ -38,12 +40,14 @@ export function normalizeCreativeContextState(
|
|
|
38
40
|
if (contextMode === "off") {
|
|
39
41
|
return {
|
|
40
42
|
contextMode,
|
|
43
|
+
selectedContextId: null,
|
|
41
44
|
currentPackId: null,
|
|
42
45
|
pinnedPackId: null,
|
|
43
46
|
};
|
|
44
47
|
}
|
|
45
48
|
return {
|
|
46
49
|
contextMode,
|
|
50
|
+
selectedContextId: normalizePackId(record.selectedContextId),
|
|
47
51
|
currentPackId: normalizePackId(record.currentPackId),
|
|
48
52
|
pinnedPackId: normalizePackId(record.pinnedPackId),
|
|
49
53
|
};
|
|
@@ -76,8 +80,18 @@ export async function setCreativeContextMode(
|
|
|
76
80
|
const state = current ?? (await readCreativeContextState());
|
|
77
81
|
return setCreativeContextState(
|
|
78
82
|
mode === "off"
|
|
79
|
-
? {
|
|
80
|
-
|
|
83
|
+
? {
|
|
84
|
+
contextMode: "off",
|
|
85
|
+
selectedContextId: null,
|
|
86
|
+
currentPackId: null,
|
|
87
|
+
pinnedPackId: null,
|
|
88
|
+
}
|
|
89
|
+
: {
|
|
90
|
+
...state,
|
|
91
|
+
contextMode: "auto",
|
|
92
|
+
selectedContextId: null,
|
|
93
|
+
pinnedPackId: null,
|
|
94
|
+
},
|
|
81
95
|
);
|
|
82
96
|
}
|
|
83
97
|
|
|
@@ -89,10 +103,24 @@ export async function setPinnedCreativeContextPack(
|
|
|
89
103
|
return setCreativeContextState({
|
|
90
104
|
...state,
|
|
91
105
|
contextMode: "auto",
|
|
106
|
+
selectedContextId: null,
|
|
92
107
|
pinnedPackId: normalizePackId(packId),
|
|
93
108
|
});
|
|
94
109
|
}
|
|
95
110
|
|
|
111
|
+
export async function setSelectedCreativeContext(
|
|
112
|
+
contextId: string | null,
|
|
113
|
+
current?: CreativeContextApplicationState,
|
|
114
|
+
): Promise<CreativeContextApplicationState> {
|
|
115
|
+
const state = current ?? (await readCreativeContextState());
|
|
116
|
+
return setCreativeContextState({
|
|
117
|
+
...state,
|
|
118
|
+
contextMode: "auto",
|
|
119
|
+
selectedContextId: normalizePackId(contextId),
|
|
120
|
+
pinnedPackId: null,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
96
124
|
export function useCreativeContextState() {
|
|
97
125
|
const appStateVersion = useChangeVersion("app-state");
|
|
98
126
|
const [state, setState] = useState<CreativeContextApplicationState>(
|