@talex-touch/utils 1.0.42 → 1.0.45
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/.eslintcache +1 -0
- package/__tests__/cloud-sync-sdk.test.ts +442 -0
- package/__tests__/icons/icons.test.ts +84 -0
- package/__tests__/plugin-sdk-lifecycle.test.ts +130 -0
- package/__tests__/power-sdk.test.ts +143 -0
- package/__tests__/preset-export-types.test.ts +108 -0
- package/__tests__/search/fuzzy-match.test.ts +137 -0
- package/__tests__/transport/port-policy.test.ts +44 -0
- package/__tests__/transport-domain-sdks.test.ts +152 -0
- package/__tests__/types/update.test.ts +67 -0
- package/account/account-sdk.ts +915 -0
- package/account/index.ts +2 -0
- package/account/types.ts +321 -0
- package/analytics/client.ts +136 -0
- package/analytics/index.ts +2 -0
- package/analytics/types.ts +156 -0
- package/animation/auto-resize.ts +322 -0
- package/animation/window-node.ts +26 -19
- package/auth/clerk-types.ts +12 -30
- package/auth/index.ts +0 -2
- package/auth/useAuthState.ts +6 -14
- package/base/index.ts +2 -0
- package/base/log-level.ts +105 -0
- package/channel/index.ts +170 -69
- package/cloud-sync/cloud-sync-sdk.ts +450 -0
- package/cloud-sync/index.ts +1 -0
- package/common/file-scan-utils.ts +17 -9
- package/common/index.ts +4 -0
- package/common/logger/index.ts +46 -0
- package/common/logger/logger-manager.ts +303 -0
- package/common/logger/module-logger.ts +270 -0
- package/common/logger/transport-logger.ts +234 -0
- package/common/logger/types.ts +93 -0
- package/common/search/gather.ts +48 -6
- package/common/search/index.ts +8 -0
- package/common/storage/constants.ts +13 -0
- package/common/storage/entity/app-settings.ts +245 -0
- package/common/storage/entity/index.ts +3 -0
- package/common/storage/entity/layout-atom-types.ts +147 -0
- package/common/storage/entity/openers.ts +1 -0
- package/common/storage/entity/preset-cloud-api.ts +132 -0
- package/common/storage/entity/preset-export-types.ts +256 -0
- package/common/storage/entity/shortcut-settings.ts +1 -0
- package/common/storage/shortcut-storage.ts +11 -0
- package/common/utils/clone-diagnostics.ts +105 -0
- package/common/utils/file.ts +16 -8
- package/common/utils/index.ts +6 -2
- package/common/utils/payload-preview.ts +173 -0
- package/common/utils/polling.ts +167 -13
- package/common/utils/safe-path.ts +103 -0
- package/common/utils/safe-shell.ts +115 -0
- package/common/utils/task-queue.ts +4 -1
- package/core-box/builder/tuff-builder.ts +0 -1
- package/core-box/index.ts +1 -1
- package/core-box/recommendation.ts +38 -1
- package/core-box/tuff/tuff-dsl.ts +32 -0
- package/electron/download-manager.ts +10 -7
- package/electron/env-tool.ts +42 -40
- package/electron/index.ts +0 -1
- package/env/index.ts +156 -0
- package/eslint.config.js +55 -0
- package/i18n/index.ts +62 -0
- package/i18n/locales/en.json +226 -0
- package/i18n/locales/zh.json +226 -0
- package/i18n/message-keys.ts +236 -0
- package/i18n/resolver.ts +181 -0
- package/icons/index.ts +257 -0
- package/icons/svg.ts +69 -0
- package/index.ts +9 -1
- package/intelligence/client.ts +72 -42
- package/market/constants.ts +9 -5
- package/market/index.ts +1 -1
- package/market/types.ts +19 -4
- package/package.json +15 -5
- package/permission/index.ts +143 -46
- package/permission/legacy.ts +26 -0
- package/permission/registry.ts +304 -0
- package/permission/types.ts +164 -0
- package/plugin/channel.ts +68 -39
- package/plugin/index.ts +80 -7
- package/plugin/install.ts +3 -0
- package/plugin/log/types.ts +22 -5
- package/plugin/node/logger-manager.ts +11 -3
- package/plugin/node/logger.ts +24 -17
- package/plugin/preload.ts +25 -2
- package/plugin/providers/index.ts +4 -4
- package/plugin/providers/market-client.ts +6 -3
- package/plugin/providers/npm-provider.ts +22 -7
- package/plugin/providers/tpex-provider.ts +22 -8
- package/plugin/sdk/box-items.ts +14 -0
- package/plugin/sdk/box-sdk.ts +64 -0
- package/plugin/sdk/channel.ts +119 -4
- package/plugin/sdk/clipboard.ts +26 -12
- package/plugin/sdk/cloud-sync.ts +113 -0
- package/plugin/sdk/common.ts +19 -11
- package/plugin/sdk/core-box.ts +6 -15
- package/plugin/sdk/division-box.ts +160 -65
- package/plugin/sdk/examples/storage-onDidChange-example.js +5 -2
- package/plugin/sdk/feature-sdk.ts +111 -76
- package/plugin/sdk/flow.ts +146 -45
- package/plugin/sdk/hooks/bridge.ts +13 -6
- package/plugin/sdk/hooks/life-cycle.ts +35 -16
- package/plugin/sdk/index.ts +14 -3
- package/plugin/sdk/intelligence.ts +87 -0
- package/plugin/sdk/meta/README.md +179 -0
- package/plugin/sdk/meta-sdk.ts +244 -0
- package/plugin/sdk/notification.ts +9 -0
- package/plugin/sdk/plugin-info.ts +64 -0
- package/plugin/sdk/power.ts +155 -0
- package/plugin/sdk/recommend.ts +21 -0
- package/plugin/sdk/service/index.ts +12 -8
- package/plugin/sdk/sqlite.ts +141 -0
- package/plugin/sdk/storage.ts +2 -6
- package/plugin/sdk/system.ts +2 -9
- package/plugin/sdk/temp-files.ts +41 -0
- package/plugin/sdk/touch-sdk.ts +18 -0
- package/plugin/sdk/types.ts +44 -4
- package/plugin/sdk/window/index.ts +12 -9
- package/plugin/sdk-version.ts +231 -0
- package/preload/renderer.ts +3 -2
- package/renderer/hooks/arg-mapper.ts +16 -2
- package/renderer/hooks/index.ts +13 -0
- package/renderer/hooks/initialize.ts +2 -1
- package/renderer/hooks/use-agent-market-sdk.ts +7 -0
- package/renderer/hooks/use-agent-market.ts +106 -0
- package/renderer/hooks/use-agents-sdk.ts +7 -0
- package/renderer/hooks/use-app-sdk.ts +7 -0
- package/renderer/hooks/use-channel.ts +33 -4
- package/renderer/hooks/use-download-sdk.ts +21 -0
- package/renderer/hooks/use-intelligence-sdk.ts +7 -0
- package/renderer/hooks/use-intelligence-stats.ts +290 -0
- package/renderer/hooks/use-intelligence.ts +55 -214
- package/renderer/hooks/use-market-sdk.ts +16 -0
- package/renderer/hooks/use-notification-sdk.ts +7 -0
- package/renderer/hooks/use-permission-sdk.ts +7 -0
- package/renderer/hooks/use-permission.ts +325 -0
- package/renderer/hooks/use-platform-sdk.ts +7 -0
- package/renderer/hooks/use-plugin-sdk.ts +16 -0
- package/renderer/hooks/use-settings-sdk.ts +7 -0
- package/renderer/hooks/use-update-sdk.ts +21 -0
- package/renderer/index.ts +1 -0
- package/renderer/ref.ts +19 -10
- package/renderer/shared/components/SharedPluginDetailContent.vue +84 -0
- package/renderer/shared/components/SharedPluginDetailHeader.vue +116 -0
- package/renderer/shared/components/SharedPluginDetailMetaList.vue +39 -0
- package/renderer/shared/components/SharedPluginDetailReadme.vue +45 -0
- package/renderer/shared/components/SharedPluginDetailVersions.vue +98 -0
- package/renderer/shared/components/index.ts +5 -0
- package/renderer/shared/components/shims-vue.d.ts +5 -0
- package/renderer/shared/index.ts +2 -0
- package/renderer/shared/plugin-detail.ts +62 -0
- package/renderer/storage/app-settings.ts +3 -1
- package/renderer/storage/base-storage.ts +508 -82
- package/renderer/storage/intelligence-storage.ts +31 -40
- package/renderer/storage/openers.ts +3 -1
- package/renderer/storage/storage-subscription.ts +126 -42
- package/renderer/touch-sdk/env.ts +10 -10
- package/renderer/touch-sdk/index.ts +114 -18
- package/renderer/touch-sdk/terminal.ts +24 -13
- package/search/feature-matcher.ts +279 -0
- package/search/fuzzy-match.ts +64 -34
- package/search/index.ts +10 -0
- package/search/levenshtein-utils.ts +17 -11
- package/transport/errors.ts +310 -0
- package/transport/event/builder.ts +378 -0
- package/transport/event/index.ts +7 -0
- package/transport/event/types.ts +292 -0
- package/transport/events/index.ts +2690 -0
- package/transport/events/meta-overlay.ts +79 -0
- package/transport/events/types/agents.ts +177 -0
- package/transport/events/types/app-index.ts +20 -0
- package/transport/events/types/app.ts +475 -0
- package/transport/events/types/box-item.ts +222 -0
- package/transport/events/types/clipboard.ts +80 -0
- package/transport/events/types/core-box.ts +534 -0
- package/transport/events/types/device-idle.ts +7 -0
- package/transport/events/types/division-box.ts +99 -0
- package/transport/events/types/download.ts +115 -0
- package/transport/events/types/file-index.ts +84 -0
- package/transport/events/types/flow.ts +149 -0
- package/transport/events/types/index.ts +70 -0
- package/transport/events/types/market.ts +39 -0
- package/transport/events/types/meta-overlay.ts +184 -0
- package/transport/events/types/notification.ts +140 -0
- package/transport/events/types/permission.ts +90 -0
- package/transport/events/types/platform.ts +8 -0
- package/transport/events/types/plugin.ts +631 -0
- package/transport/events/types/sentry.ts +20 -0
- package/transport/events/types/storage.ts +208 -0
- package/transport/events/types/transport.ts +60 -0
- package/transport/events/types/tray.ts +16 -0
- package/transport/events/types/update.ts +78 -0
- package/transport/index.ts +141 -0
- package/transport/main.ts +2 -0
- package/transport/prelude.ts +208 -0
- package/transport/sdk/constants.ts +29 -0
- package/transport/sdk/domains/agents-market.ts +47 -0
- package/transport/sdk/domains/agents.ts +62 -0
- package/transport/sdk/domains/app.ts +48 -0
- package/transport/sdk/domains/disposable.ts +35 -0
- package/transport/sdk/domains/download.ts +139 -0
- package/transport/sdk/domains/index.ts +13 -0
- package/transport/sdk/domains/intelligence.ts +616 -0
- package/transport/sdk/domains/market.ts +35 -0
- package/transport/sdk/domains/notification.ts +62 -0
- package/transport/sdk/domains/permission.ts +85 -0
- package/transport/sdk/domains/platform.ts +19 -0
- package/transport/sdk/domains/plugin.ts +144 -0
- package/transport/sdk/domains/settings.ts +102 -0
- package/transport/sdk/domains/update.ts +64 -0
- package/transport/sdk/index.ts +60 -0
- package/transport/sdk/main-transport.ts +710 -0
- package/transport/sdk/main.ts +9 -0
- package/transport/sdk/plugin-transport.ts +654 -0
- package/transport/sdk/port-policy.ts +38 -0
- package/transport/sdk/renderer-transport.ts +1165 -0
- package/transport/types.ts +605 -0
- package/types/agent.ts +399 -0
- package/types/cloud-sync.ts +157 -0
- package/types/division-box.ts +31 -31
- package/types/download.ts +1 -0
- package/types/flow.ts +63 -12
- package/types/icon.ts +2 -1
- package/types/index.ts +5 -0
- package/types/intelligence.ts +166 -173
- package/types/modules/base.ts +2 -0
- package/types/path-browserify.d.ts +5 -0
- package/types/platform.ts +12 -0
- package/types/startup-info.ts +32 -0
- package/types/touch-app-core.ts +8 -8
- package/types/update.ts +94 -1
- package/vitest.config.ts +25 -0
- package/auth/useClerkConfig.ts +0 -40
- package/auth/useClerkProvider.ts +0 -52
|
@@ -0,0 +1,915 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AccountInfo,
|
|
3
|
+
AccountSDKConfig,
|
|
4
|
+
DeviceSession,
|
|
5
|
+
FeatureFlag,
|
|
6
|
+
PlanComparisonItem,
|
|
7
|
+
PlanQuota,
|
|
8
|
+
QuotaCheckResult,
|
|
9
|
+
SocialConnection,
|
|
10
|
+
Subscription,
|
|
11
|
+
Team,
|
|
12
|
+
UpgradeOption,
|
|
13
|
+
UsageStats,
|
|
14
|
+
UserProfile,
|
|
15
|
+
} from './types'
|
|
16
|
+
import {
|
|
17
|
+
BillingCycle,
|
|
18
|
+
SubscriptionPlan,
|
|
19
|
+
SubscriptionStatus,
|
|
20
|
+
TeamRole,
|
|
21
|
+
VerificationStatus,
|
|
22
|
+
} from './types'
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Default plan quotas
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_PLAN_QUOTAS: Record<SubscriptionPlan, PlanQuota> = {
|
|
28
|
+
[SubscriptionPlan.FREE]: {
|
|
29
|
+
aiRequestsPerDay: 50,
|
|
30
|
+
aiTokensPerMonth: 100000,
|
|
31
|
+
maxPlugins: 5,
|
|
32
|
+
maxStorageBytes: 100 * 1024 * 1024, // 100MB
|
|
33
|
+
maxWorkspaces: 1,
|
|
34
|
+
customModelAccess: false,
|
|
35
|
+
prioritySupport: false,
|
|
36
|
+
apiAccess: false,
|
|
37
|
+
advancedAnalytics: false,
|
|
38
|
+
},
|
|
39
|
+
[SubscriptionPlan.PRO]: {
|
|
40
|
+
aiRequestsPerDay: 500,
|
|
41
|
+
aiTokensPerMonth: 1000000,
|
|
42
|
+
maxPlugins: 20,
|
|
43
|
+
maxStorageBytes: 1024 * 1024 * 1024, // 1GB
|
|
44
|
+
maxWorkspaces: 5,
|
|
45
|
+
customModelAccess: true,
|
|
46
|
+
prioritySupport: false,
|
|
47
|
+
apiAccess: true,
|
|
48
|
+
advancedAnalytics: false,
|
|
49
|
+
},
|
|
50
|
+
[SubscriptionPlan.PLUS]: {
|
|
51
|
+
aiRequestsPerDay: 2000,
|
|
52
|
+
aiTokensPerMonth: 5000000,
|
|
53
|
+
maxPlugins: 50,
|
|
54
|
+
maxStorageBytes: 5 * 1024 * 1024 * 1024, // 5GB
|
|
55
|
+
maxWorkspaces: 20,
|
|
56
|
+
customModelAccess: true,
|
|
57
|
+
prioritySupport: true,
|
|
58
|
+
apiAccess: true,
|
|
59
|
+
advancedAnalytics: true,
|
|
60
|
+
},
|
|
61
|
+
[SubscriptionPlan.TEAM]: {
|
|
62
|
+
aiRequestsPerDay: 10000,
|
|
63
|
+
aiTokensPerMonth: 20000000,
|
|
64
|
+
maxPlugins: 100,
|
|
65
|
+
maxStorageBytes: 20 * 1024 * 1024 * 1024, // 20GB
|
|
66
|
+
maxTeamMembers: 10,
|
|
67
|
+
maxWorkspaces: 50,
|
|
68
|
+
customModelAccess: true,
|
|
69
|
+
prioritySupport: true,
|
|
70
|
+
apiAccess: true,
|
|
71
|
+
advancedAnalytics: true,
|
|
72
|
+
},
|
|
73
|
+
[SubscriptionPlan.ENTERPRISE]: {
|
|
74
|
+
aiRequestsPerDay: -1, // Unlimited
|
|
75
|
+
aiTokensPerMonth: -1, // Unlimited
|
|
76
|
+
maxPlugins: -1, // Unlimited
|
|
77
|
+
maxStorageBytes: -1, // Unlimited
|
|
78
|
+
maxTeamMembers: -1, // Unlimited
|
|
79
|
+
maxWorkspaces: -1, // Unlimited
|
|
80
|
+
customModelAccess: true,
|
|
81
|
+
prioritySupport: true,
|
|
82
|
+
apiAccess: true,
|
|
83
|
+
advancedAnalytics: true,
|
|
84
|
+
},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Upgrade options with pricing
|
|
89
|
+
*/
|
|
90
|
+
export const UPGRADE_OPTIONS: UpgradeOption[] = [
|
|
91
|
+
{
|
|
92
|
+
plan: SubscriptionPlan.PRO,
|
|
93
|
+
name: 'Pro',
|
|
94
|
+
description: 'For power users who need more AI capabilities',
|
|
95
|
+
priceMonthly: 9.99,
|
|
96
|
+
priceYearly: 99.99,
|
|
97
|
+
currency: 'USD',
|
|
98
|
+
features: [
|
|
99
|
+
'500 AI requests/day',
|
|
100
|
+
'1M tokens/month',
|
|
101
|
+
'20 plugins',
|
|
102
|
+
'1GB storage',
|
|
103
|
+
'Custom model access',
|
|
104
|
+
'API access',
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
plan: SubscriptionPlan.PLUS,
|
|
109
|
+
name: 'Plus',
|
|
110
|
+
description: 'For professionals who demand the best',
|
|
111
|
+
priceMonthly: 19.99,
|
|
112
|
+
priceYearly: 199.99,
|
|
113
|
+
currency: 'USD',
|
|
114
|
+
features: [
|
|
115
|
+
'2000 AI requests/day',
|
|
116
|
+
'5M tokens/month',
|
|
117
|
+
'50 plugins',
|
|
118
|
+
'5GB storage',
|
|
119
|
+
'Priority support',
|
|
120
|
+
'Advanced analytics',
|
|
121
|
+
],
|
|
122
|
+
recommended: true,
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
plan: SubscriptionPlan.TEAM,
|
|
126
|
+
name: 'Team',
|
|
127
|
+
description: 'For teams that collaborate',
|
|
128
|
+
priceMonthly: 49.99,
|
|
129
|
+
priceYearly: 499.99,
|
|
130
|
+
currency: 'USD',
|
|
131
|
+
features: [
|
|
132
|
+
'10000 AI requests/day',
|
|
133
|
+
'20M tokens/month',
|
|
134
|
+
'Unlimited plugins',
|
|
135
|
+
'20GB storage',
|
|
136
|
+
'Up to 10 team members',
|
|
137
|
+
'Team management',
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Account SDK for plugins and Prelude scripts
|
|
144
|
+
*/
|
|
145
|
+
export class AccountSDK {
|
|
146
|
+
private config: AccountSDKConfig
|
|
147
|
+
private cache: Map<string, { data: any, timestamp: number }> = new Map()
|
|
148
|
+
private channelSend: ((event: string, data?: any) => Promise<any>) | null = null
|
|
149
|
+
|
|
150
|
+
constructor(config: AccountSDKConfig = {}) {
|
|
151
|
+
this.config = {
|
|
152
|
+
cacheTTL: 60000, // 1 minute default
|
|
153
|
+
offlineMode: false,
|
|
154
|
+
...config,
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Set the channel send function for IPC communication
|
|
160
|
+
*/
|
|
161
|
+
setChannelSend(send: (event: string, data?: any) => Promise<any>): void {
|
|
162
|
+
this.channelSend = send
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
private async send<T>(event: string, data?: any): Promise<T> {
|
|
166
|
+
if (!this.channelSend) {
|
|
167
|
+
throw new Error('[AccountSDK] Channel not initialized. Call setChannelSend first.')
|
|
168
|
+
}
|
|
169
|
+
return this.channelSend(event, data)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private getCached<T>(key: string): T | null {
|
|
173
|
+
const cached = this.cache.get(key)
|
|
174
|
+
if (!cached)
|
|
175
|
+
return null
|
|
176
|
+
|
|
177
|
+
const ttl = this.config.cacheTTL || 60000
|
|
178
|
+
if (Date.now() - cached.timestamp > ttl) {
|
|
179
|
+
this.cache.delete(key)
|
|
180
|
+
return null
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return cached.data as T
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private setCache(key: string, data: any): void {
|
|
187
|
+
this.cache.set(key, { data, timestamp: Date.now() })
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Clear all cached data
|
|
192
|
+
*/
|
|
193
|
+
clearCache(): void {
|
|
194
|
+
this.cache.clear()
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// ============================================================================
|
|
198
|
+
// Auth Token & Device
|
|
199
|
+
// ============================================================================
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Get auth token for API requests
|
|
203
|
+
*/
|
|
204
|
+
async getAuthToken(): Promise<string | null> {
|
|
205
|
+
const cached = this.getCached<string>('authToken')
|
|
206
|
+
if (cached)
|
|
207
|
+
return cached
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
const token = await this.send<string | null>('account:get-auth-token')
|
|
211
|
+
if (token) {
|
|
212
|
+
this.setCache('authToken', token)
|
|
213
|
+
}
|
|
214
|
+
return token
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
return null
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get current device id
|
|
223
|
+
*/
|
|
224
|
+
async getDeviceId(): Promise<string | null> {
|
|
225
|
+
const cached = this.getCached<string>('deviceId')
|
|
226
|
+
if (cached)
|
|
227
|
+
return cached
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
const deviceId = await this.send<string | null>('account:get-device-id')
|
|
231
|
+
if (deviceId) {
|
|
232
|
+
this.setCache('deviceId', deviceId)
|
|
233
|
+
}
|
|
234
|
+
return deviceId
|
|
235
|
+
}
|
|
236
|
+
catch {
|
|
237
|
+
return null
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Get user sync preference switch from host app.
|
|
243
|
+
* Defaults to true for backward compatibility when channel is not implemented.
|
|
244
|
+
*/
|
|
245
|
+
async getSyncEnabled(): Promise<boolean> {
|
|
246
|
+
try {
|
|
247
|
+
const enabled = await this.send<boolean | null>('account:get-sync-enabled')
|
|
248
|
+
return typeof enabled === 'boolean' ? enabled : true
|
|
249
|
+
}
|
|
250
|
+
catch {
|
|
251
|
+
return true
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Report sync activity to host app for status display.
|
|
257
|
+
*/
|
|
258
|
+
async recordSyncActivity(kind: 'push' | 'pull'): Promise<void> {
|
|
259
|
+
try {
|
|
260
|
+
await this.send('account:record-sync-activity', { kind })
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// ignore, best-effort telemetry
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// ============================================================================
|
|
268
|
+
// User Profile
|
|
269
|
+
// ============================================================================
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Get current user profile
|
|
273
|
+
*/
|
|
274
|
+
async getProfile(): Promise<UserProfile | null> {
|
|
275
|
+
const cached = this.getCached<UserProfile>('profile')
|
|
276
|
+
if (cached)
|
|
277
|
+
return cached
|
|
278
|
+
|
|
279
|
+
try {
|
|
280
|
+
const profile = await this.send<UserProfile | null>('account:get-profile')
|
|
281
|
+
if (profile) {
|
|
282
|
+
this.setCache('profile', profile)
|
|
283
|
+
}
|
|
284
|
+
return profile
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
return null
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Check if user is logged in
|
|
293
|
+
*/
|
|
294
|
+
async isLoggedIn(): Promise<boolean> {
|
|
295
|
+
const profile = await this.getProfile()
|
|
296
|
+
return profile !== null
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* Get user ID
|
|
301
|
+
*/
|
|
302
|
+
async getUserId(): Promise<string | null> {
|
|
303
|
+
const profile = await this.getProfile()
|
|
304
|
+
return profile?.id ?? null
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Get display name
|
|
309
|
+
*/
|
|
310
|
+
async getDisplayName(): Promise<string> {
|
|
311
|
+
const profile = await this.getProfile()
|
|
312
|
+
if (!profile)
|
|
313
|
+
return ''
|
|
314
|
+
const email = profile.email ?? ''
|
|
315
|
+
const emailName = email ? email.split('@')[0] : ''
|
|
316
|
+
return profile.displayName ?? profile.username ?? emailName
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Get user email
|
|
321
|
+
*/
|
|
322
|
+
async getEmail(): Promise<string | null> {
|
|
323
|
+
const profile = await this.getProfile()
|
|
324
|
+
return profile?.email ?? null
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Get avatar URL
|
|
329
|
+
*/
|
|
330
|
+
async getAvatarUrl(): Promise<string | null> {
|
|
331
|
+
const profile = await this.getProfile()
|
|
332
|
+
return profile?.avatarUrl ?? null
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// ============================================================================
|
|
336
|
+
// Subscription & Plan
|
|
337
|
+
// ============================================================================
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Get current subscription
|
|
341
|
+
*/
|
|
342
|
+
async getSubscription(): Promise<Subscription | null> {
|
|
343
|
+
const cached = this.getCached<Subscription>('subscription')
|
|
344
|
+
if (cached)
|
|
345
|
+
return cached
|
|
346
|
+
|
|
347
|
+
try {
|
|
348
|
+
const subscription = await this.send<Subscription | null>('account:get-subscription')
|
|
349
|
+
if (subscription) {
|
|
350
|
+
this.setCache('subscription', subscription)
|
|
351
|
+
}
|
|
352
|
+
return subscription
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return null
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Get current plan
|
|
361
|
+
*/
|
|
362
|
+
async getPlan(): Promise<SubscriptionPlan> {
|
|
363
|
+
const subscription = await this.getSubscription()
|
|
364
|
+
return subscription?.plan ?? SubscriptionPlan.FREE
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Check if user has a paid plan
|
|
369
|
+
*/
|
|
370
|
+
async isPaidUser(): Promise<boolean> {
|
|
371
|
+
const plan = await this.getPlan()
|
|
372
|
+
return plan !== SubscriptionPlan.FREE
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Check if user is Pro or above
|
|
377
|
+
*/
|
|
378
|
+
async isProOrAbove(): Promise<boolean> {
|
|
379
|
+
const plan = await this.getPlan()
|
|
380
|
+
return [
|
|
381
|
+
SubscriptionPlan.PRO,
|
|
382
|
+
SubscriptionPlan.PLUS,
|
|
383
|
+
SubscriptionPlan.TEAM,
|
|
384
|
+
SubscriptionPlan.ENTERPRISE,
|
|
385
|
+
].includes(plan)
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Check if user is Plus or above
|
|
390
|
+
*/
|
|
391
|
+
async isPlusOrAbove(): Promise<boolean> {
|
|
392
|
+
const plan = await this.getPlan()
|
|
393
|
+
return [
|
|
394
|
+
SubscriptionPlan.PLUS,
|
|
395
|
+
SubscriptionPlan.TEAM,
|
|
396
|
+
SubscriptionPlan.ENTERPRISE,
|
|
397
|
+
].includes(plan)
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Check if user is Team or above
|
|
402
|
+
*/
|
|
403
|
+
async isTeamOrAbove(): Promise<boolean> {
|
|
404
|
+
const plan = await this.getPlan()
|
|
405
|
+
return [
|
|
406
|
+
SubscriptionPlan.TEAM,
|
|
407
|
+
SubscriptionPlan.ENTERPRISE,
|
|
408
|
+
].includes(plan)
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Check if user is Enterprise
|
|
413
|
+
*/
|
|
414
|
+
async isEnterprise(): Promise<boolean> {
|
|
415
|
+
const plan = await this.getPlan()
|
|
416
|
+
return plan === SubscriptionPlan.ENTERPRISE
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* Check if subscription is active
|
|
421
|
+
*/
|
|
422
|
+
async isSubscriptionActive(): Promise<boolean> {
|
|
423
|
+
const subscription = await this.getSubscription()
|
|
424
|
+
if (!subscription)
|
|
425
|
+
return false
|
|
426
|
+
return [
|
|
427
|
+
SubscriptionStatus.ACTIVE,
|
|
428
|
+
SubscriptionStatus.TRIALING,
|
|
429
|
+
].includes(subscription.status)
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* Check if user is in trial period
|
|
434
|
+
*/
|
|
435
|
+
async isTrialing(): Promise<boolean> {
|
|
436
|
+
const subscription = await this.getSubscription()
|
|
437
|
+
return subscription?.status === SubscriptionStatus.TRIALING
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
/**
|
|
441
|
+
* Get days remaining in current period
|
|
442
|
+
*/
|
|
443
|
+
async getDaysRemaining(): Promise<number> {
|
|
444
|
+
const subscription = await this.getSubscription()
|
|
445
|
+
if (!subscription)
|
|
446
|
+
return 0
|
|
447
|
+
|
|
448
|
+
const now = Date.now()
|
|
449
|
+
const end = subscription.currentPeriodEnd
|
|
450
|
+
const days = Math.ceil((end - now) / (1000 * 60 * 60 * 24))
|
|
451
|
+
return Math.max(0, days)
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Get trial days remaining
|
|
456
|
+
*/
|
|
457
|
+
async getTrialDaysRemaining(): Promise<number> {
|
|
458
|
+
const subscription = await this.getSubscription()
|
|
459
|
+
if (!subscription?.trialEndAt)
|
|
460
|
+
return 0
|
|
461
|
+
|
|
462
|
+
const now = Date.now()
|
|
463
|
+
const days = Math.ceil((subscription.trialEndAt - now) / (1000 * 60 * 60 * 24))
|
|
464
|
+
return Math.max(0, days)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// ============================================================================
|
|
468
|
+
// Quota & Usage
|
|
469
|
+
// ============================================================================
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* Get plan quota limits
|
|
473
|
+
*/
|
|
474
|
+
async getQuota(): Promise<PlanQuota> {
|
|
475
|
+
const subscription = await this.getSubscription()
|
|
476
|
+
return subscription?.quota ?? DEFAULT_PLAN_QUOTAS[SubscriptionPlan.FREE]
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* Get current usage stats
|
|
481
|
+
*/
|
|
482
|
+
async getUsage(): Promise<UsageStats> {
|
|
483
|
+
const cached = this.getCached<UsageStats>('usage')
|
|
484
|
+
if (cached)
|
|
485
|
+
return cached
|
|
486
|
+
|
|
487
|
+
try {
|
|
488
|
+
const usage = await this.send<UsageStats>('account:get-usage')
|
|
489
|
+
this.setCache('usage', usage)
|
|
490
|
+
return usage
|
|
491
|
+
}
|
|
492
|
+
catch {
|
|
493
|
+
return {
|
|
494
|
+
aiRequestsToday: 0,
|
|
495
|
+
aiRequestsThisMonth: 0,
|
|
496
|
+
aiTokensThisMonth: 0,
|
|
497
|
+
storageUsedBytes: 0,
|
|
498
|
+
pluginsInstalled: 0,
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Check if AI requests quota is available
|
|
505
|
+
*/
|
|
506
|
+
async checkAiRequestQuota(): Promise<QuotaCheckResult> {
|
|
507
|
+
const [quota, usage] = await Promise.all([this.getQuota(), this.getUsage()])
|
|
508
|
+
|
|
509
|
+
if (quota.aiRequestsPerDay === -1) {
|
|
510
|
+
return { allowed: true, remaining: -1 }
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const remaining = quota.aiRequestsPerDay - usage.aiRequestsToday
|
|
514
|
+
if (remaining <= 0) {
|
|
515
|
+
const tomorrow = new Date()
|
|
516
|
+
tomorrow.setHours(24, 0, 0, 0)
|
|
517
|
+
return {
|
|
518
|
+
allowed: false,
|
|
519
|
+
reason: 'Daily AI request limit reached',
|
|
520
|
+
remaining: 0,
|
|
521
|
+
resetAt: tomorrow.getTime(),
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
return { allowed: true, remaining }
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Check if AI tokens quota is available
|
|
530
|
+
*/
|
|
531
|
+
async checkAiTokenQuota(estimatedTokens: number = 0): Promise<QuotaCheckResult> {
|
|
532
|
+
const [quota, usage] = await Promise.all([this.getQuota(), this.getUsage()])
|
|
533
|
+
|
|
534
|
+
if (quota.aiTokensPerMonth === -1) {
|
|
535
|
+
return { allowed: true, remaining: -1 }
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
const remaining = quota.aiTokensPerMonth - usage.aiTokensThisMonth
|
|
539
|
+
if (remaining < estimatedTokens) {
|
|
540
|
+
const nextMonth = new Date()
|
|
541
|
+
nextMonth.setMonth(nextMonth.getMonth() + 1, 1)
|
|
542
|
+
nextMonth.setHours(0, 0, 0, 0)
|
|
543
|
+
return {
|
|
544
|
+
allowed: false,
|
|
545
|
+
reason: 'Monthly AI token limit reached',
|
|
546
|
+
remaining: Math.max(0, remaining),
|
|
547
|
+
resetAt: nextMonth.getTime(),
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return { allowed: true, remaining }
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/**
|
|
555
|
+
* Check if storage quota is available
|
|
556
|
+
*/
|
|
557
|
+
async checkStorageQuota(additionalBytes: number = 0): Promise<QuotaCheckResult> {
|
|
558
|
+
const [quota, usage] = await Promise.all([this.getQuota(), this.getUsage()])
|
|
559
|
+
|
|
560
|
+
if (quota.maxStorageBytes === -1) {
|
|
561
|
+
return { allowed: true, remaining: -1 }
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
const remaining = quota.maxStorageBytes - usage.storageUsedBytes
|
|
565
|
+
if (remaining < additionalBytes) {
|
|
566
|
+
return {
|
|
567
|
+
allowed: false,
|
|
568
|
+
reason: 'Storage limit reached',
|
|
569
|
+
remaining: Math.max(0, remaining),
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
return { allowed: true, remaining }
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* Check if plugin install quota is available
|
|
578
|
+
*/
|
|
579
|
+
async checkPluginQuota(): Promise<QuotaCheckResult> {
|
|
580
|
+
const [quota, usage] = await Promise.all([this.getQuota(), this.getUsage()])
|
|
581
|
+
|
|
582
|
+
if (quota.maxPlugins === -1) {
|
|
583
|
+
return { allowed: true, remaining: -1 }
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const remaining = quota.maxPlugins - usage.pluginsInstalled
|
|
587
|
+
if (remaining <= 0) {
|
|
588
|
+
return {
|
|
589
|
+
allowed: false,
|
|
590
|
+
reason: 'Plugin limit reached',
|
|
591
|
+
remaining: 0,
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return { allowed: true, remaining }
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Get usage percentage (0-100)
|
|
600
|
+
*/
|
|
601
|
+
async getUsagePercentage(type: 'aiRequests' | 'aiTokens' | 'storage' | 'plugins'): Promise<number> {
|
|
602
|
+
const [quota, usage] = await Promise.all([this.getQuota(), this.getUsage()])
|
|
603
|
+
|
|
604
|
+
switch (type) {
|
|
605
|
+
case 'aiRequests':
|
|
606
|
+
if (quota.aiRequestsPerDay === -1)
|
|
607
|
+
return 0
|
|
608
|
+
return Math.min(100, (usage.aiRequestsToday / quota.aiRequestsPerDay) * 100)
|
|
609
|
+
case 'aiTokens':
|
|
610
|
+
if (quota.aiTokensPerMonth === -1)
|
|
611
|
+
return 0
|
|
612
|
+
return Math.min(100, (usage.aiTokensThisMonth / quota.aiTokensPerMonth) * 100)
|
|
613
|
+
case 'storage':
|
|
614
|
+
if (quota.maxStorageBytes === -1)
|
|
615
|
+
return 0
|
|
616
|
+
return Math.min(100, (usage.storageUsedBytes / quota.maxStorageBytes) * 100)
|
|
617
|
+
case 'plugins':
|
|
618
|
+
if (quota.maxPlugins === -1)
|
|
619
|
+
return 0
|
|
620
|
+
return Math.min(100, (usage.pluginsInstalled / quota.maxPlugins) * 100)
|
|
621
|
+
default:
|
|
622
|
+
return 0
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// ============================================================================
|
|
627
|
+
// Features & Permissions
|
|
628
|
+
// ============================================================================
|
|
629
|
+
|
|
630
|
+
/**
|
|
631
|
+
* Check if a feature is enabled for user
|
|
632
|
+
*/
|
|
633
|
+
async hasFeature(featureId: string): Promise<boolean> {
|
|
634
|
+
try {
|
|
635
|
+
const features = await this.send<FeatureFlag[]>('account:get-features')
|
|
636
|
+
const feature = features.find(f => f.id === featureId)
|
|
637
|
+
return feature?.enabled ?? false
|
|
638
|
+
}
|
|
639
|
+
catch {
|
|
640
|
+
return false
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* Get feature value
|
|
646
|
+
*/
|
|
647
|
+
async getFeatureValue<T = any>(featureId: string): Promise<T | null> {
|
|
648
|
+
try {
|
|
649
|
+
const features = await this.send<FeatureFlag[]>('account:get-features')
|
|
650
|
+
const feature = features.find(f => f.id === featureId)
|
|
651
|
+
return (feature?.value as T) ?? null
|
|
652
|
+
}
|
|
653
|
+
catch {
|
|
654
|
+
return null
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/**
|
|
659
|
+
* Check if user has API access
|
|
660
|
+
*/
|
|
661
|
+
async hasApiAccess(): Promise<boolean> {
|
|
662
|
+
const quota = await this.getQuota()
|
|
663
|
+
return quota.apiAccess
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
/**
|
|
667
|
+
* Check if user has custom model access
|
|
668
|
+
*/
|
|
669
|
+
async hasCustomModelAccess(): Promise<boolean> {
|
|
670
|
+
const quota = await this.getQuota()
|
|
671
|
+
return quota.customModelAccess
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
/**
|
|
675
|
+
* Check if user has priority support
|
|
676
|
+
*/
|
|
677
|
+
async hasPrioritySupport(): Promise<boolean> {
|
|
678
|
+
const quota = await this.getQuota()
|
|
679
|
+
return quota.prioritySupport
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
/**
|
|
683
|
+
* Check if user has advanced analytics
|
|
684
|
+
*/
|
|
685
|
+
async hasAdvancedAnalytics(): Promise<boolean> {
|
|
686
|
+
const quota = await this.getQuota()
|
|
687
|
+
return quota.advancedAnalytics
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// ============================================================================
|
|
691
|
+
// Team
|
|
692
|
+
// ============================================================================
|
|
693
|
+
|
|
694
|
+
/**
|
|
695
|
+
* Get user's teams
|
|
696
|
+
*/
|
|
697
|
+
async getTeams(): Promise<Team[]> {
|
|
698
|
+
try {
|
|
699
|
+
return await this.send<Team[]>('account:get-teams')
|
|
700
|
+
}
|
|
701
|
+
catch {
|
|
702
|
+
return []
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Check if user is in any team
|
|
708
|
+
*/
|
|
709
|
+
async isInTeam(): Promise<boolean> {
|
|
710
|
+
const teams = await this.getTeams()
|
|
711
|
+
return teams.length > 0
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Check if user is team owner
|
|
716
|
+
*/
|
|
717
|
+
async isTeamOwner(teamId?: string): Promise<boolean> {
|
|
718
|
+
const teams = await this.getTeams()
|
|
719
|
+
if (teamId) {
|
|
720
|
+
const team = teams.find(t => t.id === teamId)
|
|
721
|
+
return team?.role === TeamRole.OWNER
|
|
722
|
+
}
|
|
723
|
+
return teams.some(t => t.role === TeamRole.OWNER)
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Check if user is team admin
|
|
728
|
+
*/
|
|
729
|
+
async isTeamAdmin(teamId?: string): Promise<boolean> {
|
|
730
|
+
const teams = await this.getTeams()
|
|
731
|
+
if (teamId) {
|
|
732
|
+
const team = teams.find(t => t.id === teamId)
|
|
733
|
+
return team?.role === TeamRole.OWNER || team?.role === TeamRole.ADMIN
|
|
734
|
+
}
|
|
735
|
+
return teams.some(t => t.role === TeamRole.OWNER || t.role === TeamRole.ADMIN)
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// ============================================================================
|
|
739
|
+
// Sessions
|
|
740
|
+
// ============================================================================
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Get active sessions
|
|
744
|
+
*/
|
|
745
|
+
async getSessions(): Promise<DeviceSession[]> {
|
|
746
|
+
try {
|
|
747
|
+
return await this.send<DeviceSession[]>('account:get-sessions')
|
|
748
|
+
}
|
|
749
|
+
catch {
|
|
750
|
+
return []
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
/**
|
|
755
|
+
* Get current session
|
|
756
|
+
*/
|
|
757
|
+
async getCurrentSession(): Promise<DeviceSession | null> {
|
|
758
|
+
const sessions = await this.getSessions()
|
|
759
|
+
return sessions.find(s => s.isCurrent) ?? null
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
// ============================================================================
|
|
763
|
+
// Full Account Info
|
|
764
|
+
// ============================================================================
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Get complete account info
|
|
768
|
+
*/
|
|
769
|
+
async getAccountInfo(): Promise<AccountInfo | null> {
|
|
770
|
+
const cached = this.getCached<AccountInfo>('accountInfo')
|
|
771
|
+
if (cached)
|
|
772
|
+
return cached
|
|
773
|
+
|
|
774
|
+
try {
|
|
775
|
+
const info = await this.send<AccountInfo | null>('account:get-info')
|
|
776
|
+
if (info) {
|
|
777
|
+
this.setCache('accountInfo', info)
|
|
778
|
+
}
|
|
779
|
+
return info
|
|
780
|
+
}
|
|
781
|
+
catch {
|
|
782
|
+
return null
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
/**
|
|
787
|
+
* Check if user is beta tester
|
|
788
|
+
*/
|
|
789
|
+
async isBetaTester(): Promise<boolean> {
|
|
790
|
+
const info = await this.getAccountInfo()
|
|
791
|
+
return info?.isBetaTester ?? false
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* Get referral code
|
|
796
|
+
*/
|
|
797
|
+
async getReferralCode(): Promise<string | null> {
|
|
798
|
+
const info = await this.getAccountInfo()
|
|
799
|
+
return info?.referralCode ?? null
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Get referral count
|
|
804
|
+
*/
|
|
805
|
+
async getReferralCount(): Promise<number> {
|
|
806
|
+
const info = await this.getAccountInfo()
|
|
807
|
+
return info?.referralCount ?? 0
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// ============================================================================
|
|
811
|
+
// Upgrade & Billing
|
|
812
|
+
// ============================================================================
|
|
813
|
+
|
|
814
|
+
/**
|
|
815
|
+
* Get available upgrade options
|
|
816
|
+
*/
|
|
817
|
+
getUpgradeOptions(): UpgradeOption[] {
|
|
818
|
+
return UPGRADE_OPTIONS
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Get plan comparison table
|
|
823
|
+
*/
|
|
824
|
+
getPlanComparison(): PlanComparisonItem[] {
|
|
825
|
+
return [
|
|
826
|
+
{ feature: 'AI Requests/Day', free: 50, pro: 500, plus: 2000, team: 10000, enterprise: 'Unlimited' },
|
|
827
|
+
{ feature: 'AI Tokens/Month', free: '100K', pro: '1M', plus: '5M', team: '20M', enterprise: 'Unlimited' },
|
|
828
|
+
{ feature: 'Plugins', free: 5, pro: 20, plus: 50, team: 100, enterprise: 'Unlimited' },
|
|
829
|
+
{ feature: 'Storage', free: '100MB', pro: '1GB', plus: '5GB', team: '20GB', enterprise: 'Unlimited' },
|
|
830
|
+
{ feature: 'Workspaces', free: 1, pro: 5, plus: 20, team: 50, enterprise: 'Unlimited' },
|
|
831
|
+
{ feature: 'Team Members', free: false, pro: false, plus: false, team: 10, enterprise: 'Unlimited' },
|
|
832
|
+
{ feature: 'Custom Models', free: false, pro: true, plus: true, team: true, enterprise: true },
|
|
833
|
+
{ feature: 'API Access', free: false, pro: true, plus: true, team: true, enterprise: true },
|
|
834
|
+
{ feature: 'Priority Support', free: false, pro: false, plus: true, team: true, enterprise: true },
|
|
835
|
+
{ feature: 'Advanced Analytics', free: false, pro: false, plus: true, team: true, enterprise: true },
|
|
836
|
+
]
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Open upgrade page
|
|
841
|
+
*/
|
|
842
|
+
async openUpgradePage(plan?: SubscriptionPlan): Promise<void> {
|
|
843
|
+
await this.send('account:open-upgrade', { plan })
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
/**
|
|
847
|
+
* Open billing management page
|
|
848
|
+
*/
|
|
849
|
+
async openBillingPage(): Promise<void> {
|
|
850
|
+
await this.send('account:open-billing')
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// ============================================================================
|
|
854
|
+
// Account Actions
|
|
855
|
+
// ============================================================================
|
|
856
|
+
|
|
857
|
+
/**
|
|
858
|
+
* Open account settings
|
|
859
|
+
*/
|
|
860
|
+
async openAccountSettings(): Promise<void> {
|
|
861
|
+
await this.send('account:open-settings')
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
/**
|
|
865
|
+
* Open profile editor
|
|
866
|
+
*/
|
|
867
|
+
async openProfileEditor(): Promise<void> {
|
|
868
|
+
await this.send('account:open-profile')
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
/**
|
|
872
|
+
* Request login (opens login dialog)
|
|
873
|
+
*/
|
|
874
|
+
async requestLogin(): Promise<boolean> {
|
|
875
|
+
return this.send<boolean>('account:request-login')
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
/**
|
|
879
|
+
* Logout current user
|
|
880
|
+
*/
|
|
881
|
+
async logout(): Promise<void> {
|
|
882
|
+
this.clearCache()
|
|
883
|
+
await this.send('account:logout')
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
/**
|
|
888
|
+
* Singleton instance for easy import
|
|
889
|
+
*/
|
|
890
|
+
export const accountSDK = new AccountSDK()
|
|
891
|
+
|
|
892
|
+
// Re-export types and enums
|
|
893
|
+
export {
|
|
894
|
+
BillingCycle,
|
|
895
|
+
SubscriptionPlan,
|
|
896
|
+
SubscriptionStatus,
|
|
897
|
+
TeamRole,
|
|
898
|
+
VerificationStatus,
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
export type {
|
|
902
|
+
AccountInfo,
|
|
903
|
+
AccountSDKConfig,
|
|
904
|
+
DeviceSession,
|
|
905
|
+
FeatureFlag,
|
|
906
|
+
PlanComparisonItem,
|
|
907
|
+
PlanQuota,
|
|
908
|
+
QuotaCheckResult,
|
|
909
|
+
SocialConnection,
|
|
910
|
+
Subscription,
|
|
911
|
+
Team,
|
|
912
|
+
UpgradeOption,
|
|
913
|
+
UsageStats,
|
|
914
|
+
UserProfile,
|
|
915
|
+
}
|