@positronic/cli 0.0.73 → 0.0.75

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 (55) hide show
  1. package/dist/src/cli.js +93 -110
  2. package/dist/src/commands/auth.js +8 -34
  3. package/dist/src/commands/schedule.js +3 -2
  4. package/dist/src/commands/users.js +15 -14
  5. package/dist/src/components/auth-login.js +1 -1
  6. package/dist/src/components/project-auth-setup.js +6 -3
  7. package/dist/src/components/project-create.js +8 -2
  8. package/dist/src/components/schedule-create.js +9 -3
  9. package/dist/src/components/schedule-list.js +1 -1
  10. package/dist/src/components/store-explorer.js +3 -5
  11. package/dist/src/components/users-create.js +2 -4
  12. package/dist/src/components/users-delete.js +5 -5
  13. package/dist/src/components/users-keys-add.js +71 -17
  14. package/dist/src/components/users-keys-list.js +5 -5
  15. package/dist/src/components/users-keys-remove.js +5 -5
  16. package/dist/src/components/users-list.js +2 -11
  17. package/dist/src/components/whoami.js +71 -0
  18. package/dist/src/hooks/useApi.js +2 -2
  19. package/dist/src/lib/jwt-auth.js +1 -1
  20. package/dist/src/lib/ssh-key-utils.js +17 -0
  21. package/dist/types/cli.d.ts.map +1 -1
  22. package/dist/types/commands/auth.d.ts +5 -18
  23. package/dist/types/commands/auth.d.ts.map +1 -1
  24. package/dist/types/commands/schedule.d.ts +2 -1
  25. package/dist/types/commands/schedule.d.ts.map +1 -1
  26. package/dist/types/commands/users.d.ts +13 -12
  27. package/dist/types/commands/users.d.ts.map +1 -1
  28. package/dist/types/components/project-auth-setup.d.ts.map +1 -1
  29. package/dist/types/components/project-create.d.ts.map +1 -1
  30. package/dist/types/components/schedule-create.d.ts +2 -1
  31. package/dist/types/components/schedule-create.d.ts.map +1 -1
  32. package/dist/types/components/users-create.d.ts.map +1 -1
  33. package/dist/types/components/users-delete.d.ts +2 -2
  34. package/dist/types/components/users-delete.d.ts.map +1 -1
  35. package/dist/types/components/users-keys-add.d.ts +4 -3
  36. package/dist/types/components/users-keys-add.d.ts.map +1 -1
  37. package/dist/types/components/users-keys-list.d.ts +2 -2
  38. package/dist/types/components/users-keys-list.d.ts.map +1 -1
  39. package/dist/types/components/users-keys-remove.d.ts +2 -2
  40. package/dist/types/components/users-keys-remove.d.ts.map +1 -1
  41. package/dist/types/components/users-list.d.ts.map +1 -1
  42. package/dist/types/components/whoami.d.ts +8 -0
  43. package/dist/types/components/whoami.d.ts.map +1 -0
  44. package/dist/types/lib/ssh-key-utils.d.ts +5 -0
  45. package/dist/types/lib/ssh-key-utils.d.ts.map +1 -1
  46. package/package.json +4 -4
  47. package/dist/src/components/auth-format-jwk-key.js +0 -457
  48. package/dist/src/components/auth-list.js +0 -66
  49. package/dist/src/components/auth-status.js +0 -113
  50. package/dist/types/components/auth-format-jwk-key.d.ts +0 -6
  51. package/dist/types/components/auth-format-jwk-key.d.ts.map +0 -1
  52. package/dist/types/components/auth-list.d.ts +0 -8
  53. package/dist/types/components/auth-list.d.ts.map +0 -1
  54. package/dist/types/components/auth-status.d.ts +0 -8
  55. package/dist/types/components/auth-status.d.ts.map +0 -1
package/dist/src/cli.js CHANGED
@@ -781,7 +781,13 @@ export function buildCli(options) {
781
781
  describe: 'Cron expression for the schedule (e.g., "0 3 * * *" for daily at 3am)',
782
782
  type: 'string',
783
783
  demandOption: true
784
- }).example('$0 schedule create my-brain "0 3 * * *"', 'Run my-brain daily at 3am').example('$0 schedule c my-brain "0 3 * * *"', 'Run my-brain daily at 3am (shorthand)').example('$0 schedule create data-sync "*/30 * * * *"', 'Run data-sync every 30 minutes').example('$0 schedule create weekly-report "0 9 * * 1"', 'Run weekly-report every Monday at 9am');
784
+ }).option('options', {
785
+ describe: 'Options to pass to the brain on each run (key=value format)',
786
+ type: 'array',
787
+ alias: 'o',
788
+ string: true,
789
+ coerce: parseKeyValueOptions
790
+ }).example('$0 schedule create my-brain "0 3 * * *"', 'Run my-brain daily at 3am').example('$0 schedule c my-brain "0 3 * * *"', 'Run my-brain daily at 3am (shorthand)').example('$0 schedule create data-sync "*/30 * * * *"', 'Run data-sync every 30 minutes').example('$0 schedule create weekly-report "0 9 * * 1"', 'Run weekly-report every Monday at 9am').example('$0 schedule create my-brain "0 8 * * 1" -o notify=sean,jim', 'Run with options passed to the brain');
785
791
  }, function(argv) {
786
792
  var element = scheduleCommand.create(argv);
787
793
  render(element);
@@ -891,9 +897,9 @@ export function buildCli(options) {
891
897
  }, function(argv) {
892
898
  var element = usersCommand.create(argv);
893
899
  render(element);
894
- }).command('delete <id>', 'Delete a user\n', function(yargsDelete) {
895
- return yargsDelete.positional('id', {
896
- describe: 'ID of the user to delete',
900
+ }).command('delete <name>', 'Delete a user\n', function(yargsDelete) {
901
+ return yargsDelete.positional('name', {
902
+ describe: 'Name of the user to delete',
897
903
  type: 'string',
898
904
  demandOption: true
899
905
  }).option('force', {
@@ -901,67 +907,63 @@ export function buildCli(options) {
901
907
  type: 'boolean',
902
908
  alias: 'f',
903
909
  default: false
904
- }).example('$0 users delete abc123', 'Delete a user').example('$0 users delete abc123 --force', 'Delete without confirmation');
910
+ }).example('$0 users delete admin', 'Delete a user').example('$0 users delete admin --force', 'Delete without confirmation');
905
911
  }, function(argv) {
906
912
  var element = usersCommand.delete(argv);
907
913
  render(element);
908
- }).command('keys', 'Manage SSH keys for users\n', function(yargsKeys) {
909
- return yargsKeys.command('list <user-id>', 'List keys for a user\n', function(yargsKeysList) {
910
- return yargsKeysList.positional('user-id', {
911
- describe: 'User ID',
912
- type: 'string',
913
- demandOption: true
914
- }).example('$0 users keys list abc123', 'List keys for a user');
915
- }, function(argv) {
916
- var element = usersCommand.keysList({
917
- id: argv.userId
918
- });
919
- render(element);
920
- }).command('add <user-id> <pubkey-path>', 'Add an SSH public key to a user\n', function(yargsAdd) {
921
- return yargsAdd.positional('user-id', {
922
- describe: 'User ID',
923
- type: 'string',
924
- demandOption: true
925
- }).positional('pubkey-path', {
926
- describe: 'Path to the SSH public key file',
927
- type: 'string',
928
- demandOption: true
929
- }).option('label', {
930
- describe: 'Label for the key (e.g., "laptop", "desktop")',
931
- type: 'string',
932
- alias: 'l'
933
- }).example('$0 users keys add abc123 ~/.ssh/id_rsa.pub', 'Add RSA public key').example('$0 users keys add abc123 ~/.ssh/id_ed25519.pub --label laptop', 'Add key with label');
934
- }, function(argv) {
935
- var element = usersCommand.keysAdd({
936
- id: argv.userId,
937
- pubkeyPath: argv.pubkeyPath,
938
- label: argv.label
939
- });
940
- render(element);
941
- }).command('remove <user-id> <fingerprint>', 'Remove a key from a user\n', function(yargsRemove) {
942
- return yargsRemove.positional('user-id', {
943
- describe: 'User ID',
944
- type: 'string',
945
- demandOption: true
946
- }).positional('fingerprint', {
947
- describe: 'Fingerprint of the key to remove',
948
- type: 'string',
949
- demandOption: true
950
- }).option('force', {
951
- describe: 'Skip confirmation prompt',
952
- type: 'boolean',
953
- alias: 'f',
954
- default: false
955
- }).example('$0 users keys remove abc123 SHA256:...', 'Remove a key');
956
- }, function(argv) {
957
- var element = usersCommand.keysRemove({
958
- id: argv.userId,
959
- fingerprint: argv.fingerprint,
960
- force: argv.force
961
- });
962
- render(element);
963
- }).demandCommand(1, 'You need to specify a keys command (list, add, remove)');
964
- }).demandCommand(1, 'You need to specify a users command (list, create, delete, keys)');
914
+ }).command('list-keys <name>', 'List keys for a user\n', function(yargsKeysList) {
915
+ return yargsKeysList.positional('name', {
916
+ describe: 'Name of the user',
917
+ type: 'string',
918
+ demandOption: true
919
+ }).example('$0 users list-keys admin', 'List keys for a user');
920
+ }, function(argv) {
921
+ var element = usersCommand.listKeys(argv);
922
+ render(element);
923
+ }).command('add-key <name> [pubkey-path]', 'Add an SSH public key to a user\n', function(yargsAdd) {
924
+ return yargsAdd.positional('name', {
925
+ describe: 'Name of the user',
926
+ type: 'string',
927
+ demandOption: true
928
+ }).positional('pubkey-path', {
929
+ describe: 'Path to the SSH public key file',
930
+ type: 'string'
931
+ }).option('paste', {
932
+ describe: 'Paste a public key from clipboard',
933
+ type: 'boolean',
934
+ default: false
935
+ }).option('label', {
936
+ describe: 'Label for the key (e.g., "laptop", "desktop")',
937
+ type: 'string',
938
+ alias: 'l'
939
+ }).check(function(argv) {
940
+ if (!argv.pubkeyPath && !argv.paste) {
941
+ throw new Error('You must provide a pubkey-path or use --paste');
942
+ }
943
+ return true;
944
+ }).example('$0 users add-key admin ~/.ssh/id_ed25519.pub', 'Add an SSH public key').example('$0 users add-key admin --paste', 'Paste a public key interactively').example('$0 users add-key admin ~/.ssh/id_ed25519.pub --label laptop', 'Add key with label');
945
+ }, function(argv) {
946
+ var element = usersCommand.addKey(argv);
947
+ render(element);
948
+ }).command('remove-key <name> <fingerprint>', 'Remove a key from a user\n', function(yargsRemove) {
949
+ return yargsRemove.positional('name', {
950
+ describe: 'Name of the user',
951
+ type: 'string',
952
+ demandOption: true
953
+ }).positional('fingerprint', {
954
+ describe: 'Fingerprint of the key to remove',
955
+ type: 'string',
956
+ demandOption: true
957
+ }).option('force', {
958
+ describe: 'Skip confirmation prompt',
959
+ type: 'boolean',
960
+ alias: 'f',
961
+ default: false
962
+ }).example('$0 users remove-key admin SHA256:...', 'Remove a key');
963
+ }, function(argv) {
964
+ var element = usersCommand.removeKey(argv);
965
+ render(element);
966
+ }).demandCommand(1, 'You need to specify a users command (list, create, delete, list-keys, add-key, remove-key)');
965
967
  return yargsUsers;
966
968
  });
967
969
  // --- Store Explorer Command ---
@@ -970,55 +972,36 @@ export function buildCli(options) {
970
972
  var element = storeCommand.explore();
971
973
  render(element);
972
974
  });
973
- // --- Auth Commands (Available in both local and global mode) ---
975
+ // --- Auth Commands (Top-level) ---
974
976
  var authCommand = new AuthCommand(undefined, projectRootPath);
975
- {
976
- cli = cli.command('auth', 'Manage authentication configuration\n', function(yargsAuth) {
977
- yargsAuth.command('status', 'Show current auth configuration\n', function() {}, function() {
978
- var element = authCommand.status();
979
- render(element);
980
- }).command('login', 'Configure SSH key for authentication\n', function(yargsLogin) {
981
- return yargsLogin.option('path', {
982
- describe: 'Path to SSH private key',
983
- type: 'string',
984
- alias: 'p'
985
- }).option('project', {
986
- describe: 'Set key for current project instead of global',
987
- type: 'boolean',
988
- default: false
989
- }).example('$0 auth login', 'Interactive key selection').example('$0 auth login --path ~/.ssh/id_ed25519', 'Set key directly').example('$0 auth login --project', 'Set key for current project');
990
- }, function(argv) {
991
- var element = authCommand.login(argv);
992
- render(element);
993
- }).command('logout', 'Clear SSH key configuration\n', function(yargsLogout) {
994
- return yargsLogout.option('project', {
995
- describe: 'Clear key for current project only',
996
- type: 'boolean',
997
- default: false
998
- }).example('$0 auth logout', 'Clear global key configuration').example('$0 auth logout --project', 'Clear project-specific key');
999
- }, function(argv) {
1000
- var element = authCommand.logout(argv);
1001
- render(element);
1002
- }).command('list', 'List available SSH keys\n', function() {}, function() {
1003
- var element = authCommand.list();
1004
- render(element);
1005
- }).command('format-jwk-key', 'Convert an SSH public key to JWK format for ROOT_PUBLIC_KEY\n', function(yargsFormatJwkKey) {
1006
- return yargsFormatJwkKey.option('pubkey', {
1007
- describe: 'Path to SSH public key file',
1008
- type: 'string',
1009
- alias: 'p'
1010
- }).example('$0 auth format-jwk-key', 'Interactive public key selection').example('$0 auth format-jwk-key --pubkey ~/.ssh/id_ed25519.pub', 'Convert specific key');
1011
- }, function(argv) {
1012
- var element = authCommand.formatJwkKey(argv);
1013
- render(element);
1014
- }).command('$0', false, function() {}, function() {
1015
- // Default to status when just 'px auth' is run
1016
- var element = authCommand.status();
1017
- render(element);
1018
- });
1019
- return yargsAuth;
1020
- });
1021
- }
977
+ cli = cli.command('login', 'Configure SSH key for authentication\n', function(yargsLogin) {
978
+ return yargsLogin.option('path', {
979
+ describe: 'Path to SSH private key',
980
+ type: 'string',
981
+ alias: 'p'
982
+ }).option('project', {
983
+ describe: 'Set key for current project instead of global',
984
+ type: 'boolean',
985
+ default: false
986
+ }).example('$0 login', 'Interactive key selection').example('$0 login --path ~/.ssh/id_ed25519', 'Set key directly').example('$0 login --project', 'Set key for current project');
987
+ }, function(argv) {
988
+ var element = authCommand.login(argv);
989
+ render(element);
990
+ });
991
+ cli = cli.command('logout', 'Clear SSH key configuration\n', function(yargsLogout) {
992
+ return yargsLogout.option('project', {
993
+ describe: 'Clear key for current project only',
994
+ type: 'boolean',
995
+ default: false
996
+ }).example('$0 logout', 'Clear global key configuration').example('$0 logout --project', 'Clear project-specific key');
997
+ }, function(argv) {
998
+ var element = authCommand.logout(argv);
999
+ render(element);
1000
+ });
1001
+ cli = cli.command('whoami', 'Show your current authenticated identity\n', function() {}, function() {
1002
+ var element = authCommand.whoami();
1003
+ render(element);
1004
+ });
1022
1005
  cli = cli.epilogue('For more information, visit https://positronic.sh');
1023
1006
  return cli;
1024
1007
  }
@@ -31,11 +31,9 @@ function _define_property(obj, key, value) {
31
31
  return obj;
32
32
  }
33
33
  import React from 'react';
34
- import { AuthStatus } from '../components/auth-status.js';
35
34
  import { AuthLogin } from '../components/auth-login.js';
36
35
  import { AuthLogout } from '../components/auth-logout.js';
37
- import { AuthList } from '../components/auth-list.js';
38
- import { AuthFormatJwkKey } from '../components/auth-format-jwk-key.js';
36
+ import { Whoami } from '../components/whoami.js';
39
37
  import { ProjectConfigManager } from './project-config-manager.js';
40
38
  export var AuthCommand = /*#__PURE__*/ function() {
41
39
  "use strict";
@@ -49,19 +47,7 @@ export var AuthCommand = /*#__PURE__*/ function() {
49
47
  _create_class(AuthCommand, [
50
48
  {
51
49
  /**
52
- * Handles the 'px auth' or 'px auth status' command.
53
- * Shows current auth configuration.
54
- */ key: "status",
55
- value: function status() {
56
- return React.createElement(AuthStatus, {
57
- configManager: this.configManager,
58
- projectRootPath: this.projectRootPath
59
- });
60
- }
61
- },
62
- {
63
- /**
64
- * Handles the 'px auth login' command.
50
+ * Handles the 'px login' command.
65
51
  * Configure SSH key for authentication.
66
52
  */ key: "login",
67
53
  value: function login(param) {
@@ -76,7 +62,7 @@ export var AuthCommand = /*#__PURE__*/ function() {
76
62
  },
77
63
  {
78
64
  /**
79
- * Handles the 'px auth logout' command.
65
+ * Handles the 'px logout' command.
80
66
  * Clear SSH key configuration.
81
67
  */ key: "logout",
82
68
  value: function logout(param) {
@@ -90,27 +76,15 @@ export var AuthCommand = /*#__PURE__*/ function() {
90
76
  },
91
77
  {
92
78
  /**
93
- * Handles the 'px auth list' command.
94
- * List available SSH keys.
95
- */ key: "list",
96
- value: function list() {
97
- return React.createElement(AuthList, {
79
+ * Handles the 'px whoami' command.
80
+ * Shows the current authenticated identity.
81
+ */ key: "whoami",
82
+ value: function whoami() {
83
+ return React.createElement(Whoami, {
98
84
  configManager: this.configManager,
99
85
  projectRootPath: this.projectRootPath
100
86
  });
101
87
  }
102
- },
103
- {
104
- /**
105
- * Handles the 'px auth format-jwk-key' command.
106
- * Convert an SSH public key to JWK format for ROOT_PUBLIC_KEY configuration.
107
- */ key: "formatJwkKey",
108
- value: function formatJwkKey(param) {
109
- var pubkey = param.pubkey;
110
- return React.createElement(AuthFormatJwkKey, {
111
- pubkeyPath: pubkey
112
- });
113
- }
114
88
  }
115
89
  ]);
116
90
  return AuthCommand;
@@ -33,13 +33,14 @@ export var ScheduleCommand = /*#__PURE__*/ function() {
33
33
  {
34
34
  key: "create",
35
35
  value: function create(param) {
36
- var brain = param.brain, cronExpression = param.cronExpression;
36
+ var brain = param.brain, cronExpression = param.cronExpression, options = param.options;
37
37
  return React.createElement(BrainResolver, {
38
38
  identifier: brain,
39
39
  children: function(resolvedBrainTitle) {
40
40
  return React.createElement(ScheduleCreate, {
41
41
  identifier: resolvedBrainTitle,
42
- cronExpression: cronExpression
42
+ cronExpression: cronExpression,
43
+ options: options
43
44
  });
44
45
  }
45
46
  });
@@ -48,39 +48,40 @@ export var UsersCommand = /*#__PURE__*/ function() {
48
48
  {
49
49
  key: "delete",
50
50
  value: function _delete(param) {
51
- var id = param.id, force = param.force;
51
+ var name = param.name, force = param.force;
52
52
  return React.createElement(UsersDelete, {
53
- userId: id,
53
+ userName: name,
54
54
  force: force
55
55
  });
56
56
  }
57
57
  },
58
58
  {
59
- key: "keysList",
60
- value: function keysList(param) {
61
- var id = param.id;
59
+ key: "listKeys",
60
+ value: function listKeys(param) {
61
+ var name = param.name;
62
62
  return React.createElement(UsersKeysList, {
63
- userId: id
63
+ userName: name
64
64
  });
65
65
  }
66
66
  },
67
67
  {
68
- key: "keysAdd",
69
- value: function keysAdd(param) {
70
- var id = param.id, pubkeyPath = param.pubkeyPath, label = param.label;
68
+ key: "addKey",
69
+ value: function addKey(param) {
70
+ var name = param.name, pubkeyPath = param.pubkeyPath, paste = param.paste, label = param.label;
71
71
  return React.createElement(UsersKeysAdd, {
72
- userId: id,
72
+ userName: name,
73
73
  pubkeyPath: pubkeyPath,
74
+ paste: paste,
74
75
  label: label
75
76
  });
76
77
  }
77
78
  },
78
79
  {
79
- key: "keysRemove",
80
- value: function keysRemove(param) {
81
- var id = param.id, fingerprint = param.fingerprint, force = param.force;
80
+ key: "removeKey",
81
+ value: function removeKey(param) {
82
+ var name = param.name, fingerprint = param.fingerprint, force = param.force;
82
83
  return React.createElement(UsersKeysRemove, {
83
- userId: id,
84
+ userName: name,
84
85
  fingerprint: fingerprint,
85
86
  force: force
86
87
  });
@@ -144,7 +144,7 @@ export var AuthLogin = function(param) {
144
144
  marginTop: 1
145
145
  }, /*#__PURE__*/ React.createElement(Text, {
146
146
  dimColor: true
147
- }, "Or specify a custom path with: px auth login --path /path/to/key")));
147
+ }, "Or specify a custom path with: px login --path /path/to/key")));
148
148
  }
149
149
  var items = discoveredKeys.map(function(key) {
150
150
  return {
@@ -57,7 +57,7 @@ import { ProjectConfigManager } from '../commands/project-config-manager.js';
57
57
  import { discoverSSHKeys, generateSSHKey, convertSSHPubKeyToJWK } from '../lib/ssh-key-utils.js';
58
58
  import { resetJwtAuthProvider } from '../lib/jwt-auth.js';
59
59
  import { SelectList } from './select-list.js';
60
- import { appendFileSync, existsSync, writeFileSync } from 'fs';
60
+ import { appendFileSync, existsSync, readFileSync, writeFileSync } from 'fs';
61
61
  import { join } from 'path';
62
62
  export var ProjectAuthSetup = function(param) {
63
63
  var projectDir = param.projectDir, onComplete = param.onComplete;
@@ -125,7 +125,10 @@ export var ProjectAuthSetup = function(param) {
125
125
  var envPath = join(projectDir, '.env');
126
126
  var envLine = "ROOT_PUBLIC_KEY='".concat(jwkString, "'\n");
127
127
  if (existsSync(envPath)) {
128
- appendFileSync(envPath, envLine);
128
+ // Ensure we start on a new line if the file doesn't end with one
129
+ var existing = readFileSync(envPath, 'utf-8');
130
+ var prefix = existing.length > 0 && !existing.endsWith('\n') ? '\n' : '';
131
+ appendFileSync(envPath, prefix + envLine);
129
132
  } else {
130
133
  writeFileSync(envPath, envLine);
131
134
  }
@@ -235,7 +238,7 @@ export var ProjectAuthSetup = function(param) {
235
238
  marginTop: 1
236
239
  }, /*#__PURE__*/ React.createElement(Text, {
237
240
  dimColor: true
238
- }, "You can manually configure auth later with: px auth login")));
241
+ }, "You can manually configure auth later with: px login")));
239
242
  }
240
243
  return null;
241
244
  };
@@ -302,7 +302,13 @@ export var ProjectCreate = function(param) {
302
302
  bold: true
303
303
  }, "2."), " Install dependencies if you didn't choose to during setup (e.g., npm install)"), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
304
304
  bold: true
305
- }, "3."), " Run the development server: px s or positronic server"), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
305
+ }, "3."), " Add your AI provider API key to .env (e.g., GOOGLE_GENERATIVE_AI_API_KEY)"), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
306
306
  bold: true
307
- }, "4."), " Open a new terminal in '", projectName, "' and run a brain: px run example --watch"))));
307
+ }, "4."), " Run the development server: px s or positronic server"), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
308
+ bold: true
309
+ }, "5."), " Open a new terminal in '", projectName, "' and run a brain: px run example --watch")), /*#__PURE__*/ React.createElement(Box, {
310
+ marginTop: 1
311
+ }, /*#__PURE__*/ React.createElement(Text, {
312
+ dimColor: true
313
+ }, "See runner.ts to switch to a different AI provider (e.g., Anthropic, OpenAI)"))));
308
314
  };
@@ -169,7 +169,7 @@ import { Box, Text } from 'ink';
169
169
  import { ErrorComponent } from './error.js';
170
170
  import { useApiPost } from '../hooks/useApi.js';
171
171
  export var ScheduleCreate = function(param) {
172
- var identifier = param.identifier, cronExpression = param.cronExpression;
172
+ var identifier = param.identifier, cronExpression = param.cronExpression, options = param.options;
173
173
  var _useState = _sliced_to_array(useState(false), 2), created = _useState[0], setCreated = _useState[1];
174
174
  var _useState1 = _sliced_to_array(useState(null), 2), schedule = _useState1[0], setSchedule = _useState1[1];
175
175
  var _useApiPost = useApiPost('/brains/schedules', {
@@ -194,7 +194,8 @@ export var ScheduleCreate = function(param) {
194
194
  4,
195
195
  execute({
196
196
  identifier: identifier,
197
- cronExpression: cronExpression
197
+ cronExpression: cronExpression,
198
+ options: options
198
199
  })
199
200
  ];
200
201
  case 1:
@@ -248,7 +249,12 @@ export var ScheduleCreate = function(param) {
248
249
  bold: true
249
250
  }, "Timezone:"), " ", schedule.timezone), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
250
251
  bold: true
251
- }, "Status:"), " ", schedule.enabled ? 'Enabled' : 'Disabled'), schedule.nextRunAt && /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
252
+ }, "Status:"), " ", schedule.enabled ? 'Enabled' : 'Disabled'), options && Object.keys(options).length > 0 && /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
253
+ bold: true
254
+ }, "Options:"), ' ', Object.entries(options).map(function(param) {
255
+ var _param = _sliced_to_array(param, 2), k = _param[0], v = _param[1];
256
+ return "".concat(k, "=").concat(v);
257
+ }).join(', ')), schedule.nextRunAt && /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
252
258
  bold: true
253
259
  }, "Next Run:"), ' ', new Date(schedule.nextRunAt).toLocaleString('en-US', {
254
260
  timeZone: schedule.timezone,
@@ -181,7 +181,7 @@ export var ScheduleList = function(param) {
181
181
  color: schedule.enabled ? 'green' : 'red'
182
182
  }, padRight(schedule.enabled ? 'Enabled' : 'Disabled', columns.status.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
183
183
  dimColor: true
184
- }, padRight(truncate(schedule.runAsUserId, columns.runAs.width), columns.runAs.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
184
+ }, padRight(truncate(schedule.runAsUserName, columns.runAs.width), columns.runAs.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
185
185
  dimColor: true
186
186
  }, padRight(truncate(schedule.timezone || 'UTC', columns.timezone.width), columns.timezone.width)), /*#__PURE__*/ React.createElement(Text, null, " "), /*#__PURE__*/ React.createElement(Text, {
187
187
  color: isOverdue ? 'red' : undefined
@@ -562,9 +562,7 @@ export var StoreExplorer = function() {
562
562
  inputHandlerRef.current(input, key);
563
563
  }, []);
564
564
  // Keyboard handling - uses stable callback to avoid stale closure issues
565
- useInput(stableInputHandler, {
566
- isActive: mode !== 'value'
567
- });
565
+ useInput(stableInputHandler);
568
566
  // Adjust selectedIndex if list shrinks
569
567
  useEffect(function() {
570
568
  var listLength = mode === 'brains' ? brains.length : mode === 'keys' ? keys.length : 0;
@@ -645,12 +643,12 @@ export var StoreExplorer = function() {
645
643
  color: "cyan"
646
644
  }, "Store: ", selectedBrain, " (", keys.length, " keys)")), keys.map(function(entry, i) {
647
645
  return /*#__PURE__*/ React.createElement(Box, {
648
- key: "".concat(entry.scope, "-").concat(entry.key, "-").concat(entry.userId || '')
646
+ key: "".concat(entry.scope, "-").concat(entry.key, "-").concat(entry.userName || '')
649
647
  }, /*#__PURE__*/ React.createElement(Text, {
650
648
  color: i === selectedIndex ? 'cyan' : undefined
651
649
  }, i === selectedIndex ? '> ' : ' ', entry.key, /*#__PURE__*/ React.createElement(Text, {
652
650
  dimColor: true
653
- }, ' ', "[", entry.scope, entry.userId ? ":".concat(entry.userId) : '', "] ", entry.size, "B")));
651
+ }, ' ', "[", entry.scope, entry.userName ? ":".concat(entry.userName) : '', "] ", entry.size, "B")));
654
652
  }), deleteMessage && /*#__PURE__*/ React.createElement(Box, {
655
653
  marginTop: 1
656
654
  }, /*#__PURE__*/ React.createElement(Text, {
@@ -281,13 +281,11 @@ export var UsersCreate = function(param) {
281
281
  flexDirection: "column"
282
282
  }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
283
283
  bold: true
284
- }, "Name:"), " ", data.name), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
285
- bold: true
286
- }, "ID:"), " ", data.id)), /*#__PURE__*/ React.createElement(Box, {
284
+ }, "Name:"), " ", data.name)), /*#__PURE__*/ React.createElement(Box, {
287
285
  marginTop: 1
288
286
  }, /*#__PURE__*/ React.createElement(Text, {
289
287
  dimColor: true
290
- }, "Add a key with: px users keys add ", data.id, " ~/.ssh/id_rsa.pub")));
288
+ }, "Add a key with: px users add-key ", data.name, " ~/.ssh/id_ed25519.pub")));
291
289
  }
292
290
  return null;
293
291
  };
@@ -169,9 +169,9 @@ import { Box, Text, useInput, useApp } from 'ink';
169
169
  import { ErrorComponent } from './error.js';
170
170
  import { useApiDelete, useApiGet } from '../hooks/useApi.js';
171
171
  export var UsersDelete = function(param) {
172
- var userId = param.userId, force = param.force;
172
+ var userName = param.userName, force = param.force;
173
173
  var exit = useApp().exit;
174
- var _useApiGet = useApiGet("/users/".concat(userId)), user = _useApiGet.data, loadingUser = _useApiGet.loading, getUserError = _useApiGet.error;
174
+ var _useApiGet = useApiGet("/users/".concat(userName)), user = _useApiGet.data, loadingUser = _useApiGet.loading, getUserError = _useApiGet.error;
175
175
  var _useApiDelete = useApiDelete('user'), deleting = _useApiDelete.loading, deleteError = _useApiDelete.error, execute = _useApiDelete.execute;
176
176
  var _useState = _sliced_to_array(useState(force), 2), confirmed = _useState[0], setConfirmed = _useState[1];
177
177
  var _useState1 = _sliced_to_array(useState(false), 2), deleted = _useState1[0], setDeleted = _useState1[1];
@@ -196,7 +196,7 @@ export var UsersDelete = function(param) {
196
196
  ]);
197
197
  return [
198
198
  4,
199
- execute("/users/".concat(userId))
199
+ execute("/users/".concat(userName))
200
200
  ];
201
201
  case 2:
202
202
  _state.sent();
@@ -220,7 +220,7 @@ export var UsersDelete = function(param) {
220
220
  })();
221
221
  }, [
222
222
  execute,
223
- userId,
223
+ userName,
224
224
  deletionStarted
225
225
  ]);
226
226
  useEffect(function() {
@@ -259,7 +259,7 @@ export var UsersDelete = function(param) {
259
259
  if (!user) {
260
260
  return /*#__PURE__*/ React.createElement(Box, null, /*#__PURE__*/ React.createElement(Text, {
261
261
  color: "red"
262
- }, "User not found: ", userId));
262
+ }, "User not found: ", userName));
263
263
  }
264
264
  if (deleted) {
265
265
  return /*#__PURE__*/ React.createElement(Box, {