neoagent 3.0.1-beta.2 → 3.0.1-beta.20
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/.env.example +19 -0
- package/README.md +16 -0
- package/docs/benchmarking.md +102 -0
- package/docs/billing.md +224 -0
- package/docs/configuration.md +22 -0
- package/docs/index.md +1 -0
- package/flutter_app/lib/main.dart +4 -1
- package/flutter_app/lib/main_app_shell.dart +316 -0
- package/flutter_app/lib/main_billing.dart +1465 -0
- package/flutter_app/lib/main_chat.dart +1568 -231
- package/flutter_app/lib/main_controller.dart +263 -26
- package/flutter_app/lib/main_devices.dart +1 -1
- package/flutter_app/lib/main_install.dart +1147 -0
- package/flutter_app/lib/main_navigation.dart +12 -0
- package/flutter_app/lib/main_operations.dart +134 -9
- package/flutter_app/lib/main_settings.dart +148 -52
- package/flutter_app/lib/main_shared.dart +1 -0
- package/flutter_app/lib/src/backend_client.dart +69 -1
- package/landing/index.html +2 -2
- package/lib/manager.js +156 -0
- package/lib/schema_migrations.js +84 -0
- package/package.json +10 -4
- package/server/admin/access.js +12 -7
- package/server/admin/admin.css +78 -0
- package/server/admin/admin.js +511 -23
- package/server/admin/billing.js +415 -0
- package/server/admin/index.html +120 -13
- package/server/admin/users.js +15 -15
- package/server/db/database.js +13 -21
- package/server/db/sessions_db.js +8 -0
- package/server/http/middleware.js +4 -4
- package/server/http/routes.js +9 -0
- package/server/http/static.js +4 -2
- package/server/middleware/requireBilling.js +12 -0
- package/server/public/.last_build_id +1 -1
- package/server/public/assets/fonts/MaterialIcons-Regular.otf +0 -0
- package/server/public/flutter_bootstrap.js +1 -1
- package/server/public/main.dart.js +89120 -85431
- package/server/routes/admin.js +524 -29
- package/server/routes/agents.js +203 -21
- package/server/routes/billing.js +127 -0
- package/server/routes/billing_webhook.js +43 -0
- package/server/routes/memory.js +1 -4
- package/server/routes/settings.js +1 -2
- package/server/routes/skills.js +1 -1
- package/server/routes/triggers.js +2 -2
- package/server/services/account/sessions.js +1 -9
- package/server/services/ai/loop/agent_engine_core.js +42 -0
- package/server/services/ai/loop/blank_recovery.js +36 -0
- package/server/services/ai/loop/completion_judge.js +42 -0
- package/server/services/ai/loop/conversation_loop.js +248 -34
- package/server/services/ai/loop/progress_monitor.js +6 -6
- package/server/services/ai/loopPolicy.js +37 -44
- package/server/services/ai/messagingFallback.js +25 -1
- package/server/services/ai/models.js +18 -0
- package/server/services/ai/preModelCompaction.js +25 -5
- package/server/services/ai/rate_limits.js +28 -4
- package/server/services/ai/systemPrompt.js +23 -5
- package/server/services/ai/taskAnalysis.js +2 -0
- package/server/services/ai/tools.js +231 -20
- package/server/services/billing/billing_email.js +106 -0
- package/server/services/billing/config.js +17 -0
- package/server/services/billing/plans.js +121 -0
- package/server/services/billing/stripe_client.js +21 -0
- package/server/services/billing/subscriptions.js +462 -0
- package/server/services/billing/trial_guard.js +111 -0
- package/server/services/browser/contentExtractor.js +629 -0
- package/server/services/browser/controller.js +4 -8
- package/server/services/desktop/gateway.js +7 -4
- package/server/services/integrations/google/calendar.js +30 -2
- package/server/services/integrations/secrets.js +7 -4
- package/server/services/manager.js +11 -0
- package/server/services/messaging/automation.js +1 -1
- package/server/services/messaging/telnyx.js +12 -11
- package/server/services/messaging/whatsapp.js +1 -1
- package/server/services/recordings/manager.js +13 -7
- package/server/services/runtime/backends/local-vm.js +40 -22
- package/server/services/tasks/runtime.js +103 -15
- package/server/services/tasks/schedule_utils.js +5 -5
- package/server/services/voice/runtimeManager.js +19 -10
- package/server/services/wearable/gateway.js +8 -5
- package/server/services/websocket.js +26 -8
- package/server/services/workspace/manager.js +37 -3
package/lib/manager.js
CHANGED
|
@@ -2000,6 +2000,152 @@ function cmdVersion() {
|
|
|
2000
2000
|
console.log(currentInstalledVersionLabel());
|
|
2001
2001
|
}
|
|
2002
2002
|
|
|
2003
|
+
async function cmdBilling(args = []) {
|
|
2004
|
+
const sub = (args[0] || 'status').toLowerCase();
|
|
2005
|
+
|
|
2006
|
+
if (sub === '--help' || sub === '-h' || sub === 'help') {
|
|
2007
|
+
console.log('\nNeoAgent Billing');
|
|
2008
|
+
console.log('Usage: neoagent billing [subcommand]');
|
|
2009
|
+
console.log('');
|
|
2010
|
+
console.log('Subcommands:');
|
|
2011
|
+
console.log(' neoagent billing Show billing configuration status');
|
|
2012
|
+
console.log(' neoagent billing setup Interactive Stripe setup wizard');
|
|
2013
|
+
console.log(' neoagent billing enable Enable billing and restart');
|
|
2014
|
+
console.log(' neoagent billing disable Disable billing and restart');
|
|
2015
|
+
console.log('');
|
|
2016
|
+
return;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
if (sub === 'status') {
|
|
2020
|
+
cliBanner('Billing', 'configuration status');
|
|
2021
|
+
heading('Billing Status');
|
|
2022
|
+
const env = Object.fromEntries(parseEnv(readEnvFileRaw()).entries());
|
|
2023
|
+
const enabled = ['1', 'true', 'yes'].includes(String(env.NEOAGENT_BILLING_ENABLED || '').toLowerCase());
|
|
2024
|
+
const hasSecret = Boolean(env.STRIPE_SECRET_KEY);
|
|
2025
|
+
const hasPub = Boolean(env.STRIPE_PUBLISHABLE_KEY);
|
|
2026
|
+
const hasWebhook = Boolean(env.STRIPE_WEBHOOK_SECRET);
|
|
2027
|
+
const trialDays = env.BILLING_TRIAL_DAYS || '14';
|
|
2028
|
+
|
|
2029
|
+
cliSection('Billing config');
|
|
2030
|
+
statusLine(enabled, 'enabled', enabled ? 'yes' : 'no', enabled ? '' : 'run: neoagent billing enable');
|
|
2031
|
+
statusLine(hasSecret, 'secret', hasSecret ? maskEnvValue('SECRET', env.STRIPE_SECRET_KEY) : 'not set', hasSecret ? '' : 'run: neoagent billing setup');
|
|
2032
|
+
statusLine(hasPub, 'public', hasPub ? maskEnvValue('KEY', env.STRIPE_PUBLISHABLE_KEY) : 'not set');
|
|
2033
|
+
statusLine(hasWebhook, 'webhook', hasWebhook ? 'configured' : 'not set');
|
|
2034
|
+
console.log('');
|
|
2035
|
+
cliSection('Trial');
|
|
2036
|
+
console.log(` trial days ${trialDays}`);
|
|
2037
|
+
|
|
2038
|
+
const port = loadEnvPort();
|
|
2039
|
+
const publicUrl = env.PUBLIC_URL || `http://localhost:${port}`;
|
|
2040
|
+
console.log('');
|
|
2041
|
+
cliSection('Webhook endpoint');
|
|
2042
|
+
console.log(` ${publicUrl}/api/billing/webhook`);
|
|
2043
|
+
console.log('');
|
|
2044
|
+
|
|
2045
|
+
if (!hasSecret || !hasPub) {
|
|
2046
|
+
logWarn('Stripe keys not configured. Run `neoagent billing setup` to get started.');
|
|
2047
|
+
} else if (!enabled) {
|
|
2048
|
+
logInfo('Billing is configured but not enabled. Run `neoagent billing enable` to activate.');
|
|
2049
|
+
} else {
|
|
2050
|
+
logOk('Billing is active. Manage plans in Admin › Billing.');
|
|
2051
|
+
}
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
|
|
2055
|
+
if (sub === 'enable') {
|
|
2056
|
+
heading('Enable Billing');
|
|
2057
|
+
upsertEnvValue('NEOAGENT_BILLING_ENABLED', 'true');
|
|
2058
|
+
logOk('Set NEOAGENT_BILLING_ENABLED=true');
|
|
2059
|
+
logInfo('Restarting NeoAgent to apply changes...');
|
|
2060
|
+
cmdRestart();
|
|
2061
|
+
return;
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
if (sub === 'disable') {
|
|
2065
|
+
heading('Disable Billing');
|
|
2066
|
+
upsertEnvValue('NEOAGENT_BILLING_ENABLED', 'false');
|
|
2067
|
+
logOk('Set NEOAGENT_BILLING_ENABLED=false');
|
|
2068
|
+
logInfo('Restarting NeoAgent to apply changes...');
|
|
2069
|
+
cmdRestart();
|
|
2070
|
+
return;
|
|
2071
|
+
}
|
|
2072
|
+
|
|
2073
|
+
if (sub === 'setup') {
|
|
2074
|
+
cliBanner('Billing Setup', 'Stripe configuration');
|
|
2075
|
+
heading('Billing Setup');
|
|
2076
|
+
ensureRuntimeDirs();
|
|
2077
|
+
|
|
2078
|
+
const current = Object.fromEntries(parseEnv(readEnvFileRaw()).entries());
|
|
2079
|
+
const port = loadEnvPort();
|
|
2080
|
+
const publicUrl = current.PUBLIC_URL || `http://localhost:${port}`;
|
|
2081
|
+
|
|
2082
|
+
logInfo('Press Enter to keep the current value shown in brackets.');
|
|
2083
|
+
logInfo(`Webhook endpoint: ${publicUrl}/api/billing/webhook`);
|
|
2084
|
+
console.log('');
|
|
2085
|
+
|
|
2086
|
+
heading('Stripe API keys');
|
|
2087
|
+
logInfo('Find these in your Stripe dashboard: https://dashboard.stripe.com/apikeys');
|
|
2088
|
+
const secretKey = await askSecret('Stripe secret key (sk_live_... or sk_test_...)', current.STRIPE_SECRET_KEY || '');
|
|
2089
|
+
const publishableKey = await askSecret('Stripe publishable key (pk_live_... or pk_test_...)', current.STRIPE_PUBLISHABLE_KEY || '');
|
|
2090
|
+
|
|
2091
|
+
if (secretKey && !secretKey.startsWith('sk_')) {
|
|
2092
|
+
logWarn('Secret key does not start with "sk_" — double-check the value.');
|
|
2093
|
+
}
|
|
2094
|
+
if (publishableKey && !publishableKey.startsWith('pk_')) {
|
|
2095
|
+
logWarn('Publishable key does not start with "pk_" — double-check the value.');
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
heading('Webhook');
|
|
2099
|
+
logInfo(`Register this endpoint in Stripe: ${publicUrl}/api/billing/webhook`);
|
|
2100
|
+
logInfo('Required events: customer.subscription.*, invoice.payment_succeeded, invoice.payment_failed');
|
|
2101
|
+
const webhookSecret = await askSecret('Stripe webhook signing secret (whsec_...)', current.STRIPE_WEBHOOK_SECRET || '');
|
|
2102
|
+
|
|
2103
|
+
if (webhookSecret && !webhookSecret.startsWith('whsec_')) {
|
|
2104
|
+
logWarn('Webhook secret does not start with "whsec_" — double-check the value.');
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
heading('Trial');
|
|
2108
|
+
const trialDaysRaw = await ask('Free trial length in days (0 to disable)', current.BILLING_TRIAL_DAYS || '14');
|
|
2109
|
+
const trialDays = Number(trialDaysRaw);
|
|
2110
|
+
if (!Number.isInteger(trialDays) || trialDays < 0) {
|
|
2111
|
+
throw new Error(`Invalid trial length "${trialDaysRaw}". Must be a non-negative integer.`);
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
if (secretKey) upsertEnvValue('STRIPE_SECRET_KEY', secretKey);
|
|
2115
|
+
if (publishableKey) upsertEnvValue('STRIPE_PUBLISHABLE_KEY', publishableKey);
|
|
2116
|
+
if (webhookSecret) upsertEnvValue('STRIPE_WEBHOOK_SECRET', webhookSecret);
|
|
2117
|
+
upsertEnvValue('BILLING_TRIAL_DAYS', String(trialDays));
|
|
2118
|
+
|
|
2119
|
+
logOk('Stripe credentials saved to .env');
|
|
2120
|
+
|
|
2121
|
+
const isAlreadyEnabled = ['1', 'true', 'yes'].includes(String(current.NEOAGENT_BILLING_ENABLED || '').toLowerCase());
|
|
2122
|
+
let enableNow = isAlreadyEnabled;
|
|
2123
|
+
if (!isAlreadyEnabled) {
|
|
2124
|
+
const enableAnswer = await ask('Enable billing now? (y/N)', 'N');
|
|
2125
|
+
enableNow = enableAnswer.toLowerCase() === 'y' || enableAnswer.toLowerCase() === 'yes';
|
|
2126
|
+
}
|
|
2127
|
+
|
|
2128
|
+
if (enableNow) {
|
|
2129
|
+
upsertEnvValue('NEOAGENT_BILLING_ENABLED', 'true');
|
|
2130
|
+
logOk('Billing enabled');
|
|
2131
|
+
logInfo('Restarting NeoAgent to apply credentials...');
|
|
2132
|
+
cmdRestart();
|
|
2133
|
+
} else {
|
|
2134
|
+
logInfo('Billing is not yet enabled. Run `neoagent billing enable` when ready.');
|
|
2135
|
+
}
|
|
2136
|
+
|
|
2137
|
+
console.log('');
|
|
2138
|
+
heading('Next steps');
|
|
2139
|
+
logInfo('1. Verify the webhook endpoint is reachable from Stripe');
|
|
2140
|
+
logInfo('2. Create subscription plans in Admin › Billing › Plans');
|
|
2141
|
+
logInfo('3. Add a free plan (price = 0) for users without a paid subscription');
|
|
2142
|
+
logInfo(' See: neoagent billing status');
|
|
2143
|
+
return;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
throw new Error(`Unknown billing subcommand: ${sub}. Run "neoagent billing --help" for usage.`);
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2003
2149
|
function printHelp() {
|
|
2004
2150
|
const c = COLORS;
|
|
2005
2151
|
const W = 38;
|
|
@@ -2047,6 +2193,13 @@ function printHelp() {
|
|
|
2047
2193
|
row('admin', 'Show admin dashboard URL and credentials');
|
|
2048
2194
|
console.log('');
|
|
2049
2195
|
|
|
2196
|
+
cliSection('Billing');
|
|
2197
|
+
row('billing', 'Show billing configuration status');
|
|
2198
|
+
row('billing setup', 'Interactive Stripe setup wizard');
|
|
2199
|
+
row('billing enable', 'Enable billing and restart');
|
|
2200
|
+
row('billing disable', 'Disable billing and restart');
|
|
2201
|
+
console.log('');
|
|
2202
|
+
|
|
2050
2203
|
cliSection('Maintenance');
|
|
2051
2204
|
row('migrate', 'Migrate from another agent installation');
|
|
2052
2205
|
row('migrate dry-run', 'Preview what would be migrated');
|
|
@@ -2106,6 +2259,9 @@ async function runCLI(argv) {
|
|
|
2106
2259
|
case 'login':
|
|
2107
2260
|
await cmdLogin(argv.slice(1));
|
|
2108
2261
|
break;
|
|
2262
|
+
case 'billing':
|
|
2263
|
+
await cmdBilling(argv.slice(1));
|
|
2264
|
+
break;
|
|
2109
2265
|
case 'admin': {
|
|
2110
2266
|
cliBanner('Admin Dashboard', 'credentials');
|
|
2111
2267
|
const adminCreds = readAdminCredentials();
|
package/lib/schema_migrations.js
CHANGED
|
@@ -458,6 +458,88 @@ function migrateToolPoliciesAllowAlways(db) {
|
|
|
458
458
|
`);
|
|
459
459
|
}
|
|
460
460
|
|
|
461
|
+
function migrateBilling(db) {
|
|
462
|
+
db.exec(`
|
|
463
|
+
CREATE TABLE IF NOT EXISTS billing_plans (
|
|
464
|
+
id TEXT PRIMARY KEY,
|
|
465
|
+
name TEXT NOT NULL,
|
|
466
|
+
description TEXT DEFAULT '',
|
|
467
|
+
price_cents INTEGER NOT NULL DEFAULT 0,
|
|
468
|
+
currency TEXT NOT NULL DEFAULT 'usd',
|
|
469
|
+
interval TEXT DEFAULT 'month',
|
|
470
|
+
stripe_price_id TEXT,
|
|
471
|
+
token_limit_4h INTEGER,
|
|
472
|
+
token_limit_weekly INTEGER,
|
|
473
|
+
allowed_models_json TEXT DEFAULT '[]',
|
|
474
|
+
features_json TEXT DEFAULT '[]',
|
|
475
|
+
is_active INTEGER DEFAULT 1,
|
|
476
|
+
sort_order INTEGER DEFAULT 0,
|
|
477
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
478
|
+
updated_at TEXT DEFAULT (datetime('now'))
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
CREATE TABLE IF NOT EXISTS billing_customers (
|
|
482
|
+
user_id INTEGER PRIMARY KEY,
|
|
483
|
+
stripe_customer_id TEXT UNIQUE,
|
|
484
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
485
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
486
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
CREATE TABLE IF NOT EXISTS user_subscriptions (
|
|
490
|
+
id TEXT PRIMARY KEY,
|
|
491
|
+
user_id INTEGER NOT NULL,
|
|
492
|
+
plan_id TEXT NOT NULL,
|
|
493
|
+
stripe_subscription_id TEXT UNIQUE,
|
|
494
|
+
status TEXT NOT NULL,
|
|
495
|
+
trial_ends_at TEXT,
|
|
496
|
+
current_period_start TEXT,
|
|
497
|
+
current_period_end TEXT,
|
|
498
|
+
cancel_at_period_end INTEGER DEFAULT 0,
|
|
499
|
+
canceled_at TEXT,
|
|
500
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
501
|
+
updated_at TEXT DEFAULT (datetime('now')),
|
|
502
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
|
503
|
+
FOREIGN KEY (plan_id) REFERENCES billing_plans(id)
|
|
504
|
+
);
|
|
505
|
+
|
|
506
|
+
CREATE TABLE IF NOT EXISTS subscription_events (
|
|
507
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
508
|
+
user_id INTEGER NOT NULL,
|
|
509
|
+
subscription_id TEXT,
|
|
510
|
+
event_type TEXT NOT NULL,
|
|
511
|
+
stripe_event_id TEXT UNIQUE,
|
|
512
|
+
payload_json TEXT DEFAULT '{}',
|
|
513
|
+
created_at TEXT DEFAULT (datetime('now')),
|
|
514
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
|
515
|
+
);
|
|
516
|
+
|
|
517
|
+
CREATE TABLE IF NOT EXISTS trial_fingerprints (
|
|
518
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
519
|
+
fingerprint_hash TEXT NOT NULL,
|
|
520
|
+
fingerprint_type TEXT NOT NULL,
|
|
521
|
+
user_id INTEGER,
|
|
522
|
+
used_at TEXT DEFAULT (datetime('now')),
|
|
523
|
+
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL
|
|
524
|
+
);
|
|
525
|
+
|
|
526
|
+
CREATE INDEX IF NOT EXISTS idx_billing_customers_stripe
|
|
527
|
+
ON billing_customers(stripe_customer_id);
|
|
528
|
+
|
|
529
|
+
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_user
|
|
530
|
+
ON user_subscriptions(user_id, status, updated_at DESC);
|
|
531
|
+
|
|
532
|
+
CREATE INDEX IF NOT EXISTS idx_user_subscriptions_stripe
|
|
533
|
+
ON user_subscriptions(stripe_subscription_id);
|
|
534
|
+
|
|
535
|
+
CREATE INDEX IF NOT EXISTS idx_subscription_events_stripe
|
|
536
|
+
ON subscription_events(stripe_event_id);
|
|
537
|
+
|
|
538
|
+
CREATE INDEX IF NOT EXISTS idx_trial_fingerprints_hash
|
|
539
|
+
ON trial_fingerprints(fingerprint_hash, fingerprint_type);
|
|
540
|
+
`);
|
|
541
|
+
}
|
|
542
|
+
|
|
461
543
|
function runSchemaMigrations(db) {
|
|
462
544
|
migrateMemoryEmbeddingIndex(db);
|
|
463
545
|
migrateMemoryProvenance(db);
|
|
@@ -469,6 +551,7 @@ function runSchemaMigrations(db) {
|
|
|
469
551
|
migrateToolPermissions(db);
|
|
470
552
|
migrateApprovalPersistence(db);
|
|
471
553
|
migrateToolPoliciesAllowAlways(db);
|
|
554
|
+
migrateBilling(db);
|
|
472
555
|
}
|
|
473
556
|
|
|
474
557
|
module.exports = {
|
|
@@ -482,5 +565,6 @@ module.exports = {
|
|
|
482
565
|
migrateToolPermissions,
|
|
483
566
|
migrateApprovalPersistence,
|
|
484
567
|
migrateToolPoliciesAllowAlways,
|
|
568
|
+
migrateBilling,
|
|
485
569
|
runSchemaMigrations,
|
|
486
570
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "neoagent",
|
|
3
|
-
"version": "3.0.1-beta.
|
|
3
|
+
"version": "3.0.1-beta.20",
|
|
4
4
|
"description": "Self-hosted AI agent for long-running tasks, automation, messaging, device control, and local memory",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"main": "server/index.js",
|
|
@@ -51,10 +51,14 @@
|
|
|
51
51
|
"flutter:test": "cd flutter_app && flutter test ../test/flutter/unit ../test/flutter/widget",
|
|
52
52
|
"flutter:test:unit": "cd flutter_app && flutter test ../test/flutter/unit",
|
|
53
53
|
"flutter:test:widget": "cd flutter_app && flutter test ../test/flutter/widget",
|
|
54
|
+
"benchmark:setup": "node benchmark/cli.js setup",
|
|
55
|
+
"benchmark:run": "node benchmark/cli.js run",
|
|
56
|
+
"benchmark:report": "node benchmark/cli.js report",
|
|
54
57
|
"benchmark:tokens": "node scripts/benchmark-token-cost.js",
|
|
55
58
|
"benchmark:memory": "node scripts/benchmark-memory.js",
|
|
56
59
|
"benchmark:memorybench:install": "node scripts/install-memorybench-provider.js",
|
|
57
|
-
"release": "npx semantic-release"
|
|
60
|
+
"release": "npx semantic-release",
|
|
61
|
+
"audit:ci": "npm audit --omit=dev --audit-level=high"
|
|
58
62
|
},
|
|
59
63
|
"repository": {
|
|
60
64
|
"type": "git",
|
|
@@ -99,11 +103,12 @@
|
|
|
99
103
|
"remotion": "^4.0.459",
|
|
100
104
|
"sharp": "^0.34.5",
|
|
101
105
|
"socket.io": "^4.8.1",
|
|
106
|
+
"stripe": "^22.2.1",
|
|
102
107
|
"telegraf": "^4.16.3",
|
|
103
108
|
"telnyx": "^5.51.0",
|
|
104
109
|
"tesseract.js": "^7.0.0",
|
|
105
110
|
"uuid": "^11.1.0",
|
|
106
|
-
"ws": "^8.
|
|
111
|
+
"ws": "^8.21.0"
|
|
107
112
|
},
|
|
108
113
|
"overrides": {
|
|
109
114
|
"axios": "^1.15.2",
|
|
@@ -113,7 +118,8 @@
|
|
|
113
118
|
"protobufjs": "^7.5.5",
|
|
114
119
|
"serialize-javascript": "^7.0.5",
|
|
115
120
|
"undici": "^6.24.0",
|
|
116
|
-
"webpackbar": "^7.0.0"
|
|
121
|
+
"webpackbar": "^7.0.0",
|
|
122
|
+
"ws": "^8.21.0"
|
|
117
123
|
},
|
|
118
124
|
"devDependencies": {
|
|
119
125
|
"@docusaurus/core": "3.10.0",
|
package/server/admin/access.js
CHANGED
|
@@ -113,12 +113,12 @@ async function setSignup(enabled) {
|
|
|
113
113
|
}
|
|
114
114
|
|
|
115
115
|
async function rotateApiKey(btn) {
|
|
116
|
-
if (!
|
|
117
|
-
'Rotate admin API key
|
|
118
|
-
'The current key will stop working immediately
|
|
119
|
-
'
|
|
120
|
-
|
|
121
|
-
)) return;
|
|
116
|
+
if (!await showConfirmModal({
|
|
117
|
+
title: 'Rotate admin API key?',
|
|
118
|
+
body: 'The current key will stop working immediately. Any scripts using it must be updated.<br><br>The new key will be shown once — copy it before leaving.',
|
|
119
|
+
confirmLabel: 'Rotate Key',
|
|
120
|
+
confirmClass: 'btn-danger',
|
|
121
|
+
})) return;
|
|
122
122
|
btn.disabled = true;
|
|
123
123
|
btn.textContent = 'Rotating…';
|
|
124
124
|
try {
|
|
@@ -140,7 +140,12 @@ async function rotateApiKey(btn) {
|
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
async function revokeApiKey(btn) {
|
|
143
|
-
if (!
|
|
143
|
+
if (!await showConfirmModal({
|
|
144
|
+
title: 'Revoke admin API key?',
|
|
145
|
+
body: 'All programmatic access using this key will stop immediately.',
|
|
146
|
+
confirmLabel: 'Revoke Key',
|
|
147
|
+
confirmClass: 'btn-danger',
|
|
148
|
+
})) return;
|
|
144
149
|
btn.disabled = true;
|
|
145
150
|
btn.textContent = 'Revoking…';
|
|
146
151
|
_revealedKey = null;
|
package/server/admin/admin.css
CHANGED
|
@@ -318,3 +318,81 @@ button:disabled,
|
|
|
318
318
|
border: 1px solid rgba(116, 192, 124, 0.25);
|
|
319
319
|
color: var(--success);
|
|
320
320
|
}
|
|
321
|
+
|
|
322
|
+
/* ── Form helpers (used in dynamic modals) ───────────────────────────────── */
|
|
323
|
+
.form-label {
|
|
324
|
+
display: block;
|
|
325
|
+
font-size: 11px;
|
|
326
|
+
font-weight: 600;
|
|
327
|
+
letter-spacing: 0.04em;
|
|
328
|
+
color: var(--text-muted);
|
|
329
|
+
text-transform: uppercase;
|
|
330
|
+
margin-bottom: 6px;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
.form-label small {
|
|
334
|
+
font-size: 10px;
|
|
335
|
+
font-weight: 400;
|
|
336
|
+
text-transform: none;
|
|
337
|
+
letter-spacing: 0;
|
|
338
|
+
opacity: 0.75;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
.form-input {
|
|
342
|
+
width: 100%;
|
|
343
|
+
background: var(--bg-input);
|
|
344
|
+
border: 1px solid var(--border-light);
|
|
345
|
+
border-radius: var(--radius-sm);
|
|
346
|
+
padding: 9px 12px;
|
|
347
|
+
color: var(--text);
|
|
348
|
+
font-family: var(--font-sans);
|
|
349
|
+
font-size: 13px;
|
|
350
|
+
outline: none;
|
|
351
|
+
transition: border-color 0.15s;
|
|
352
|
+
-webkit-appearance: none;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
.form-input:focus {
|
|
356
|
+
border-color: var(--accent);
|
|
357
|
+
box-shadow: 0 0 0 3px var(--accent-muted);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.form-input:disabled {
|
|
361
|
+
opacity: 0.5;
|
|
362
|
+
cursor: default;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/* ── Small button variant ────────────────────────────────────────────────── */
|
|
366
|
+
.btn-sm {
|
|
367
|
+
padding: 5px 10px;
|
|
368
|
+
font-size: 12px;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/* ── Generic data table (billing, etc.) ──────────────────────────────────── */
|
|
372
|
+
.data-table {
|
|
373
|
+
width: 100%;
|
|
374
|
+
border-collapse: collapse;
|
|
375
|
+
font-size: 13px;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.data-table th {
|
|
379
|
+
text-align: left;
|
|
380
|
+
font-size: 10px;
|
|
381
|
+
font-weight: 600;
|
|
382
|
+
text-transform: uppercase;
|
|
383
|
+
letter-spacing: 0.07em;
|
|
384
|
+
color: var(--text-muted);
|
|
385
|
+
padding: 6px 10px;
|
|
386
|
+
border-bottom: 1px solid var(--border);
|
|
387
|
+
white-space: nowrap;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
.data-table td {
|
|
391
|
+
padding: 10px 10px;
|
|
392
|
+
border-bottom: 1px solid var(--border);
|
|
393
|
+
color: var(--text-secondary);
|
|
394
|
+
vertical-align: middle;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.data-table tr:last-child td { border-bottom: none; }
|
|
398
|
+
.data-table tr:hover td { background: var(--row-hover); }
|