pendingyou 0.20.1 → 0.22.0

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/args.js CHANGED
@@ -2,6 +2,7 @@ import { APP_IDS, APP_NAMES, DEFAULT_APP, isAppId } from "./apps/ids.js";
2
2
  export const DEFAULT_ORIGIN = 'https://www.pendingyou.com';
3
3
  export const DEFAULT_TIMEOUT_MS = 4 * 60 * 60 * 1000;
4
4
  const MAX_TIMEOUT_MS = 24 * 60 * 60 * 1000;
5
+ export const APP_SUBS = ['login', 'logout', 'status'];
5
6
  export const MACHINE_SUBS = ['status', 'attest', 'rotate'];
6
7
  export const HERDR_SUBS = [
7
8
  'report',
@@ -82,6 +83,7 @@ const COMMANDS = new Set([
82
83
  'presence',
83
84
  'herdr',
84
85
  'machine',
86
+ 'app',
85
87
  ]);
86
88
  const FLAGS = {
87
89
  help: {},
@@ -151,6 +153,15 @@ const FLAGS = {
151
153
  ensure: false,
152
154
  },
153
155
  machine: { origin: true, 'client-id': true, cnf: true, name: true, yes: false },
156
+ app: {
157
+ origin: true,
158
+ 'client-id': true,
159
+ scope: true,
160
+ name: true,
161
+ device: false,
162
+ browser: false,
163
+ 'no-browser': false,
164
+ },
154
165
  };
155
166
  const VALUE_OPTIONS = new Set([
156
167
  'origin',
@@ -167,6 +178,7 @@ const VALUE_OPTIONS = new Set([
167
178
  'at',
168
179
  'client-id',
169
180
  'cnf',
181
+ 'scope',
170
182
  ]);
171
183
  function splitCommand(argv) {
172
184
  let index = 0;
@@ -417,6 +429,8 @@ export function parseArgs(argv, env = {}) {
417
429
  return herdrCommand(origin, positional, flags, app);
418
430
  case 'machine':
419
431
  return machineCommand(origin, positional, flags, machine);
432
+ case 'app':
433
+ return appCommandOf(origin, positional, flags, machine, device);
420
434
  case 'init':
421
435
  none();
422
436
  return {
@@ -569,6 +583,66 @@ function machineCommand(origin, positional, flags, machine) {
569
583
  ...machine(),
570
584
  };
571
585
  }
586
+ const APP_SCOPE_NAMES = [
587
+ 'cards:read',
588
+ 'cards:read:all',
589
+ 'cards:answer',
590
+ 'cards:reply',
591
+ 'cards:later',
592
+ 'cards:delegate',
593
+ 'assistants:read',
594
+ 'presence:desk',
595
+ ];
596
+ function appCommandOf(origin, positional, flags, machine, device) {
597
+ const [sub, app, ...extra] = positional;
598
+ if (sub === undefined)
599
+ throw new UsageError('app needs what to do, like: pendingyou app login herdr');
600
+ if (!APP_SUBS.includes(sub))
601
+ throw new UsageError(`app has no “${sub}”. Use ${APP_SUBS.join(', ')}.`);
602
+ if (extra.length)
603
+ throw new UsageError(`app ${sub} takes one app, not “${extra[0]}”.`);
604
+ const allowed = {
605
+ login: ['client-id', 'scope', 'name', 'device', 'browser', 'no-browser'],
606
+ logout: [],
607
+ status: [],
608
+ };
609
+ for (const key of flags.keys())
610
+ if (key !== 'origin' && !allowed[sub].includes(key))
611
+ throw new UsageError(`app ${sub} has no --${key} option.`);
612
+ if (app !== undefined && !/^[a-z0-9][a-z0-9-]{0,39}$/.test(app))
613
+ throw new UsageError(`“${app}” isn’t an app’s name here: lower-case letters, digits and dashes.`);
614
+ if (app === undefined && sub !== 'status')
615
+ throw new UsageError(`app ${sub} needs the app, like: pendingyou app ${sub} herdr`);
616
+ const command = {
617
+ name: 'app',
618
+ origin,
619
+ sub: sub,
620
+ ...(app ? { app } : {}),
621
+ device: null,
622
+ browser: true,
623
+ };
624
+ if (sub !== 'login')
625
+ return command;
626
+ const clientId = flags.get('client-id');
627
+ if (clientId !== undefined && (typeof clientId !== 'string' || !CLIENT_ID.test(clientId)))
628
+ throw new UsageError('--client-id needs the client the app signs in with.');
629
+ const scope = flags.get('scope');
630
+ let scopes;
631
+ if (typeof scope === 'string') {
632
+ scopes = [...new Set(scope.split(/[\s,]+/).filter(Boolean))];
633
+ const unknown = scopes.find((each) => !APP_SCOPE_NAMES.includes(each));
634
+ if (unknown || scopes.length === 0)
635
+ throw new UsageError(`--scope takes the person API’s scopes: ${APP_SCOPE_NAMES.join(', ')}.`);
636
+ }
637
+ return {
638
+ ...command,
639
+ ...(typeof clientId === 'string' ? { clientId } : {}),
640
+ ...(scopes ? { scopes } : {}),
641
+ ...machine(),
642
+ device: device(),
643
+ browser: !flags.has('no-browser'),
644
+ };
645
+ }
572
646
  export const USAGE = `pendingyou: Pending You for your coding agents (Claude Code, Codex, OpenCode and Pi)
573
647
 
574
648
  npx -y pendingyou@latest init
@@ -602,6 +676,10 @@ export const USAGE = `pendingyou: Pending You for your coding agents (Claude Cod
602
676
  never leaves the computer): whether Pending You knows each agent's
603
677
  connection by it, a proof of it for an app's own sign-in
604
678
  (--client-id, --cnf), or a new key (--yes: without asking)
679
+ npx pendingyou app login herdr | logout herdr | status
680
+ Sign in an app that answers your cards when you press a key in it (the
681
+ Pending You plugin for Herdr), out again, or what each may do. This
682
+ command line never answers: the app does, with its own sign-in and key
605
683
 
606
684
  Apps (for --app): ${APP_IDS.map((app) => `${app} (${APP_NAMES[app]})`).join(', ')}.
607
685