prior-cli 1.2.3 → 1.2.5

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.
Files changed (3) hide show
  1. package/bin/prior.js +108 -18
  2. package/lib/api.js +11 -1
  3. package/package.json +1 -1
package/bin/prior.js CHANGED
@@ -14,6 +14,13 @@ const { renderMarkdown } = require('../lib/render');
14
14
  const { getToken, getUsername, saveAuth, clearAuth } = require('../lib/config');
15
15
  const { runAgent, CONFIRM_TOOLS } = require('../lib/agent');
16
16
 
17
+ function decodeToken(token) {
18
+ try {
19
+ const payload = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
20
+ return payload;
21
+ } catch { return {}; }
22
+ }
23
+
17
24
  // ── Theme ──────────────────────────────────────────────────────
18
25
  const THEME = '#9CE2D4';
19
26
  const c = {
@@ -490,6 +497,78 @@ async function doLoginFlow() {
490
497
  return username;
491
498
  }
492
499
 
500
+ // ── Organization ToS flow ──────────────────────────────────────
501
+ const ORG_TOS = `
502
+ PRIOR NETWORK — ORGANIZATION ACCOUNT TERMS OF SERVICE
503
+ ══════════════════════════════════════════════════════
504
+
505
+ By accepting, you agree to the following:
506
+
507
+ 1. USAGE LIMITS
508
+ Organization accounts receive up to 500,000 tokens per day.
509
+ Abuse, automated scraping, or intentional limit exhaustion
510
+ may result in immediate account suspension.
511
+
512
+ 2. ACCEPTABLE USE
513
+ You may use Prior AI for legitimate business, research, and
514
+ productivity purposes. You may not use it to generate harmful,
515
+ illegal, or malicious content.
516
+
517
+ 3. DATA & PRIVACY
518
+ Conversations may be logged for safety and abuse monitoring.
519
+ Do not share confidential credentials or personal data.
520
+
521
+ 4. ACCOUNTABILITY
522
+ Organization account holders are responsible for all activity
523
+ on their account. Sharing credentials with unauthorized users
524
+ is prohibited.
525
+
526
+ 5. TERMINATION
527
+ Prior Network reserves the right to revoke organization access
528
+ at any time for violations of these terms.
529
+
530
+ These terms are legally binding upon acceptance.
531
+ `;
532
+
533
+ async function checkOrgTos(rl) {
534
+ const token = getToken();
535
+ if (!token) return;
536
+ const payload = decodeToken(token);
537
+ if (payload.role !== 'organization') return;
538
+ if (payload.tos_accepted) return;
539
+
540
+ console.clear();
541
+ banner();
542
+ console.log(DIVIDER);
543
+ console.log(c.bold(' Organization Account — Terms of Service'));
544
+ console.log(DIVIDER);
545
+ console.log(c.muted(ORG_TOS));
546
+ console.log(DIVIDER);
547
+ console.log(c.warn(' You must accept these terms to use your Organization account.'));
548
+ console.log('');
549
+
550
+ const accepted = await askConfirmKey('I accept the Terms of Service', rl);
551
+ if (!accepted) {
552
+ console.log('');
553
+ console.log(c.err(' Terms not accepted. Exiting.'));
554
+ console.log('');
555
+ process.exit(0);
556
+ }
557
+
558
+ process.stdout.write(c.dim(' Saving acceptance…'));
559
+ try {
560
+ const result = await api.acceptTos();
561
+ if (result.token) saveAuth(result.token, getUsername());
562
+ clearLine();
563
+ console.log(c.ok(' ✓ Terms accepted. Welcome to Prior Organization.'));
564
+ console.log('');
565
+ } catch (err) {
566
+ clearLine();
567
+ console.log(c.err(` ✗ Could not save acceptance: ${err.message}`));
568
+ console.log('');
569
+ }
570
+ }
571
+
493
572
  // ── Interactive Chat ───────────────────────────────────────────
494
573
  async function startChat(opts = {}) {
495
574
  // If not logged in, prompt inline instead of erroring out
@@ -505,6 +584,25 @@ async function startChat(opts = {}) {
505
584
  }
506
585
 
507
586
  const user = getUsername();
587
+ const payload = decodeToken(getToken() || '');
588
+ const isOrg = payload.role === 'organization';
589
+
590
+ // ── Readline needed early for ToS prompt ─────────────────────
591
+ const rl = readline.createInterface({
592
+ input: process.stdin,
593
+ output: process.stdout,
594
+ terminal: true,
595
+ historySize: 100,
596
+ completer: line => {
597
+ const cmds = ['/help', '/clear', '/model ', '/tools', '/uncensored', '/censored', '/login', '/logout', '/exit'];
598
+ if (!line.startsWith('/')) return [[], line];
599
+ const hits = cmds.filter(cmd => cmd.startsWith(line));
600
+ return [hits, line];
601
+ },
602
+ });
603
+
604
+ // ToS check for org accounts (before showing the chat UI)
605
+ await checkOrgTos(rl);
508
606
 
509
607
  console.clear();
510
608
  banner();
@@ -513,12 +611,16 @@ async function startChat(opts = {}) {
513
611
  // Header row
514
612
  const modelLabel = opts.model || 'default';
515
613
  const cwdShort = process.cwd().replace(os.homedir(), '~');
614
+ const accountBadge = isOrg
615
+ ? c.brand(' ◈ Organization Account')
616
+ : c.muted(' ◈ Standard Account');
516
617
  console.log(
517
618
  c.brand(' Prior AI') +
518
619
  c.muted(' · ') +
519
620
  c.bold(`@${user}`) +
520
621
  c.muted(` · ${modelLabel}`)
521
622
  );
623
+ console.log(accountBadge);
522
624
  console.log(c.muted(` ${cwdShort}`));
523
625
  console.log(c.ok(' ◉') + c.muted(' Agent mode ') + c.dim('· file web shell image prior-network'));
524
626
 
@@ -533,19 +635,6 @@ async function startChat(opts = {}) {
533
635
  let currentModel = opts.model || null;
534
636
  let uncensored = opts.uncensored || false;
535
637
 
536
- const rl = readline.createInterface({
537
- input: process.stdin,
538
- output: process.stdout,
539
- terminal: true,
540
- historySize: 100,
541
- completer: line => {
542
- const cmds = ['/help', '/clear', '/model ', '/tools', '/uncensored', '/censored', '/login', '/logout', '/exit'];
543
- if (!line.startsWith('/')) return [[], line];
544
- const hits = cmds.filter(cmd => cmd.startsWith(line));
545
- return [hits, line];
546
- },
547
- });
548
-
549
638
  // ── Live slash-command suggestions ──────────────────────────
550
639
  let clearSuggestions = () => {};
551
640
 
@@ -581,14 +670,12 @@ async function startChat(opts = {}) {
581
670
  clearSuggestions();
582
671
  if (!matches.length) return;
583
672
  _suggCount = matches.length;
584
- process.stdout.write('\x1b[s'); // save cursor first (at end of typed input)
585
- // Print newlines to scroll terminal and guarantee room below the prompt
586
- process.stdout.write('\n'.repeat(matches.length));
587
- process.stdout.write(`\x1b[${matches.length}A`); // move cursor back up to prompt line
673
+ process.stdout.write('\x1b[s'); // save cursor at end of typed input
588
674
  for (const { cmd, desc } of matches) {
675
+ // \x1b[B = cursor down 1 (no scroll), \r = col 0, \x1b[2K = clear line
589
676
  process.stdout.write(`\x1b[B\r\x1b[2K${c.brand(' ' + cmd.padEnd(14))}${c.dim(desc)}`);
590
677
  }
591
- process.stdout.write('\x1b[u'); // restore cursor to end of typed input
678
+ process.stdout.write('\x1b[u'); // restore cursor to end of typed input
592
679
  }
593
680
 
594
681
  process.stdin.on('keypress', (ch, key) => {
@@ -857,7 +944,10 @@ Keep it under 350 words. Write prior.md now.`;
857
944
  const used = data.used ?? data.tokens_used ?? data.tokensUsed ?? data.totalTokens ?? 0;
858
945
  const limit = data.limit ?? data.token_limit ?? data.dailyLimit ?? null;
859
946
  const pct = limit ? Math.min(100, Math.round((used / limit) * 100)) : null;
947
+ const role = data.role || decodeToken(getToken() || '').role || 'user';
948
+ const acctLabel = role === 'organization' ? c.brand(' Organization Account') : c.muted(' Standard Account');
860
949
  console.log('');
950
+ console.log(acctLabel);
861
951
  if (pct !== null) {
862
952
  console.log(` ${progressBar(pct)}`);
863
953
  console.log(` ${c.bold(used.toLocaleString())} ${c.muted('/')} ${limit.toLocaleString()} tokens ${c.muted(`(${pct}%)`)}`);
package/lib/api.js CHANGED
@@ -191,8 +191,18 @@ async function search(query) {
191
191
  return data;
192
192
  }
193
193
 
194
+ async function acceptTos() {
195
+ const res = await fetch(`${BASE}/network/api/user/tos-accept`, {
196
+ method: 'POST',
197
+ headers: authHeaders(),
198
+ });
199
+ const data = await res.json();
200
+ if (!res.ok) throw new Error(data.error || 'Failed to accept ToS');
201
+ return data; // { ok, token, tos_accepted_at }
202
+ }
203
+
194
204
  module.exports = {
195
- login, infer,
205
+ login, infer, acceptTos,
196
206
  generate,
197
207
  generateImage, pollImageProgress, downloadImage,
198
208
  getModels, getChats, getUsage, getWeather, search,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prior-cli",
3
- "version": "1.2.3",
3
+ "version": "1.2.5",
4
4
  "description": "Prior Network AI — command-line interface",
5
5
  "bin": {
6
6
  "prior": "bin/prior.js"