snow-flow 10.0.80 → 10.0.82
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/package.json
CHANGED
package/src/agent/agent.ts
CHANGED
|
@@ -271,12 +271,22 @@ export namespace Agent {
|
|
|
271
271
|
item.permission = PermissionNext.merge(item.permission, PermissionNext.fromConfig(value.permission ?? {}))
|
|
272
272
|
}
|
|
273
273
|
|
|
274
|
-
// Unhide review agent for enterprise users
|
|
274
|
+
// Unhide review agent for enterprise users with the code-review module
|
|
275
275
|
const enterpriseAuth = await Auth.all().then((all) =>
|
|
276
276
|
Object.values(all).find((e) => e.type === "enterprise" && (e.licenseKey || e.token)),
|
|
277
277
|
)
|
|
278
|
-
if (enterpriseAuth && result.review) {
|
|
279
|
-
|
|
278
|
+
if (enterpriseAuth && result.review && enterpriseAuth.type === "enterprise") {
|
|
279
|
+
const jwt = enterpriseAuth.token
|
|
280
|
+
if (jwt) {
|
|
281
|
+
try {
|
|
282
|
+
const payload = JSON.parse(Buffer.from(jwt.split(".")[1], "base64").toString())
|
|
283
|
+
if (Array.isArray(payload.features) && payload.features.includes("code-review")) {
|
|
284
|
+
result.review.hidden = false
|
|
285
|
+
}
|
|
286
|
+
} catch {
|
|
287
|
+
// malformed token — keep review agent hidden
|
|
288
|
+
}
|
|
289
|
+
}
|
|
280
290
|
}
|
|
281
291
|
|
|
282
292
|
// Ensure Truncate.DIR is allowed unless explicitly configured
|
package/src/auth/index.ts
CHANGED
|
@@ -82,6 +82,10 @@ export namespace Auth {
|
|
|
82
82
|
azureOrg: z.string().optional(),
|
|
83
83
|
azureProject: z.string().optional(),
|
|
84
84
|
azurePat: z.string().optional(),
|
|
85
|
+
// Subscription & feature gating (set after device/verify)
|
|
86
|
+
features: z.array(z.string()).optional(),
|
|
87
|
+
subscriptionStatus: z.string().optional(),
|
|
88
|
+
trialEndsAt: z.number().optional(),
|
|
85
89
|
})
|
|
86
90
|
.meta({ ref: "Enterprise" })
|
|
87
91
|
|
|
@@ -1054,6 +1054,9 @@ function DialogAuthEnterprise() {
|
|
|
1054
1054
|
username: data.user?.username || data.user?.email,
|
|
1055
1055
|
email: data.user?.email,
|
|
1056
1056
|
role: data.user?.role,
|
|
1057
|
+
features: data.features || [],
|
|
1058
|
+
subscriptionStatus: data.subscription?.status,
|
|
1059
|
+
trialEndsAt: data.subscription?.trialEndsAt,
|
|
1057
1060
|
})
|
|
1058
1061
|
|
|
1059
1062
|
// Also save to ~/.snow-code/enterprise.json for the enterprise proxy
|
|
@@ -1185,6 +1188,50 @@ function DialogAuthEnterprise() {
|
|
|
1185
1188
|
console.error('[Enterprise] Failed to update documentation:', docError)
|
|
1186
1189
|
}
|
|
1187
1190
|
|
|
1191
|
+
// Show trial/subscription status toast
|
|
1192
|
+
try {
|
|
1193
|
+
const subStatus = data.subscription?.status
|
|
1194
|
+
const trialEnd = data.subscription?.trialEndsAt
|
|
1195
|
+
const featureCount = (data.features || []).length
|
|
1196
|
+
|
|
1197
|
+
if (subStatus === "trialing" && trialEnd) {
|
|
1198
|
+
const daysLeft = Math.max(0, Math.ceil((trialEnd - Date.now()) / (24 * 60 * 60 * 1000)))
|
|
1199
|
+
if (daysLeft <= 0) {
|
|
1200
|
+
toast.show({
|
|
1201
|
+
variant: "error",
|
|
1202
|
+
message: "Trial ended — visit portal.snow-flow.dev/portal/billing to activate features",
|
|
1203
|
+
duration: 8000,
|
|
1204
|
+
})
|
|
1205
|
+
} else if (daysLeft <= 3) {
|
|
1206
|
+
toast.show({
|
|
1207
|
+
variant: "warning",
|
|
1208
|
+
message: `Trial ends in ${daysLeft} day${daysLeft === 1 ? "" : "s"} — all features enabled`,
|
|
1209
|
+
duration: 6000,
|
|
1210
|
+
})
|
|
1211
|
+
} else {
|
|
1212
|
+
toast.show({
|
|
1213
|
+
variant: "info",
|
|
1214
|
+
message: `Trial active — all features enabled (${daysLeft} days remaining)`,
|
|
1215
|
+
duration: 4000,
|
|
1216
|
+
})
|
|
1217
|
+
}
|
|
1218
|
+
} else if (subStatus === "past_due") {
|
|
1219
|
+
toast.show({
|
|
1220
|
+
variant: "error",
|
|
1221
|
+
message: "Trial ended — visit portal.snow-flow.dev/portal/billing to activate features",
|
|
1222
|
+
duration: 8000,
|
|
1223
|
+
})
|
|
1224
|
+
} else if (subStatus === "active" && featureCount > 0) {
|
|
1225
|
+
toast.show({
|
|
1226
|
+
variant: "info",
|
|
1227
|
+
message: `Enterprise connected — ${featureCount} feature${featureCount === 1 ? "" : "s"} enabled`,
|
|
1228
|
+
duration: 4000,
|
|
1229
|
+
})
|
|
1230
|
+
}
|
|
1231
|
+
} catch {
|
|
1232
|
+
// Non-critical, skip toast on error
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1188
1235
|
dialog.clear()
|
|
1189
1236
|
} catch (e) {
|
|
1190
1237
|
toast.show({ variant: "error", message: e instanceof Error ? e.message : "Verification failed" })
|
|
@@ -393,4 +393,45 @@ export function registerEnterpriseCommands(program: Command): void {
|
|
|
393
393
|
});
|
|
394
394
|
}
|
|
395
395
|
|
|
396
|
+
/**
|
|
397
|
+
* Get subscription status and features from the portal auth store.
|
|
398
|
+
* Falls back to the legacy ~/.snow-flow/auth.json if portal auth is not available.
|
|
399
|
+
*/
|
|
400
|
+
export async function getSubscriptionStatus(): Promise<{
|
|
401
|
+
status?: string;
|
|
402
|
+
trialEndsAt?: number;
|
|
403
|
+
features: string[];
|
|
404
|
+
} | null> {
|
|
405
|
+
// Try portal auth store first (new device auth flow)
|
|
406
|
+
try {
|
|
407
|
+
const { Auth } = await import('../../auth/index.js');
|
|
408
|
+
const enterprise = await Auth.get('enterprise');
|
|
409
|
+
if (enterprise?.type === 'enterprise') {
|
|
410
|
+
return {
|
|
411
|
+
status: enterprise.subscriptionStatus,
|
|
412
|
+
trialEndsAt: enterprise.trialEndsAt,
|
|
413
|
+
features: enterprise.features || [],
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
} catch {
|
|
417
|
+
// Fall through to legacy auth
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Fallback: legacy auth.json
|
|
421
|
+
const auth = await loadAuth();
|
|
422
|
+
if (auth?.customer) {
|
|
423
|
+
return {
|
|
424
|
+
features: auth.customer.features || [],
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
return null;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Check if a specific feature is enabled in the user's subscription.
|
|
432
|
+
*/
|
|
433
|
+
export function isFeatureEnabled(features: string[], feature: string): boolean {
|
|
434
|
+
return features.includes(feature);
|
|
435
|
+
}
|
|
436
|
+
|
|
396
437
|
export const ENTERPRISE_MCP_SERVER_URL = MCP_SERVER_URL;
|