@joai/core 4.6.0 → 4.7.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/dist/index.d.mts CHANGED
@@ -1,4 +1,3 @@
1
- import { _ as MediaMime, a as ContentFieldType, b as IHttpService, c as ContentValue, d as PatchContentInput, f as AppFile, g as MediaLibraryAttributes, h as MediaAspectRatio, i as ContentField, l as ContentVersion, m as Media, n as ContentDefinition, o as ContentPatch, p as AppFileType, r as ContentEntry, s as ContentStatus, t as Content, u as CreateContentInput, v as JsonValue, x as IRequestOptions, y as IAppResponse } from "./types-BbqlPvhU.mjs";
2
1
  import { Warp, WarpActionInput, WarpBrandUrls, WarpChainInfo, WarpChainName, WarpI18nText, WarpLocale, WarpNativeValue, WarpSecret, WarpText, WarpWalletProvider } from "@joai/warps";
3
2
 
4
3
  //#region src/auth/types.d.ts
@@ -44,6 +43,37 @@ declare const JoaiUrls: {
44
43
  readonly PlayStore: "https://play.google.com/store/apps/details?id=ai.joai.app";
45
44
  };
46
45
  //#endregion
46
+ //#region src/http/types.d.ts
47
+ interface IHttpService {
48
+ readonly baseUrl: string;
49
+ readonly authToken: string | null;
50
+ onNetworkError: (error: Error) => void;
51
+ onUnauthorized: (response: IAppResponse<any>) => void;
52
+ onSuccessfulResponse: (response: IAppResponse<any>) => void;
53
+ onMaintenanceMode: (response: IAppResponse<any>) => void;
54
+ get: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
55
+ post: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
56
+ put: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
57
+ patch: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
58
+ delete: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
59
+ }
60
+ interface IAppResponse<T> {
61
+ data: T;
62
+ meta?: any;
63
+ body: any;
64
+ errors: any;
65
+ ok: boolean;
66
+ paymentRequired: boolean;
67
+ noContent: boolean;
68
+ original: Response;
69
+ }
70
+ interface IRequestOptions {
71
+ isJson?: boolean;
72
+ headers?: {
73
+ [name: string]: string;
74
+ };
75
+ }
76
+ //#endregion
47
77
  //#region src/http/service.d.ts
48
78
  declare class HttpService implements IHttpService {
49
79
  readonly baseUrl: string;
@@ -361,6 +391,11 @@ type WalletList = Partial<Record<WarpChainName, {
361
391
  address?: string;
362
392
  }>>;
363
393
  //#endregion
394
+ //#region src/json/types.d.ts
395
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
396
+ [key: string]: JsonValue;
397
+ };
398
+ //#endregion
364
399
  //#region src/contact/types.d.ts
365
400
  type ContactHealth = 'active' | 'lukewarm' | 'cold' | 'stale' | 'unknown';
366
401
  type ContactConsentStatus = 'pending' | 'confirmed' | 'superseded' | 'unsubscribed';
@@ -447,6 +482,37 @@ type ContactCreatePayload = ContactFormData & {
447
482
  wallets?: WalletList;
448
483
  };
449
484
  //#endregion
485
+ //#region src/media/types.d.ts
486
+ type AppFileType = 'abi' | 'pdf' | 'image' | 'video' | 'json';
487
+ type AppFile = {
488
+ type: AppFileType;
489
+ original: File;
490
+ };
491
+ type MediaLibraryAttributes = {
492
+ uuid: string;
493
+ order: number;
494
+ name: string;
495
+ custom_properties: {
496
+ [key: string]: JsonValue;
497
+ };
498
+ preview_url: null | string;
499
+ original_url: null | string;
500
+ extension?: string;
501
+ size?: number;
502
+ };
503
+ type MediaMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp' | 'video/mp4' | 'video/webm' | 'video/quicktime' | 'video/x-msvideo' | 'audio/mpeg' | 'audio/mp3' | 'audio/ogg' | 'audio/wav' | 'audio/webm' | 'audio/aac' | 'audio/m4a' | 'audio/m4b' | 'audio/m4p' | 'audio/m4v' | 'application/pdf' | 'application/json';
504
+ type MediaAspectRatio = 'free' | '1:1' | '16:9' | '9:16' | '4:3' | '3:4';
505
+ type Media = {
506
+ id: string;
507
+ name: string;
508
+ mime: MediaMime;
509
+ url: string;
510
+ library: MediaLibraryAttributes;
511
+ tags?: string[];
512
+ copyright?: string | null;
513
+ aiGenerated?: boolean;
514
+ };
515
+ //#endregion
450
516
  //#region src/flow/types.d.ts
451
517
  type FlowCategory = 'none' | 'defi' | 'nft' | 'social' | 'devtools' | 'productivity' | 'trading' | 'portfolio';
452
518
  type FlowStatus = 'draft' | 'published';
@@ -1396,6 +1462,7 @@ type AgentSimple = {
1396
1462
  team?: {
1397
1463
  slug: string;
1398
1464
  } | null;
1465
+ settings?: Pick<AgentSettings, 'auto'>;
1399
1466
  };
1400
1467
  type AgentWalletMode = 'local' | 'cloud' | 'external';
1401
1468
  type AgentEngine = 'cortex' | 'openclaw';
@@ -2085,6 +2152,66 @@ type AppointmentRequest = {
2085
2152
  createdAt: string;
2086
2153
  };
2087
2154
  //#endregion
2155
+ //#region src/content/types.d.ts
2156
+ type ContentStatus = 'draft' | 'published' | 'archived';
2157
+ type ContentFieldType = 'text' | 'richText' | 'number' | 'boolean' | 'url' | 'image' | 'media' | 'list' | 'object' | 'reference';
2158
+ type ContentField = {
2159
+ key: string;
2160
+ type: ContentFieldType;
2161
+ label?: string;
2162
+ required?: boolean;
2163
+ };
2164
+ type ContentDefinition = {
2165
+ fields: ContentField[];
2166
+ };
2167
+ type ContentValue = string | number | boolean | null | ContentValue[] | {
2168
+ [key: string]: ContentValue;
2169
+ };
2170
+ type ContentEntry = {
2171
+ key: string;
2172
+ value: ContentValue;
2173
+ updatedAt: string;
2174
+ };
2175
+ type ContentVersion = {
2176
+ id: string;
2177
+ number: number;
2178
+ status: ContentStatus;
2179
+ entries: ContentEntry[];
2180
+ snapshotHash: string;
2181
+ origin: string;
2182
+ createdAt: string;
2183
+ updatedAt: string;
2184
+ publishedAt: string | null;
2185
+ };
2186
+ type Content = {
2187
+ id: string;
2188
+ name: string;
2189
+ slug: string;
2190
+ schema: string | null;
2191
+ definition: ContentDefinition;
2192
+ metadata: Record<string, ContentValue>;
2193
+ version: ContentVersion | null;
2194
+ createdAt: string;
2195
+ updatedAt: string;
2196
+ };
2197
+ type ContentPatch = {
2198
+ key: string;
2199
+ value: ContentValue;
2200
+ };
2201
+ type CreateContentInput = {
2202
+ team: string;
2203
+ name: string;
2204
+ slug: string;
2205
+ schema?: string | null;
2206
+ definition: ContentDefinition;
2207
+ metadata?: Record<string, ContentValue>;
2208
+ };
2209
+ type PatchContentInput = {
2210
+ expectedVersion: number;
2211
+ patches: ContentPatch[];
2212
+ origin?: 'api' | 'inlineEditor' | 'joai' | 'mcp';
2213
+ };
2214
+ //#endregion
2088
2215
  //#region src/commerce/helpers.d.ts
2089
2216
  type CartLine = {
2090
2217
  price: number;
@@ -3718,7 +3845,7 @@ type SegmentGroup = {
3718
3845
  type Segment = {
3719
3846
  id: string;
3720
3847
  name: string;
3721
- conditions: SegmentGroup[];
3848
+ conditions: SegmentGroup[] | SegmentCondition[];
3722
3849
  count: number;
3723
3850
  campaignsCount: number;
3724
3851
  createdAt: string;
@@ -3741,11 +3868,20 @@ type SegmentCountResult = {
3741
3868
  type CampaignChannel = 'email' | 'whatsapp' | 'sms' | 'push';
3742
3869
  type CampaignStatus = 'draft' | 'pending' | 'approved' | 'rejected' | 'sending' | 'completed' | 'failed';
3743
3870
  type CampaignCategory = 'MARKETING' | 'UTILITY' | 'AUTHENTICATION';
3871
+ type CampaignSkipReason = 'pending_consent' | 'opted_out' | 'missing_channel' | 'approval_skipped';
3872
+ type CampaignSkipReasons = Record<CampaignSkipReason, number>;
3873
+ type CampaignAudiencePreview = {
3874
+ total: number;
3875
+ sendable: number;
3876
+ willSkip: number;
3877
+ reasons: CampaignSkipReasons;
3878
+ };
3744
3879
  type CampaignApproval = {
3745
3880
  language: string | null;
3746
3881
  category: CampaignCategory | null;
3747
3882
  placeholders: string[];
3748
3883
  templateParams: Record<string, string>;
3884
+ aiParams: Record<string, string>;
3749
3885
  externalStatus: string | null;
3750
3886
  rejectionReason: string | null;
3751
3887
  };
@@ -3756,6 +3892,7 @@ type Campaign = {
3756
3892
  subject: string | null;
3757
3893
  content: string;
3758
3894
  approval: CampaignApproval;
3895
+ agent: AgentSimple | null;
3759
3896
  tags: string[];
3760
3897
  status: CampaignStatus;
3761
3898
  totalCount: number;
@@ -3763,6 +3900,7 @@ type Campaign = {
3763
3900
  sentCount: number;
3764
3901
  failedCount: number;
3765
3902
  skippedCount: number;
3903
+ skipReasons?: CampaignSkipReasons;
3766
3904
  createdAt: string;
3767
3905
  updatedAt: string;
3768
3906
  };
@@ -3774,6 +3912,8 @@ type CampaignCreatePayload = {
3774
3912
  language?: string;
3775
3913
  category?: CampaignCategory;
3776
3914
  templateParams?: Record<string, string>;
3915
+ aiParams?: Record<string, string>;
3916
+ agentId?: string;
3777
3917
  tags?: string[];
3778
3918
  contactIds?: string[];
3779
3919
  segmentId?: string;
@@ -3785,6 +3925,16 @@ type CampaignUpdatePayload = {
3785
3925
  language?: string;
3786
3926
  category?: CampaignCategory;
3787
3927
  templateParams?: Record<string, string>;
3928
+ aiParams?: Record<string, string>;
3929
+ agentId?: string;
3930
+ };
3931
+ type CampaignAudiencePreviewPayload = {
3932
+ campaignId: string;
3933
+ } | {
3934
+ channel: CampaignChannel;
3935
+ tags?: string[];
3936
+ contactIds?: string[];
3937
+ segmentId?: string;
3788
3938
  };
3789
3939
  type CampaignStats = {
3790
3940
  totalCampaigns: number;
@@ -4106,4 +4256,4 @@ type CliSessionStatus = {
4106
4256
  meta: CliSessionMeta | null;
4107
4257
  };
4108
4258
  //#endregion
4109
- export { Achievement, Address, AddressCreatePayload, AddressInput, AddressSnapshot, type AddressType, AddressTypes, AddressUpdatePayload, Affiliate, AffiliateStatus, AffiliateTier, AffiliateTierName, Agent, AgentActionHistoryEntry, AgentCharacter, AgentDelegatable, AgentEngine, AgentExecuteHandler, AgentExecuteOptions, AgentGender, AgentMessageMeta, AgentMessageOptions, AgentPrivate, AgentSettings, AgentSetupTarget, AgentSimple, AgentToolingAccess, AgentWalletMode, AggregatedRoute, AiCostEntry, AiCostsResponse, AiCostsSummary, Alert, ApiToken, AppAccessRule, AppEnv, AppFile, AppFileType, AppIngestion, AppSetupTarget, AppendKvEntryResult, AppointmentAvailability, AppointmentAvailabilityService, AppointmentAvailabilitySlot, AppointmentBooking, AppointmentBookingContext, AppointmentPolicy, AppointmentPolicySync, AppointmentRequest, AppointmentSlot, AuthUser, BillingManageAccess, Blueprint, BlueprintOnboardingStep, BlueprintRedirect, BlueprintSettings, BlueprintShortcut, BlueprintTask, BlueprintTeam, BoardSummaryViewable, BookmarkEntry, BrandBackend, BrandIntegration, BrandIntegrationAction, BrandIntegrationProvider, BrandSearchHit, BrandSiteConfig, BrandSourceConfig, Budget, ByokProviderConfig, ByokProviderName, ByokProviders, CalendarProvider, CalendarStatus, Campaign, CampaignApproval, CampaignCategory, CampaignChannel, CampaignCreatePayload, CampaignStats, CampaignStatus, CampaignUpdatePayload, Card, Cart, CartItem, CartLine, Challenge, Challenges, ChangelogEntry, Character, ChatClientAction, ChatClientThought, ChatStreamData, ChatStreamEventType, CheckoutSnapshot, CheckoutSnapshotRequest, CliSessionMeta, CliSessionStatus, CommissionAgreement, Configuration, Contact, ContactActivity, ContactActivityAuthor, ContactActivityType, ContactConsent, ContactConsentStatus, ContactCreatePayload, ContactFormData, ContactHealth, ContactViewable, Content, ContentDefinition, ContentEntry, ContentField, ContentFieldType, ContentPatch, ContentStatus, ContentValue, ContentVersion, Contract, ContractCategoryDisplayNames, ContractCategoryName, ContractCodeMetadata, ContractEntity, ContractOnNetwork, ContractVersion, ContractsAddressConfig, CortexExecuteOptions, Coupon, CouponCondition, CouponRestrictedItem, CouponRestrictedItemType, CreateContentInput, CreateHookPayload, CreateInboundHookPayload, CreateInternalHookPayload, CreateKvFieldPayload, CreateWarpLinkedHookPayload, CreateWebHookPayload, DefaultCodeMetadata, DefaultInviteTeamRole, DemoFlow, DemoMessage, Desk, DeskItem, DeskItemRole, Document, EarnResponse, Earning, Element, ElementSpec, ElementType, ElementVariation, EmailProvider, EmbedStatus, EncryptionStatus, Entity, EntityDirectExecuteRequest, EntityProposable, EntitySignable, EntityTemplate, Experience, FileInfo, FileMetadata, Flow, FlowCategory, FlowInputMapping, FlowStatus, FlowStep, Fulfillment, FulfillmentLocation, type FulfillmentMethod, FulfillmentMethods, type FulfillmentStatus, FulfillmentStatuses, GamificationData, GamificationEventType, Goal, GoalCreatePayload, GoalPriority, GoalProgressViewable, GoalStatus, GuestBuyer, HintOptions, HintPosition, Hook, HookSample, HookTrigger, HookTriggerCondition, HookTriggerInput, HttpService, IAppResponse, IHttpService, IRequestOptions, IngestionSourceType, IngestionStatus, Inquiry, InquiryStatus, InquiryType, Integration, IntegrationConnectionDetails, IntegrationDetails, IntegrationMeta, IntegrationType, Intent, InviteableTeamRoles, Item, ItemCreatePayload, ItemExecutionStatus, ItemPriority, ItemStatus, ItemUpdatePayload, ItemViewable, JoaiUrls, JsonValue, KvEntry, KvEntryPayload, KvField, KvFieldWithEntries, KvValue, Kyc, KycStatus, Link, LinkCreatePayload, LinkScanHistory, LinkStats, LinkUpdatePayload, LinkVariation, LinkVariationBatchCreatePayload, LinkVariationCreatePayload, LocalAgentWallet, LoyaltyAccount, LoyaltyMember, LoyaltyNextTier, LoyaltyProgram, LoyaltyPromotion, LoyaltyReward, LoyaltyStatus, LoyaltyTier, LoyaltyTierInfo, LoyaltyTransaction, McpToolCall, McpToolCallBroadcast, McpToolCallStatus, Media, MediaAspectRatio, MediaAttributes, MediaItems, MediaLibraryAttributes, MediaMime, Meeting, MeetingConferenceProvider, MeetingFeature, MeetingJoinInfo, MeetingJoinTeam, MeetingParticipant, MeetingSessionState, MeetingSpeakerAssignment, MeetingStatus, MeetingSummary, MeetingTranscriptEntry, MeetingUsage, Memory, Message, MessageId, MessageRole, Milestone, MilestoneType, Mission, MissionBudget, MissionCreatePayload, MissionPlan, MissionPriority, MissionSchedule, MissionStatus, MissionViewable, MollieTerminalPaymentResult, MultimodalContent, MultimodalFile, NATIVE_AUTH_TOKEN_PARAM, NativeApp, NativeApps, Notification, NotificationAction, NotificationAgent, NotificationChannel, NotificationSetting, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, OfficeAgent, OfficeEntity, OfficeEntityKind, OfficeLiveOverrides, OfficeMember, OfficeSnapshot, OfficeStatus, OfficeStatusFilter, OfficeTypeFilter, OgImageColors, OgImageParams, OgImageType, Order, OrderConfigurationItem, OrderContext, OrderItem, OrderSource, OrderStatus, OrderType, PaginatedResponse, Pass, PatchContentInput, PaymentAccount, PaymentAccountOnboarding, PaymentProvider, PayoutEntry, PeriodTypeLabels, PeriodTypeOptions, PermissionConfigType, PermissionPresetName, PermissionPresetNames, PersonaQuestionable, Plan, PlanBenefit, PlanExtra, PlanFeature, PlanInterval, PolicyMethod, PolicySetting, PricingModel, Product, ProductDiscount, ProductMeta, ProductPieces, ProductRating, ProductRelation, ProductRelationType, ProductVariation, ProductVariationMeta, ProductVariationType, ProgramSettings, Project, ProjectAspectRatio, ProjectAssembly, ProjectCaptionStyle, ProjectClipCandidate, ProjectClips, ProjectExport, ProjectExportAsset, ProjectExportResponse, ProjectImages, ProjectInputAssistIntent, ProjectInputAssistResponse, ProjectMutation, ProjectOutputPreset, ProjectOutputType, ProjectPlan, ProjectRender, ProjectRenderMode, ProjectSelectedClip, ProjectShot, ProjectSoundtrack, ProjectSourceMedia, ProjectStatus, ProjectStudioHistoryEntry, ProjectStudioQuestion, ProjectStudioResponse, ProjectStudioStage, ProjectStudioState, ProjectStudioSummary, ProjectStyleDirection, ProjectTranscript, ProjectTranscriptSegment, Proposal, ProposalAction, ProposalActionPayment, ProposalActionPaymentSerializable, ProposalActionSerializable, ProposalPollOption, ProposalStatus, PublicFormResults, PurchaseOptions, PurchaseResult, RampProvider, RampProviderInfo, Reactions, RecentExperience, RedeemResponse, Reminder, Return, type ReturnStatus, ReturnStatuses, ReturnUpdateStatus, ReturnUpdateStatuses, Room, RoomId, RoomKind, ScInfo, SchedulePreset, SecretAuthorizable, SecretSettable, Segment, SegmentCondition, SegmentConditionType, SegmentCountPayload, SegmentCountResult, SegmentCreatePayload, SegmentGroup, SendableActivityUpdate, SendableAgentAction, SendableAgentMessage, SendableAgentThought, SendableMedia, SendableUserMessage, Service, SetKvEntryResult, ShippingRate, ShippingZone, Shortcut, Site, SiteAgent, SiteBrand, SiteRoute, SiteTeam, Skill, SkillMediaBindingRole, SkillMediaBindingRoleValue, SkillScope, SkillScopeValue, SkillType, SkillTypeValue, SocialAuthProvider, SocialBot, SocialPlatform, StampResponse, StoreAgent, StoreCheckoutItem, StoreData, StoreEntityType, StoreInfo, StoreItem, StoreListing, StorePriceTier, StorePricing, StorePurchasable, StorePurchaseResult, Streak, Subscription, SubscriptionDelivery, SubscriptionInterval, SubscriptionPlan, SubscriptionStatus, Swarm, Tag, TagType, Task, Team, TeamAccessCatalog, TeamAccessConfig, TeamBrand, TeamCategory, TeamEarning, TeamEarningsBalance, TeamFeature, TeamFeatureAccess, TeamFeatureArea, TeamFeatureUsage, TeamManageAccess, TeamMember, TeamMeta, TeamPayout, TeamPayoutAddress, TeamPlace, TeamPrivate, TeamSettings, TeamUsage, TeamViewAccess, TerminalConnectionToken, TerminalPaymentIntent, Tier, TierFeature, TierName, ToggleKvFieldResult, TranscriptEntry, TranscriptionCorrection, TranscriptionResponse, TranslatableValue, UNIFIED_MCP_SERVER_NAME, Update, UpdateCreatePayload, UpdateRelation, UpdateStats, UpdateStatus, UpdateType, UpdateUpdatePayload, Upgrade, UpgradeSourceType, UpgradeStatus, User, UserInterest, UserMode, type UserPermission, UserPermissions, UserPrivate, type UserRole, UserRoles, UserSettings, UserSocialAccount, UserStats, VolumePrice, Wallet, WalletList, WarpApprovable, WarpBackend, WarpBackendStatus, WarpBatchItem, WarpBatchable, WarpCloudExecutable, WarpCreateable, WarpExecutable, WarpExecutionBackend, WarpExtras, WarpExtrasFaq, WarpInputable, WarpScreenshotVariant, WarpSearchHit, WarpSelectable, WarpSelectableDetails, WarpSuggestion, WarpTestable, WarpViewable, WebHookTriggerEvent, WorkspaceCloudFile, WorkspaceContext, WorkspaceInfo, WorkspaceSettings, XIntegrationStatus, abbreviateNumber, addressTypeValues, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildMcpServerName, cartLineTotal, createCursorMcpInstallLink, defaultInviteTeamRole, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getFormsBaseUrl, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, inviteableTeamRoles, isCompleteAddressInput, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, ogImageUrl, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, withRetry };
4259
+ export { Achievement, Address, AddressCreatePayload, AddressInput, AddressSnapshot, type AddressType, AddressTypes, AddressUpdatePayload, Affiliate, AffiliateStatus, AffiliateTier, AffiliateTierName, Agent, AgentActionHistoryEntry, AgentCharacter, AgentDelegatable, AgentEngine, AgentExecuteHandler, AgentExecuteOptions, AgentGender, AgentMessageMeta, AgentMessageOptions, AgentPrivate, AgentSettings, AgentSetupTarget, AgentSimple, AgentToolingAccess, AgentWalletMode, AggregatedRoute, AiCostEntry, AiCostsResponse, AiCostsSummary, Alert, ApiToken, AppAccessRule, AppEnv, AppFile, AppFileType, AppIngestion, AppSetupTarget, AppendKvEntryResult, AppointmentAvailability, AppointmentAvailabilityService, AppointmentAvailabilitySlot, AppointmentBooking, AppointmentBookingContext, AppointmentPolicy, AppointmentPolicySync, AppointmentRequest, AppointmentSlot, AuthUser, BillingManageAccess, Blueprint, BlueprintOnboardingStep, BlueprintRedirect, BlueprintSettings, BlueprintShortcut, BlueprintTask, BlueprintTeam, BoardSummaryViewable, BookmarkEntry, BrandBackend, BrandIntegration, BrandIntegrationAction, BrandIntegrationProvider, BrandSearchHit, BrandSiteConfig, BrandSourceConfig, Budget, ByokProviderConfig, ByokProviderName, ByokProviders, CalendarProvider, CalendarStatus, Campaign, CampaignApproval, CampaignAudiencePreview, CampaignAudiencePreviewPayload, CampaignCategory, CampaignChannel, CampaignCreatePayload, CampaignSkipReason, CampaignSkipReasons, CampaignStats, CampaignStatus, CampaignUpdatePayload, Card, Cart, CartItem, CartLine, Challenge, Challenges, ChangelogEntry, Character, ChatClientAction, ChatClientThought, ChatStreamData, ChatStreamEventType, CheckoutSnapshot, CheckoutSnapshotRequest, CliSessionMeta, CliSessionStatus, CommissionAgreement, Configuration, Contact, ContactActivity, ContactActivityAuthor, ContactActivityType, ContactConsent, ContactConsentStatus, ContactCreatePayload, ContactFormData, ContactHealth, ContactViewable, Content, ContentDefinition, ContentEntry, ContentField, ContentFieldType, ContentPatch, ContentStatus, ContentValue, ContentVersion, Contract, ContractCategoryDisplayNames, ContractCategoryName, ContractCodeMetadata, ContractEntity, ContractOnNetwork, ContractVersion, ContractsAddressConfig, CortexExecuteOptions, Coupon, CouponCondition, CouponRestrictedItem, CouponRestrictedItemType, CreateContentInput, CreateHookPayload, CreateInboundHookPayload, CreateInternalHookPayload, CreateKvFieldPayload, CreateWarpLinkedHookPayload, CreateWebHookPayload, DefaultCodeMetadata, DefaultInviteTeamRole, DemoFlow, DemoMessage, Desk, DeskItem, DeskItemRole, Document, EarnResponse, Earning, Element, ElementSpec, ElementType, ElementVariation, EmailProvider, EmbedStatus, EncryptionStatus, Entity, EntityDirectExecuteRequest, EntityProposable, EntitySignable, EntityTemplate, Experience, FileInfo, FileMetadata, Flow, FlowCategory, FlowInputMapping, FlowStatus, FlowStep, Fulfillment, FulfillmentLocation, type FulfillmentMethod, FulfillmentMethods, type FulfillmentStatus, FulfillmentStatuses, GamificationData, GamificationEventType, Goal, GoalCreatePayload, GoalPriority, GoalProgressViewable, GoalStatus, GuestBuyer, HintOptions, HintPosition, Hook, HookSample, HookTrigger, HookTriggerCondition, HookTriggerInput, HttpService, IAppResponse, IHttpService, IRequestOptions, IngestionSourceType, IngestionStatus, Inquiry, InquiryStatus, InquiryType, Integration, IntegrationConnectionDetails, IntegrationDetails, IntegrationMeta, IntegrationType, Intent, InviteableTeamRoles, Item, ItemCreatePayload, ItemExecutionStatus, ItemPriority, ItemStatus, ItemUpdatePayload, ItemViewable, JoaiUrls, JsonValue, KvEntry, KvEntryPayload, KvField, KvFieldWithEntries, KvValue, Kyc, KycStatus, Link, LinkCreatePayload, LinkScanHistory, LinkStats, LinkUpdatePayload, LinkVariation, LinkVariationBatchCreatePayload, LinkVariationCreatePayload, LocalAgentWallet, LoyaltyAccount, LoyaltyMember, LoyaltyNextTier, LoyaltyProgram, LoyaltyPromotion, LoyaltyReward, LoyaltyStatus, LoyaltyTier, LoyaltyTierInfo, LoyaltyTransaction, McpToolCall, McpToolCallBroadcast, McpToolCallStatus, Media, MediaAspectRatio, MediaAttributes, MediaItems, MediaLibraryAttributes, MediaMime, Meeting, MeetingConferenceProvider, MeetingFeature, MeetingJoinInfo, MeetingJoinTeam, MeetingParticipant, MeetingSessionState, MeetingSpeakerAssignment, MeetingStatus, MeetingSummary, MeetingTranscriptEntry, MeetingUsage, Memory, Message, MessageId, MessageRole, Milestone, MilestoneType, Mission, MissionBudget, MissionCreatePayload, MissionPlan, MissionPriority, MissionSchedule, MissionStatus, MissionViewable, MollieTerminalPaymentResult, MultimodalContent, MultimodalFile, NATIVE_AUTH_TOKEN_PARAM, NativeApp, NativeApps, Notification, NotificationAction, NotificationAgent, NotificationChannel, NotificationSetting, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, OfficeAgent, OfficeEntity, OfficeEntityKind, OfficeLiveOverrides, OfficeMember, OfficeSnapshot, OfficeStatus, OfficeStatusFilter, OfficeTypeFilter, OgImageColors, OgImageParams, OgImageType, Order, OrderConfigurationItem, OrderContext, OrderItem, OrderSource, OrderStatus, OrderType, PaginatedResponse, Pass, PatchContentInput, PaymentAccount, PaymentAccountOnboarding, PaymentProvider, PayoutEntry, PeriodTypeLabels, PeriodTypeOptions, PermissionConfigType, PermissionPresetName, PermissionPresetNames, PersonaQuestionable, Plan, PlanBenefit, PlanExtra, PlanFeature, PlanInterval, PolicyMethod, PolicySetting, PricingModel, Product, ProductDiscount, ProductMeta, ProductPieces, ProductRating, ProductRelation, ProductRelationType, ProductVariation, ProductVariationMeta, ProductVariationType, ProgramSettings, Project, ProjectAspectRatio, ProjectAssembly, ProjectCaptionStyle, ProjectClipCandidate, ProjectClips, ProjectExport, ProjectExportAsset, ProjectExportResponse, ProjectImages, ProjectInputAssistIntent, ProjectInputAssistResponse, ProjectMutation, ProjectOutputPreset, ProjectOutputType, ProjectPlan, ProjectRender, ProjectRenderMode, ProjectSelectedClip, ProjectShot, ProjectSoundtrack, ProjectSourceMedia, ProjectStatus, ProjectStudioHistoryEntry, ProjectStudioQuestion, ProjectStudioResponse, ProjectStudioStage, ProjectStudioState, ProjectStudioSummary, ProjectStyleDirection, ProjectTranscript, ProjectTranscriptSegment, Proposal, ProposalAction, ProposalActionPayment, ProposalActionPaymentSerializable, ProposalActionSerializable, ProposalPollOption, ProposalStatus, PublicFormResults, PurchaseOptions, PurchaseResult, RampProvider, RampProviderInfo, Reactions, RecentExperience, RedeemResponse, Reminder, Return, type ReturnStatus, ReturnStatuses, ReturnUpdateStatus, ReturnUpdateStatuses, Room, RoomId, RoomKind, ScInfo, SchedulePreset, SecretAuthorizable, SecretSettable, Segment, SegmentCondition, SegmentConditionType, SegmentCountPayload, SegmentCountResult, SegmentCreatePayload, SegmentGroup, SendableActivityUpdate, SendableAgentAction, SendableAgentMessage, SendableAgentThought, SendableMedia, SendableUserMessage, Service, SetKvEntryResult, ShippingRate, ShippingZone, Shortcut, Site, SiteAgent, SiteBrand, SiteRoute, SiteTeam, Skill, SkillMediaBindingRole, SkillMediaBindingRoleValue, SkillScope, SkillScopeValue, SkillType, SkillTypeValue, SocialAuthProvider, SocialBot, SocialPlatform, StampResponse, StoreAgent, StoreCheckoutItem, StoreData, StoreEntityType, StoreInfo, StoreItem, StoreListing, StorePriceTier, StorePricing, StorePurchasable, StorePurchaseResult, Streak, Subscription, SubscriptionDelivery, SubscriptionInterval, SubscriptionPlan, SubscriptionStatus, Swarm, Tag, TagType, Task, Team, TeamAccessCatalog, TeamAccessConfig, TeamBrand, TeamCategory, TeamEarning, TeamEarningsBalance, TeamFeature, TeamFeatureAccess, TeamFeatureArea, TeamFeatureUsage, TeamManageAccess, TeamMember, TeamMeta, TeamPayout, TeamPayoutAddress, TeamPlace, TeamPrivate, TeamSettings, TeamUsage, TeamViewAccess, TerminalConnectionToken, TerminalPaymentIntent, Tier, TierFeature, TierName, ToggleKvFieldResult, TranscriptEntry, TranscriptionCorrection, TranscriptionResponse, TranslatableValue, UNIFIED_MCP_SERVER_NAME, Update, UpdateCreatePayload, UpdateRelation, UpdateStats, UpdateStatus, UpdateType, UpdateUpdatePayload, Upgrade, UpgradeSourceType, UpgradeStatus, User, UserInterest, UserMode, type UserPermission, UserPermissions, UserPrivate, type UserRole, UserRoles, UserSettings, UserSocialAccount, UserStats, VolumePrice, Wallet, WalletList, WarpApprovable, WarpBackend, WarpBackendStatus, WarpBatchItem, WarpBatchable, WarpCloudExecutable, WarpCreateable, WarpExecutable, WarpExecutionBackend, WarpExtras, WarpExtrasFaq, WarpInputable, WarpScreenshotVariant, WarpSearchHit, WarpSelectable, WarpSelectableDetails, WarpSuggestion, WarpTestable, WarpViewable, WebHookTriggerEvent, WorkspaceCloudFile, WorkspaceContext, WorkspaceInfo, WorkspaceSettings, XIntegrationStatus, abbreviateNumber, addressTypeValues, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildMcpServerName, cartLineTotal, createCursorMcpInstallLink, defaultInviteTeamRole, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getFormsBaseUrl, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, inviteableTeamRoles, isCompleteAddressInput, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, ogImageUrl, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, withRetry };
@@ -1,4 +1,4 @@
1
- import { b as IHttpService, c as ContentValue, d as PatchContentInput, l as ContentVersion, m as Media, t as Content } from "../types-BbqlPvhU.mjs";
1
+ 'use client';
2
2
  import * as _$react from "react";
3
3
  import { ReactNode } from "react";
4
4
 
@@ -72,6 +72,37 @@ declare function EmbedChatInput({
72
72
  renderSendButton
73
73
  }: EmbedChatInputProps): _$react.JSX.Element;
74
74
  //#endregion
75
+ //#region src/http/types.d.ts
76
+ interface IHttpService {
77
+ readonly baseUrl: string;
78
+ readonly authToken: string | null;
79
+ onNetworkError: (error: Error) => void;
80
+ onUnauthorized: (response: IAppResponse<any>) => void;
81
+ onSuccessfulResponse: (response: IAppResponse<any>) => void;
82
+ onMaintenanceMode: (response: IAppResponse<any>) => void;
83
+ get: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
84
+ post: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
85
+ put: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
86
+ patch: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
87
+ delete: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
88
+ }
89
+ interface IAppResponse<T> {
90
+ data: T;
91
+ meta?: any;
92
+ body: any;
93
+ errors: any;
94
+ ok: boolean;
95
+ paymentRequired: boolean;
96
+ noContent: boolean;
97
+ original: Response;
98
+ }
99
+ interface IRequestOptions {
100
+ isJson?: boolean;
101
+ headers?: {
102
+ [name: string]: string;
103
+ };
104
+ }
105
+ //#endregion
75
106
  //#region src/react/use-embed-chat.d.ts
76
107
  type Options = {
77
108
  agentUuid: string | null;
@@ -101,6 +132,88 @@ declare function useEmbedChat({
101
132
  connectionError: boolean;
102
133
  };
103
134
  //#endregion
135
+ //#region src/content/types.d.ts
136
+ type ContentStatus = 'draft' | 'published' | 'archived';
137
+ type ContentFieldType = 'text' | 'richText' | 'number' | 'boolean' | 'url' | 'image' | 'media' | 'list' | 'object' | 'reference';
138
+ type ContentField = {
139
+ key: string;
140
+ type: ContentFieldType;
141
+ label?: string;
142
+ required?: boolean;
143
+ };
144
+ type ContentDefinition = {
145
+ fields: ContentField[];
146
+ };
147
+ type ContentValue = string | number | boolean | null | ContentValue[] | {
148
+ [key: string]: ContentValue;
149
+ };
150
+ type ContentEntry = {
151
+ key: string;
152
+ value: ContentValue;
153
+ updatedAt: string;
154
+ };
155
+ type ContentVersion = {
156
+ id: string;
157
+ number: number;
158
+ status: ContentStatus;
159
+ entries: ContentEntry[];
160
+ snapshotHash: string;
161
+ origin: string;
162
+ createdAt: string;
163
+ updatedAt: string;
164
+ publishedAt: string | null;
165
+ };
166
+ type Content = {
167
+ id: string;
168
+ name: string;
169
+ slug: string;
170
+ schema: string | null;
171
+ definition: ContentDefinition;
172
+ metadata: Record<string, ContentValue>;
173
+ version: ContentVersion | null;
174
+ createdAt: string;
175
+ updatedAt: string;
176
+ };
177
+ type ContentPatch = {
178
+ key: string;
179
+ value: ContentValue;
180
+ };
181
+ type PatchContentInput = {
182
+ expectedVersion: number;
183
+ patches: ContentPatch[];
184
+ origin?: 'api' | 'inlineEditor' | 'joai' | 'mcp';
185
+ };
186
+ //#endregion
187
+ //#region src/json/types.d.ts
188
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
189
+ [key: string]: JsonValue;
190
+ };
191
+ //#endregion
192
+ //#region src/media/types.d.ts
193
+ type MediaLibraryAttributes = {
194
+ uuid: string;
195
+ order: number;
196
+ name: string;
197
+ custom_properties: {
198
+ [key: string]: JsonValue;
199
+ };
200
+ preview_url: null | string;
201
+ original_url: null | string;
202
+ extension?: string;
203
+ size?: number;
204
+ };
205
+ type MediaMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp' | 'video/mp4' | 'video/webm' | 'video/quicktime' | 'video/x-msvideo' | 'audio/mpeg' | 'audio/mp3' | 'audio/ogg' | 'audio/wav' | 'audio/webm' | 'audio/aac' | 'audio/m4a' | 'audio/m4b' | 'audio/m4p' | 'audio/m4v' | 'application/pdf' | 'application/json';
206
+ type Media = {
207
+ id: string;
208
+ name: string;
209
+ mime: MediaMime;
210
+ url: string;
211
+ library: MediaLibraryAttributes;
212
+ tags?: string[];
213
+ copyright?: string | null;
214
+ aiGenerated?: boolean;
215
+ };
216
+ //#endregion
104
217
  //#region src/react/content/types.d.ts
105
218
  type ContentResource = {
106
219
  get: (contentId: string) => Promise<{
@@ -214,6 +327,7 @@ declare function EditableContent({
214
327
  placeholder,
215
328
  multiline
216
329
  }: EditableContentProp): _$react.JSX.Element;
330
+ declare function useContentValue<T extends ContentValue = ContentValue>(key: string): T | undefined;
217
331
  //#endregion
218
332
  //#region src/react/content/editable-image.d.ts
219
333
  declare function EditableImage({
@@ -243,4 +357,4 @@ declare function ContentEditor({
243
357
  ...provider
244
358
  }: Prop): _$react.JSX.Element;
245
359
  //#endregion
246
- export { ContentClient, ContentContextValue, ContentEditor, ContentProvider, ContentProviderProp, ContentResource, ContentToolbar, ContentToolbarProp, EditableContent, EditableContentProp, EditableImage, EditableImageProp, EmbedChatInput, EmbedChatItem, EmbedChatList, StreamDataHandler, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useEmbedChat };
360
+ export { ContentClient, ContentContextValue, ContentEditor, ContentProvider, ContentProviderProp, ContentResource, ContentToolbar, ContentToolbarProp, EditableContent, EditableContentProp, EditableImage, EditableImageProp, EmbedChatInput, EmbedChatItem, EmbedChatList, StreamDataHandler, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useContentValue, useEmbedChat };
@@ -1,3 +1,4 @@
1
+ 'use client';
1
2
  import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
2
3
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
4
  //#region src/react/guest.ts
@@ -296,6 +297,29 @@ function useContent() {
296
297
  return context;
297
298
  }
298
299
  //#endregion
300
+ //#region src/react/content/content-cache.ts
301
+ const contentCache = /* @__PURE__ */ new Map();
302
+ const pendingLoads = /* @__PURE__ */ new Map();
303
+ function cacheContent(content) {
304
+ contentCache.set(`id:${content.id}`, content);
305
+ contentCache.set(`slug:${content.slug}`, content);
306
+ }
307
+ async function loadContent(client, contentId, publicSlug) {
308
+ const target = contentId ?? publicSlug;
309
+ if (!target) return null;
310
+ const key = contentId ? `id:${contentId}` : `slug:${publicSlug}`;
311
+ const cached = contentCache.get(key);
312
+ if (cached) return cached;
313
+ const pending = pendingLoads.get(key);
314
+ if (pending) return pending;
315
+ const request = (contentId ? client.content.get(target) : client.content.getPublic(target)).then((result) => result.ok && result.data ? result.data : null).then((content) => {
316
+ if (content) cacheContent(content);
317
+ return content;
318
+ }).finally(() => pendingLoads.delete(key));
319
+ pendingLoads.set(key, request);
320
+ return request;
321
+ }
322
+ //#endregion
299
323
  //#region src/react/content/state.ts
300
324
  function contentValues(content) {
301
325
  return Object.fromEntries(content?.version?.entries.map((entry) => [entry.key, entry.value]) ?? []);
@@ -317,7 +341,8 @@ function ContentProvider({ children, client, contentId, publicSlug, initialConte
317
341
  const [isEditing, setEditing] = useState(false);
318
342
  const [error, setError] = useState(null);
319
343
  useEffect(() => {
320
- if (initialContent) {
344
+ if (initialContent && !contentId) {
345
+ cacheContent(initialContent);
321
346
  setContent(initialContent);
322
347
  setValues(contentValues(initialContent));
323
348
  setIsLoading(false);
@@ -327,11 +352,11 @@ function ContentProvider({ children, client, contentId, publicSlug, initialConte
327
352
  if (!contentId && !publicSlug) return;
328
353
  setIsLoading(true);
329
354
  setError(null);
330
- const result = contentId ? await client.content.get(contentId) : await client.content.getPublic(publicSlug);
331
- if (!result.ok || !result.data) setError("Content could not be loaded.");
355
+ const nextContent = await loadContent(client, contentId, publicSlug);
356
+ if (!nextContent) setError("Content could not be loaded.");
332
357
  else {
333
- setContent(result.data);
334
- setValues(contentValues(result.data));
358
+ setContent(nextContent);
359
+ setValues(contentValues(nextContent));
335
360
  }
336
361
  setIsLoading(false);
337
362
  };
@@ -370,6 +395,7 @@ function ContentProvider({ children, client, contentId, publicSlug, initialConte
370
395
  version: result.data,
371
396
  updatedAt: result.data.updatedAt
372
397
  };
398
+ cacheContent(nextContent);
373
399
  setContent(nextContent);
374
400
  setValues(contentValues(nextContent));
375
401
  return true;
@@ -396,6 +422,7 @@ function ContentProvider({ children, client, contentId, publicSlug, initialConte
396
422
  version: result.data,
397
423
  updatedAt: result.data.updatedAt
398
424
  };
425
+ cacheContent(nextContent);
399
426
  setContent(nextContent);
400
427
  setValues(contentValues(nextContent));
401
428
  setEditing(false);
@@ -470,6 +497,9 @@ function EditableContent({ field, as: Tag = "span", className, placeholder = "Ad
470
497
  onChange: (event) => setValue(field, event.target.value)
471
498
  });
472
499
  }
500
+ function useContentValue(key) {
501
+ return useContent().values[key];
502
+ }
473
503
  //#endregion
474
504
  //#region src/react/content/editable-image.tsx
475
505
  function EditableImage({ field, alt = "", className, inputClassName, placeholder = "Image URL", onSelect }) {
@@ -514,44 +544,27 @@ function EditableImage({ field, alt = "", className, inputClassName, placeholder
514
544
  alt
515
545
  }),
516
546
  onSelect && /* @__PURE__ */ jsx("button", {
547
+ className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
517
548
  type: "button",
518
549
  onClick: onSelect,
519
550
  children: "Choose image"
520
551
  }),
521
552
  !onSelect && media && teamSlug && /* @__PURE__ */ jsx("button", {
553
+ className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
522
554
  type: "button",
523
- onClick: () => setPickerOpen((open) => !open),
555
+ onClick: () => setPickerOpen(true),
524
556
  children: "Choose image"
525
557
  }),
526
- isPickerOpen && /* @__PURE__ */ jsxs("div", {
527
- role: "dialog",
528
- "aria-label": "Image picker",
529
- children: [
530
- /* @__PURE__ */ jsxs("label", { children: ["Bild hochladen", /* @__PURE__ */ jsx("input", {
531
- type: "file",
532
- accept: "image/*",
533
- disabled: isUploading,
534
- onChange: (event) => {
535
- const file = event.target.files?.[0];
536
- if (file) upload(file);
537
- }
538
- })] }),
539
- isUploading && /* @__PURE__ */ jsx("span", { children: "Uploading…" }),
540
- /* @__PURE__ */ jsx("div", {
541
- role: "list",
542
- children: images.map((image) => /* @__PURE__ */ jsx("button", {
543
- type: "button",
544
- onClick: () => {
545
- setValue(field, image.url);
546
- setPickerOpen(false);
547
- },
548
- children: /* @__PURE__ */ jsx("img", {
549
- src: image.url,
550
- alt: image.name
551
- })
552
- }, image.id))
553
- })
554
- ]
558
+ /* @__PURE__ */ jsx(ImagePicker, {
559
+ open: isPickerOpen,
560
+ onClose: () => setPickerOpen(false),
561
+ images,
562
+ isUploading,
563
+ onUpload: upload,
564
+ onSelect: (url) => {
565
+ setValue(field, url);
566
+ setPickerOpen(false);
567
+ }
555
568
  }),
556
569
  /* @__PURE__ */ jsx("input", {
557
570
  "aria-label": field,
@@ -564,6 +577,68 @@ function EditableImage({ field, alt = "", className, inputClassName, placeholder
564
577
  ]
565
578
  });
566
579
  }
580
+ function ImagePicker({ open, onClose, images, isUploading, onUpload, onSelect }) {
581
+ if (!open) return null;
582
+ return /* @__PURE__ */ jsx("div", {
583
+ className: "fixed inset-0 z-[1100] grid place-items-center bg-slate-950/45 p-4",
584
+ role: "dialog",
585
+ "aria-modal": "true",
586
+ "aria-label": "Image library",
587
+ children: /* @__PURE__ */ jsxs("div", {
588
+ className: "max-h-[min(44rem,calc(100vh-2rem))] w-full max-w-2xl overflow-y-auto rounded-xl bg-white p-5 shadow-2xl",
589
+ children: [
590
+ /* @__PURE__ */ jsxs("div", {
591
+ className: "flex items-start justify-between gap-4",
592
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
593
+ className: "text-lg font-semibold text-slate-950",
594
+ children: "Image library"
595
+ }), /* @__PURE__ */ jsx("p", {
596
+ className: "mt-1 text-sm text-slate-500",
597
+ children: "Choose an existing image or upload a new one."
598
+ })] }), /* @__PURE__ */ jsx("button", {
599
+ className: "rounded-lg px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-100",
600
+ type: "button",
601
+ onClick: onClose,
602
+ children: "Close"
603
+ })]
604
+ }),
605
+ /* @__PURE__ */ jsxs("label", {
606
+ className: "mt-5 flex cursor-pointer items-center justify-center rounded-lg border border-dashed border-slate-300 px-4 py-6 text-sm font-medium text-slate-600 transition hover:border-blue-400 hover:text-blue-600",
607
+ children: [/* @__PURE__ */ jsx("input", {
608
+ className: "sr-only",
609
+ type: "file",
610
+ accept: "image/*",
611
+ onChange: (event) => {
612
+ const file = event.target.files?.[0];
613
+ if (file) onUpload(file);
614
+ }
615
+ }), "Upload image"]
616
+ }),
617
+ isUploading && /* @__PURE__ */ jsx("span", {
618
+ className: "mt-3 block text-sm text-slate-500",
619
+ children: "Uploading…"
620
+ }),
621
+ /* @__PURE__ */ jsx("div", {
622
+ className: "mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3",
623
+ role: "list",
624
+ children: images.map((image) => /* @__PURE__ */ jsxs("button", {
625
+ className: "overflow-hidden rounded-lg border border-slate-200 text-left transition-opacity hover:opacity-75",
626
+ type: "button",
627
+ onClick: () => onSelect(image.url),
628
+ children: [/* @__PURE__ */ jsx("img", {
629
+ className: "aspect-square w-full object-cover",
630
+ src: image.url,
631
+ alt: image.name
632
+ }), /* @__PURE__ */ jsx("span", {
633
+ className: "block truncate p-2 text-xs text-slate-700",
634
+ children: image.name
635
+ })]
636
+ }, image.id))
637
+ })
638
+ ]
639
+ })
640
+ });
641
+ }
567
642
  //#endregion
568
643
  //#region src/react/content/toolbar.tsx
569
644
  function ContentToolbar({ className, labels = {}, confirmPublish }) {
@@ -578,28 +653,32 @@ function ContentToolbar({ className, labels = {}, confirmPublish }) {
578
653
  await publish();
579
654
  };
580
655
  return /* @__PURE__ */ jsxs("div", {
581
- className,
656
+ className: `flex flex-wrap items-center gap-2 ${className ?? ""}`,
582
657
  role: "toolbar",
583
658
  "aria-label": "Content editor",
584
659
  children: [
585
660
  !isEditing ? /* @__PURE__ */ jsx("button", {
661
+ className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
586
662
  type: "button",
587
663
  onClick: () => setEditing(true),
588
664
  children: edit
589
665
  }) : /* @__PURE__ */ jsxs(Fragment, { children: [
590
666
  /* @__PURE__ */ jsx("button", {
667
+ className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500 disabled:opacity-60",
591
668
  type: "button",
592
669
  disabled: isSaving,
593
670
  onClick: () => void save(),
594
- children: saveLabel
671
+ children: isSaving ? "Saving…" : saveLabel
595
672
  }),
596
673
  canPublish && /* @__PURE__ */ jsx("button", {
674
+ className: "rounded-lg bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-60",
597
675
  type: "button",
598
676
  disabled: isSaving,
599
677
  onClick: () => void handlePublish(),
600
678
  children: publishLabel
601
679
  }),
602
680
  /* @__PURE__ */ jsx("button", {
681
+ className: "rounded-lg px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-100 disabled:opacity-60",
603
682
  type: "button",
604
683
  disabled: isSaving,
605
684
  onClick: () => setEditing(false),
@@ -607,10 +686,12 @@ function ContentToolbar({ className, labels = {}, confirmPublish }) {
607
686
  })
608
687
  ] }),
609
688
  error && /* @__PURE__ */ jsx("span", {
689
+ className: "w-full text-sm text-red-600 dark:text-red-400",
610
690
  role: "alert",
611
691
  children: error
612
692
  }),
613
693
  isEditing && isDirty && /* @__PURE__ */ jsx("span", {
694
+ className: "w-full text-xs text-slate-500",
614
695
  "aria-live": "polite",
615
696
  children: "Unsaved changes"
616
697
  })
@@ -619,40 +700,30 @@ function ContentToolbar({ className, labels = {}, confirmPublish }) {
619
700
  }
620
701
  //#endregion
621
702
  //#region src/react/content/content-editor.tsx
703
+ function EditorPanel({ title }) {
704
+ const { canEdit } = useContent();
705
+ if (!canEdit) return null;
706
+ return /* @__PURE__ */ jsxs("div", {
707
+ className: "fixed right-4 bottom-4 z-[1000] w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-3 text-slate-950 shadow-xl",
708
+ children: [/* @__PURE__ */ jsx("strong", {
709
+ className: "mb-2 block text-sm font-semibold",
710
+ children: title
711
+ }), /* @__PURE__ */ jsx(ContentToolbar, { labels: {
712
+ edit: "Edit",
713
+ save: "Save draft",
714
+ publish: "Publish",
715
+ cancel: "Cancel"
716
+ } })]
717
+ });
718
+ }
622
719
  function ContentEditor({ children, title = "JoAi Content", ...provider }) {
623
720
  return /* @__PURE__ */ jsx(ContentProvider, {
624
721
  ...provider,
625
722
  children: /* @__PURE__ */ jsxs("div", {
626
723
  "data-joai-content-editor": "true",
627
- children: [/* @__PURE__ */ jsxs("div", {
628
- style: {
629
- position: "fixed",
630
- right: 16,
631
- bottom: 16,
632
- zIndex: 1e3,
633
- maxWidth: "calc(100vw - 32px)",
634
- padding: 12,
635
- borderRadius: 14,
636
- background: "#111827",
637
- color: "#fff",
638
- boxShadow: "0 14px 40px rgba(0,0,0,.28)"
639
- },
640
- children: [/* @__PURE__ */ jsx("strong", {
641
- style: {
642
- display: "block",
643
- marginBottom: 8,
644
- fontSize: 13
645
- },
646
- children: title
647
- }), /* @__PURE__ */ jsx(ContentToolbar, { labels: {
648
- edit: "Edit",
649
- save: "Save draft",
650
- publish: "Publish",
651
- cancel: "Cancel"
652
- } })]
653
- }), children]
724
+ children: [/* @__PURE__ */ jsx(EditorPanel, { title }), children]
654
725
  })
655
726
  });
656
727
  }
657
728
  //#endregion
658
- export { ContentEditor, ContentProvider, ContentToolbar, EditableContent, EditableImage, EmbedChatInput, EmbedChatList, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useEmbedChat };
729
+ export { ContentEditor, ContentProvider, ContentToolbar, EditableContent, EditableImage, EmbedChatInput, EmbedChatList, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useContentValue, useEmbedChat };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joai/core",
3
- "version": "4.6.0",
3
+ "version": "4.7.1",
4
4
  "description": "JoAi shared types, HTTP service, and config",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,128 +0,0 @@
1
- //#region src/http/types.d.ts
2
- interface IHttpService {
3
- readonly baseUrl: string;
4
- readonly authToken: string | null;
5
- onNetworkError: (error: Error) => void;
6
- onUnauthorized: (response: IAppResponse<any>) => void;
7
- onSuccessfulResponse: (response: IAppResponse<any>) => void;
8
- onMaintenanceMode: (response: IAppResponse<any>) => void;
9
- get: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
10
- post: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
11
- put: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
12
- patch: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
13
- delete: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
14
- }
15
- interface IAppResponse<T> {
16
- data: T;
17
- meta?: any;
18
- body: any;
19
- errors: any;
20
- ok: boolean;
21
- paymentRequired: boolean;
22
- noContent: boolean;
23
- original: Response;
24
- }
25
- interface IRequestOptions {
26
- isJson?: boolean;
27
- headers?: {
28
- [name: string]: string;
29
- };
30
- }
31
- //#endregion
32
- //#region src/json/types.d.ts
33
- type JsonValue = string | number | boolean | null | JsonValue[] | {
34
- [key: string]: JsonValue;
35
- };
36
- //#endregion
37
- //#region src/media/types.d.ts
38
- type AppFileType = 'abi' | 'pdf' | 'image' | 'video' | 'json';
39
- type AppFile = {
40
- type: AppFileType;
41
- original: File;
42
- };
43
- type MediaLibraryAttributes = {
44
- uuid: string;
45
- order: number;
46
- name: string;
47
- custom_properties: {
48
- [key: string]: JsonValue;
49
- };
50
- preview_url: null | string;
51
- original_url: null | string;
52
- extension?: string;
53
- size?: number;
54
- };
55
- type MediaMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp' | 'video/mp4' | 'video/webm' | 'video/quicktime' | 'video/x-msvideo' | 'audio/mpeg' | 'audio/mp3' | 'audio/ogg' | 'audio/wav' | 'audio/webm' | 'audio/aac' | 'audio/m4a' | 'audio/m4b' | 'audio/m4p' | 'audio/m4v' | 'application/pdf' | 'application/json';
56
- type MediaAspectRatio = 'free' | '1:1' | '16:9' | '9:16' | '4:3' | '3:4';
57
- type Media = {
58
- id: string;
59
- name: string;
60
- mime: MediaMime;
61
- url: string;
62
- library: MediaLibraryAttributes;
63
- tags?: string[];
64
- copyright?: string | null;
65
- aiGenerated?: boolean;
66
- };
67
- //#endregion
68
- //#region src/content/types.d.ts
69
- type ContentStatus = 'draft' | 'published' | 'archived';
70
- type ContentFieldType = 'text' | 'richText' | 'number' | 'boolean' | 'url' | 'image' | 'media' | 'list' | 'object' | 'reference';
71
- type ContentField = {
72
- key: string;
73
- type: ContentFieldType;
74
- label?: string;
75
- required?: boolean;
76
- };
77
- type ContentDefinition = {
78
- fields: ContentField[];
79
- };
80
- type ContentValue = string | number | boolean | null | ContentValue[] | {
81
- [key: string]: ContentValue;
82
- };
83
- type ContentEntry = {
84
- key: string;
85
- value: ContentValue;
86
- updatedAt: string;
87
- };
88
- type ContentVersion = {
89
- id: string;
90
- number: number;
91
- status: ContentStatus;
92
- entries: ContentEntry[];
93
- snapshotHash: string;
94
- origin: string;
95
- createdAt: string;
96
- updatedAt: string;
97
- publishedAt: string | null;
98
- };
99
- type Content = {
100
- id: string;
101
- name: string;
102
- slug: string;
103
- schema: string | null;
104
- definition: ContentDefinition;
105
- metadata: Record<string, ContentValue>;
106
- version: ContentVersion | null;
107
- createdAt: string;
108
- updatedAt: string;
109
- };
110
- type ContentPatch = {
111
- key: string;
112
- value: ContentValue;
113
- };
114
- type CreateContentInput = {
115
- team: string;
116
- name: string;
117
- slug: string;
118
- schema?: string | null;
119
- definition: ContentDefinition;
120
- metadata?: Record<string, ContentValue>;
121
- };
122
- type PatchContentInput = {
123
- expectedVersion: number;
124
- patches: ContentPatch[];
125
- origin?: 'api' | 'inlineEditor' | 'joai' | 'mcp';
126
- };
127
- //#endregion
128
- export { MediaMime as _, ContentFieldType as a, IHttpService as b, ContentValue as c, PatchContentInput as d, AppFile as f, MediaLibraryAttributes as g, MediaAspectRatio as h, ContentField as i, ContentVersion as l, Media as m, ContentDefinition as n, ContentPatch as o, AppFileType as p, ContentEntry as r, ContentStatus as s, Content as t, CreateContentInput as u, JsonValue as v, IRequestOptions as x, IAppResponse as y };