@positronic/cli 0.0.61 → 0.0.63

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/src/cli.js CHANGED
@@ -954,9 +954,9 @@ export function buildCli(options) {
954
954
  }).demandCommand(1, 'You need to specify a users command (list, create, delete, keys)');
955
955
  return yargsUsers;
956
956
  });
957
- // --- Auth Commands (Global Mode Only) ---
958
- if (!isLocalDevMode) {
959
- var authCommand = new AuthCommand();
957
+ // --- Auth Commands (Available in both local and global mode) ---
958
+ var authCommand = new AuthCommand();
959
+ {
960
960
  cli = cli.command('auth', 'Manage authentication configuration\n', function(yargsAuth) {
961
961
  yargsAuth.command('status', 'Show current auth configuration\n', function() {}, function() {
962
962
  var element = authCommand.status();
@@ -267,7 +267,7 @@ var isLocalDevMode = true;
267
267
  export var apiClient = {
268
268
  fetch: function(apiPath, options) {
269
269
  return _async_to_generator(function() {
270
- var baseUrl, port, fullUrl, requestOptions, existingHeaders, headersObj, authHeader;
270
+ var baseUrl, port, fullUrl, existingHeaders, headersObj, authHeader, requestOptions;
271
271
  return _ts_generator(this, function(_state) {
272
272
  switch(_state.label){
273
273
  case 0:
@@ -279,12 +279,7 @@ export var apiClient = {
279
279
  baseUrl = "http://localhost:".concat(port);
280
280
  }
281
281
  fullUrl = "".concat(baseUrl).concat(apiPath.startsWith('/') ? apiPath : '/' + apiPath);
282
- // Add auth header when not in local dev mode
283
- requestOptions = options || {};
284
- if (!!isLocalDevMode) return [
285
- 3,
286
- 2
287
- ];
282
+ // Add auth header to all requests
288
283
  existingHeaders = (options === null || options === void 0 ? void 0 : options.headers) || {};
289
284
  headersObj = {};
290
285
  // Convert headers to plain object
@@ -309,8 +304,6 @@ export var apiClient = {
309
304
  requestOptions = _object_spread_props(_object_spread({}, options), {
310
305
  headers: _object_spread({}, headersObj, authHeader)
311
306
  });
312
- _state.label = 2;
313
- case 2:
314
307
  return [
315
308
  2,
316
309
  fetch(fullUrl, requestOptions)
@@ -42,6 +42,8 @@ function getStatusIcon(status) {
42
42
  switch(status){
43
43
  case 'complete':
44
44
  return '✓';
45
+ case 'halted':
46
+ return '-';
45
47
  case 'running':
46
48
  return '•';
47
49
  case 'error':
@@ -0,0 +1,241 @@
1
+ function _array_like_to_array(arr, len) {
2
+ if (len == null || len > arr.length) len = arr.length;
3
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4
+ return arr2;
5
+ }
6
+ function _array_with_holes(arr) {
7
+ if (Array.isArray(arr)) return arr;
8
+ }
9
+ function _instanceof(left, right) {
10
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
11
+ return !!right[Symbol.hasInstance](left);
12
+ } else {
13
+ return left instanceof right;
14
+ }
15
+ }
16
+ function _iterable_to_array_limit(arr, i) {
17
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
18
+ if (_i == null) return;
19
+ var _arr = [];
20
+ var _n = true;
21
+ var _d = false;
22
+ var _s, _e;
23
+ try {
24
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
25
+ _arr.push(_s.value);
26
+ if (i && _arr.length === i) break;
27
+ }
28
+ } catch (err) {
29
+ _d = true;
30
+ _e = err;
31
+ } finally{
32
+ try {
33
+ if (!_n && _i["return"] != null) _i["return"]();
34
+ } finally{
35
+ if (_d) throw _e;
36
+ }
37
+ }
38
+ return _arr;
39
+ }
40
+ function _non_iterable_rest() {
41
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
42
+ }
43
+ function _sliced_to_array(arr, i) {
44
+ return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
45
+ }
46
+ function _unsupported_iterable_to_array(o, minLen) {
47
+ if (!o) return;
48
+ if (typeof o === "string") return _array_like_to_array(o, minLen);
49
+ var n = Object.prototype.toString.call(o).slice(8, -1);
50
+ if (n === "Object" && o.constructor) n = o.constructor.name;
51
+ if (n === "Map" || n === "Set") return Array.from(n);
52
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
53
+ }
54
+ import React, { useState, useEffect } from 'react';
55
+ import { Box, Text, useApp } from 'ink';
56
+ import { ProjectConfigManager } from '../commands/project-config-manager.js';
57
+ import { discoverSSHKeys, generateSSHKey, convertSSHPubKeyToJWK } from '../lib/ssh-key-utils.js';
58
+ import { resetJwtAuthProvider } from '../lib/jwt-auth.js';
59
+ import { SelectList } from './select-list.js';
60
+ import { appendFileSync, existsSync, writeFileSync } from 'fs';
61
+ import { join } from 'path';
62
+ export var ProjectAuthSetup = function(param) {
63
+ var projectDir = param.projectDir, onComplete = param.onComplete;
64
+ var exit = useApp().exit;
65
+ var _useState = _sliced_to_array(useState('checking'), 2), state = _useState[0], setState = _useState[1];
66
+ var _useState1 = _sliced_to_array(useState([]), 2), discoveredKeys = _useState1[0], setDiscoveredKeys = _useState1[1];
67
+ var _useState2 = _sliced_to_array(useState(null), 2), selectedKey = _useState2[0], setSelectedKey = _useState2[1];
68
+ var _useState3 = _sliced_to_array(useState(null), 2), error = _useState3[0], setError = _useState3[1];
69
+ var _useState4 = _sliced_to_array(useState(null), 2), generatedKeyPath = _useState4[0], setGeneratedKeyPath = _useState4[1];
70
+ // Check for existing keys on mount
71
+ useEffect(function() {
72
+ var keys = discoverSSHKeys();
73
+ setDiscoveredKeys(keys);
74
+ if (keys.length === 0) {
75
+ // No keys found, generate one
76
+ setState('generating');
77
+ } else if (keys.length === 1) {
78
+ // Auto-select single key
79
+ setSelectedKey(keys[0]);
80
+ setState('configuring');
81
+ } else {
82
+ // Multiple keys, show selection
83
+ setState('selecting');
84
+ }
85
+ }, []);
86
+ // Generate key when in generating state
87
+ useEffect(function() {
88
+ if (state !== 'generating') return;
89
+ var result = generateSSHKey();
90
+ if (result.success) {
91
+ setGeneratedKeyPath(result.path);
92
+ // Re-discover keys to get the newly generated key
93
+ var keys = discoverSSHKeys();
94
+ var newKey = keys.find(function(k) {
95
+ return k.path === result.path;
96
+ });
97
+ if (newKey) {
98
+ setSelectedKey(newKey);
99
+ setState('configuring');
100
+ } else {
101
+ setError('Generated key but could not find it');
102
+ setState('error');
103
+ }
104
+ } else {
105
+ setError(result.error || 'Failed to generate SSH key');
106
+ setState('error');
107
+ }
108
+ }, [
109
+ state
110
+ ]);
111
+ // Configure project when key is selected
112
+ useEffect(function() {
113
+ if (state !== 'configuring' || !selectedKey) return;
114
+ try {
115
+ // Convert public key to JWK
116
+ var pubKeyPath = selectedKey.path + '.pub';
117
+ if (!existsSync(pubKeyPath)) {
118
+ setError("Public key not found at ".concat(pubKeyPath));
119
+ setState('error');
120
+ return;
121
+ }
122
+ var keyInfo = convertSSHPubKeyToJWK(pubKeyPath);
123
+ var jwkString = JSON.stringify(keyInfo.jwk);
124
+ // Write ROOT_PUBLIC_KEY to project .env file
125
+ var envPath = join(projectDir, '.env');
126
+ var envLine = "ROOT_PUBLIC_KEY='".concat(jwkString, "'\n");
127
+ if (existsSync(envPath)) {
128
+ appendFileSync(envPath, envLine);
129
+ } else {
130
+ writeFileSync(envPath, envLine);
131
+ }
132
+ // Set the CLI to use this key globally
133
+ var configManager = new ProjectConfigManager();
134
+ var displayPath = selectedKey.path.replace(process.env.HOME || '', '~');
135
+ configManager.setDefaultPrivateKeyPath(displayPath);
136
+ // Reset JWT provider to use the new key
137
+ resetJwtAuthProvider();
138
+ setState('success');
139
+ } catch (err) {
140
+ setError(_instanceof(err, Error) ? err.message : 'Failed to configure auth');
141
+ setState('error');
142
+ }
143
+ }, [
144
+ state,
145
+ selectedKey,
146
+ projectDir
147
+ ]);
148
+ // Auto-complete on success after a short delay
149
+ useEffect(function() {
150
+ if (state === 'success') {
151
+ var timer = setTimeout(function() {
152
+ onComplete();
153
+ }, 100);
154
+ return function() {
155
+ return clearTimeout(timer);
156
+ };
157
+ }
158
+ }, [
159
+ state,
160
+ onComplete
161
+ ]);
162
+ // Checking state
163
+ if (state === 'checking') {
164
+ return /*#__PURE__*/ React.createElement(Box, {
165
+ flexDirection: "column"
166
+ }, /*#__PURE__*/ React.createElement(Text, null, "Checking for SSH keys..."));
167
+ }
168
+ // Generating state
169
+ if (state === 'generating') {
170
+ return /*#__PURE__*/ React.createElement(Box, {
171
+ flexDirection: "column"
172
+ }, /*#__PURE__*/ React.createElement(Text, null, "No SSH keys found. Generating a new Ed25519 key..."));
173
+ }
174
+ // Selecting state - show key picker
175
+ if (state === 'selecting') {
176
+ var items = discoveredKeys.map(function(key) {
177
+ return {
178
+ id: key.path,
179
+ label: key.path.replace(process.env.HOME || '', '~'),
180
+ description: "".concat(key.algorithm, " - ").concat(key.fingerprint).concat(key.comment ? " (".concat(key.comment, ")") : '')
181
+ };
182
+ });
183
+ var handleSelect = function(item) {
184
+ var key = discoveredKeys.find(function(k) {
185
+ return k.path === item.id;
186
+ });
187
+ if (key) {
188
+ setSelectedKey(key);
189
+ setState('configuring');
190
+ }
191
+ };
192
+ var handleCancel = function() {
193
+ exit();
194
+ };
195
+ return /*#__PURE__*/ React.createElement(SelectList, {
196
+ items: items,
197
+ header: "Select an SSH key to use for this project",
198
+ onSelect: handleSelect,
199
+ onCancel: handleCancel,
200
+ footer: "Use arrow keys to navigate, Enter to select, q to cancel"
201
+ });
202
+ }
203
+ // Configuring state
204
+ if (state === 'configuring') {
205
+ return /*#__PURE__*/ React.createElement(Box, {
206
+ flexDirection: "column"
207
+ }, /*#__PURE__*/ React.createElement(Text, null, "Configuring authentication..."));
208
+ }
209
+ // Success state
210
+ if (state === 'success' && selectedKey) {
211
+ var displayPath = selectedKey.path.replace(process.env.HOME || '', '~');
212
+ return /*#__PURE__*/ React.createElement(Box, {
213
+ flexDirection: "column",
214
+ marginTop: 1
215
+ }, /*#__PURE__*/ React.createElement(Text, {
216
+ color: "green"
217
+ }, "Authentication configured!"), /*#__PURE__*/ React.createElement(Box, {
218
+ paddingLeft: 2,
219
+ flexDirection: "column"
220
+ }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
221
+ bold: true
222
+ }, "SSH Key:"), " ", displayPath), generatedKeyPath && /*#__PURE__*/ React.createElement(Text, {
223
+ dimColor: true
224
+ }, "(New key generated at ", generatedKeyPath, ")")));
225
+ }
226
+ // Error state
227
+ if (state === 'error') {
228
+ return /*#__PURE__*/ React.createElement(Box, {
229
+ flexDirection: "column",
230
+ paddingTop: 1,
231
+ paddingBottom: 1
232
+ }, /*#__PURE__*/ React.createElement(Text, {
233
+ color: "red"
234
+ }, "Auth setup failed: ", error), /*#__PURE__*/ React.createElement(Box, {
235
+ marginTop: 1
236
+ }, /*#__PURE__*/ React.createElement(Text, {
237
+ dimColor: true
238
+ }, "You can manually configure auth later with: px auth login")));
239
+ }
240
+ return null;
241
+ };
@@ -174,6 +174,7 @@ function _ts_generator(thisArg, body) {
174
174
  import React, { useState, useEffect } from 'react';
175
175
  import { Box, Text } from 'ink';
176
176
  import { generateProject } from '../commands/helpers.js';
177
+ import { ProjectAuthSetup } from './project-auth-setup.js';
177
178
  import path from 'path';
178
179
  export var ProjectCreate = function(param) {
179
180
  var projectPathArg = param.projectPathArg;
@@ -204,7 +205,12 @@ export var ProjectCreate = function(param) {
204
205
  ];
205
206
  case 1:
206
207
  _state.sent();
207
- setStatus('success');
208
+ // After scaffolding, move to auth setup (skip in test environment)
209
+ if (process.env.NODE_ENV === 'test') {
210
+ setStatus('success');
211
+ } else {
212
+ setStatus('auth_setup');
213
+ }
208
214
  return [
209
215
  3,
210
216
  3
@@ -241,6 +247,32 @@ export var ProjectCreate = function(param) {
241
247
  color: "red"
242
248
  }, "Error creating project: ", error));
243
249
  }
250
+ if (status === 'auth_setup') {
251
+ return /*#__PURE__*/ React.createElement(Box, {
252
+ flexDirection: "column",
253
+ paddingTop: 1
254
+ }, /*#__PURE__*/ React.createElement(Text, {
255
+ bold: true,
256
+ color: "green"
257
+ }, "Project scaffolded!"), /*#__PURE__*/ React.createElement(Box, {
258
+ marginTop: 1,
259
+ paddingLeft: 2,
260
+ flexDirection: "column"
261
+ }, /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
262
+ bold: true
263
+ }, "Name:"), " ", projectName), /*#__PURE__*/ React.createElement(Text, null, /*#__PURE__*/ React.createElement(Text, {
264
+ bold: true
265
+ }, "Location:"), " ", projectDir)), /*#__PURE__*/ React.createElement(Box, {
266
+ marginTop: 1
267
+ }, /*#__PURE__*/ React.createElement(Text, {
268
+ bold: true
269
+ }, "Setting up authentication...")), /*#__PURE__*/ React.createElement(ProjectAuthSetup, {
270
+ projectDir: projectDir,
271
+ onComplete: function() {
272
+ return setStatus('success');
273
+ }
274
+ }));
275
+ }
244
276
  return /*#__PURE__*/ React.createElement(Box, {
245
277
  flexDirection: "column",
246
278
  paddingTop: 1,
@@ -6,48 +6,6 @@ function _array_like_to_array(arr, len) {
6
6
  function _array_with_holes(arr) {
7
7
  if (Array.isArray(arr)) return arr;
8
8
  }
9
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
10
- try {
11
- var info = gen[key](arg);
12
- var value = info.value;
13
- } catch (error) {
14
- reject(error);
15
- return;
16
- }
17
- if (info.done) {
18
- resolve(value);
19
- } else {
20
- Promise.resolve(value).then(_next, _throw);
21
- }
22
- }
23
- function _async_to_generator(fn) {
24
- return function() {
25
- var self = this, args = arguments;
26
- return new Promise(function(resolve, reject) {
27
- var gen = fn.apply(self, args);
28
- function _next(value) {
29
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
30
- }
31
- function _throw(err) {
32
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
33
- }
34
- _next(undefined);
35
- });
36
- };
37
- }
38
- function _define_property(obj, key, value) {
39
- if (key in obj) {
40
- Object.defineProperty(obj, key, {
41
- value: value,
42
- enumerable: true,
43
- configurable: true,
44
- writable: true
45
- });
46
- } else {
47
- obj[key] = value;
48
- }
49
- return obj;
50
- }
51
9
  function _iterable_to_array_limit(arr, i) {
52
10
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
53
11
  if (_i == null) return;
@@ -75,45 +33,6 @@ function _iterable_to_array_limit(arr, i) {
75
33
  function _non_iterable_rest() {
76
34
  throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
77
35
  }
78
- function _object_spread(target) {
79
- for(var i = 1; i < arguments.length; i++){
80
- var source = arguments[i] != null ? arguments[i] : {};
81
- var ownKeys = Object.keys(source);
82
- if (typeof Object.getOwnPropertySymbols === "function") {
83
- ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
84
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
85
- }));
86
- }
87
- ownKeys.forEach(function(key) {
88
- _define_property(target, key, source[key]);
89
- });
90
- }
91
- return target;
92
- }
93
- function ownKeys(object, enumerableOnly) {
94
- var keys = Object.keys(object);
95
- if (Object.getOwnPropertySymbols) {
96
- var symbols = Object.getOwnPropertySymbols(object);
97
- if (enumerableOnly) {
98
- symbols = symbols.filter(function(sym) {
99
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
100
- });
101
- }
102
- keys.push.apply(keys, symbols);
103
- }
104
- return keys;
105
- }
106
- function _object_spread_props(target, source) {
107
- source = source != null ? source : {};
108
- if (Object.getOwnPropertyDescriptors) {
109
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
110
- } else {
111
- ownKeys(Object(source)).forEach(function(key) {
112
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
113
- });
114
- }
115
- return target;
116
- }
117
36
  function _sliced_to_array(arr, i) {
118
37
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
119
38
  }
@@ -125,102 +44,11 @@ function _unsupported_iterable_to_array(o, minLen) {
125
44
  if (n === "Map" || n === "Set") return Array.from(n);
126
45
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
127
46
  }
128
- function _ts_generator(thisArg, body) {
129
- var f, y, t, _ = {
130
- label: 0,
131
- sent: function() {
132
- if (t[0] & 1) throw t[1];
133
- return t[1];
134
- },
135
- trys: [],
136
- ops: []
137
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
138
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
139
- return this;
140
- }), g;
141
- function verb(n) {
142
- return function(v) {
143
- return step([
144
- n,
145
- v
146
- ]);
147
- };
148
- }
149
- function step(op) {
150
- if (f) throw new TypeError("Generator is already executing.");
151
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
152
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
153
- if (y = 0, t) op = [
154
- op[0] & 2,
155
- t.value
156
- ];
157
- switch(op[0]){
158
- case 0:
159
- case 1:
160
- t = op;
161
- break;
162
- case 4:
163
- _.label++;
164
- return {
165
- value: op[1],
166
- done: false
167
- };
168
- case 5:
169
- _.label++;
170
- y = op[1];
171
- op = [
172
- 0
173
- ];
174
- continue;
175
- case 7:
176
- op = _.ops.pop();
177
- _.trys.pop();
178
- continue;
179
- default:
180
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
181
- _ = 0;
182
- continue;
183
- }
184
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
185
- _.label = op[1];
186
- break;
187
- }
188
- if (op[0] === 6 && _.label < t[1]) {
189
- _.label = t[1];
190
- t = op;
191
- break;
192
- }
193
- if (t && _.label < t[2]) {
194
- _.label = t[2];
195
- _.ops.push(op);
196
- break;
197
- }
198
- if (t[2]) _.ops.pop();
199
- _.trys.pop();
200
- continue;
201
- }
202
- op = body.call(thisArg, _);
203
- } catch (e) {
204
- op = [
205
- 6,
206
- e
207
- ];
208
- y = 0;
209
- } finally{
210
- f = t = 0;
211
- }
212
- if (op[0] & 5) throw op[1];
213
- return {
214
- value: op[0] ? op[1] : void 0,
215
- done: true
216
- };
217
- }
218
- }
219
47
  import React, { useState, useEffect, useRef } from 'react';
220
48
  import { Text, Box, useStdout, useInput, useApp } from 'ink';
221
49
  import { EventSource } from 'eventsource';
222
50
  import { getApiBaseUrl, isApiLocalDevMode, apiClient } from '../commands/helpers.js';
223
- import { getAuthHeader } from '../lib/jwt-auth.js';
51
+ import { authenticatedFetch } from '../lib/jwt-auth.js';
224
52
  import { STATUS } from '@positronic/core';
225
53
  import { useApiDelete } from '../hooks/useApi.js';
226
54
  import { ErrorComponent } from './error.js';
@@ -296,33 +124,9 @@ export var TopNavigator = function(param) {
296
124
  }
297
125
  var baseUrl = getApiBaseUrl();
298
126
  var url = "".concat(baseUrl, "/brains/watch");
299
- // Create authenticated fetch wrapper for production mode
300
- // Each fetch call gets a fresh JWT token (tokens have 30-second lifetime)
301
- var authenticatedFetch = function(fetchUrl, init) {
302
- return _async_to_generator(function() {
303
- var authHeader;
304
- return _ts_generator(this, function(_state) {
305
- switch(_state.label){
306
- case 0:
307
- return [
308
- 4,
309
- getAuthHeader()
310
- ];
311
- case 1:
312
- authHeader = _state.sent();
313
- return [
314
- 2,
315
- fetch(fetchUrl, _object_spread_props(_object_spread({}, init), {
316
- headers: _object_spread({}, init === null || init === void 0 ? void 0 : init.headers, authHeader)
317
- }))
318
- ];
319
- }
320
- });
321
- })();
322
- };
323
- var es = new EventSource(url, !isApiLocalDevMode() ? {
127
+ var es = new EventSource(url, {
324
128
  fetch: authenticatedFetch
325
- } : undefined);
129
+ });
326
130
  eventSourceRef.current = es;
327
131
  setIsConnected(false);
328
132
  setError(null);
@@ -9,35 +9,6 @@ function _array_with_holes(arr) {
9
9
  function _array_without_holes(arr) {
10
10
  if (Array.isArray(arr)) return _array_like_to_array(arr);
11
11
  }
12
- function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
13
- try {
14
- var info = gen[key](arg);
15
- var value = info.value;
16
- } catch (error) {
17
- reject(error);
18
- return;
19
- }
20
- if (info.done) {
21
- resolve(value);
22
- } else {
23
- Promise.resolve(value).then(_next, _throw);
24
- }
25
- }
26
- function _async_to_generator(fn) {
27
- return function() {
28
- var self = this, args = arguments;
29
- return new Promise(function(resolve, reject) {
30
- var gen = fn.apply(self, args);
31
- function _next(value) {
32
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
33
- }
34
- function _throw(err) {
35
- asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
36
- }
37
- _next(undefined);
38
- });
39
- };
40
- }
41
12
  function _define_property(obj, key, value) {
42
13
  if (key in obj) {
43
14
  Object.defineProperty(obj, key, {
@@ -99,30 +70,6 @@ function _object_spread(target) {
99
70
  }
100
71
  return target;
101
72
  }
102
- function ownKeys(object, enumerableOnly) {
103
- var keys = Object.keys(object);
104
- if (Object.getOwnPropertySymbols) {
105
- var symbols = Object.getOwnPropertySymbols(object);
106
- if (enumerableOnly) {
107
- symbols = symbols.filter(function(sym) {
108
- return Object.getOwnPropertyDescriptor(object, sym).enumerable;
109
- });
110
- }
111
- keys.push.apply(keys, symbols);
112
- }
113
- return keys;
114
- }
115
- function _object_spread_props(target, source) {
116
- source = source != null ? source : {};
117
- if (Object.getOwnPropertyDescriptors) {
118
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
119
- } else {
120
- ownKeys(Object(source)).forEach(function(key) {
121
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
122
- });
123
- }
124
- return target;
125
- }
126
73
  function _sliced_to_array(arr, i) {
127
74
  return _array_with_holes(arr) || _iterable_to_array_limit(arr, i) || _unsupported_iterable_to_array(arr, i) || _non_iterable_rest();
128
75
  }
@@ -137,97 +84,6 @@ function _unsupported_iterable_to_array(o, minLen) {
137
84
  if (n === "Map" || n === "Set") return Array.from(n);
138
85
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array(o, minLen);
139
86
  }
140
- function _ts_generator(thisArg, body) {
141
- var f, y, t, _ = {
142
- label: 0,
143
- sent: function() {
144
- if (t[0] & 1) throw t[1];
145
- return t[1];
146
- },
147
- trys: [],
148
- ops: []
149
- }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
150
- return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() {
151
- return this;
152
- }), g;
153
- function verb(n) {
154
- return function(v) {
155
- return step([
156
- n,
157
- v
158
- ]);
159
- };
160
- }
161
- function step(op) {
162
- if (f) throw new TypeError("Generator is already executing.");
163
- while(g && (g = 0, op[0] && (_ = 0)), _)try {
164
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
165
- if (y = 0, t) op = [
166
- op[0] & 2,
167
- t.value
168
- ];
169
- switch(op[0]){
170
- case 0:
171
- case 1:
172
- t = op;
173
- break;
174
- case 4:
175
- _.label++;
176
- return {
177
- value: op[1],
178
- done: false
179
- };
180
- case 5:
181
- _.label++;
182
- y = op[1];
183
- op = [
184
- 0
185
- ];
186
- continue;
187
- case 7:
188
- op = _.ops.pop();
189
- _.trys.pop();
190
- continue;
191
- default:
192
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
193
- _ = 0;
194
- continue;
195
- }
196
- if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
197
- _.label = op[1];
198
- break;
199
- }
200
- if (op[0] === 6 && _.label < t[1]) {
201
- _.label = t[1];
202
- t = op;
203
- break;
204
- }
205
- if (t && _.label < t[2]) {
206
- _.label = t[2];
207
- _.ops.push(op);
208
- break;
209
- }
210
- if (t[2]) _.ops.pop();
211
- _.trys.pop();
212
- continue;
213
- }
214
- op = body.call(thisArg, _);
215
- } catch (e) {
216
- op = [
217
- 6,
218
- e
219
- ];
220
- y = 0;
221
- } finally{
222
- f = t = 0;
223
- }
224
- if (op[0] & 5) throw op[1];
225
- return {
226
- value: op[0] ? op[1] : void 0,
227
- done: true
228
- };
229
- }
230
- }
231
87
  import React, { useState, useEffect, useRef } from 'react';
232
88
  import { Text, Box, useStdout, useInput, useApp } from 'ink';
233
89
  import TextInput from 'ink-text-input';
@@ -235,7 +91,7 @@ import { EventSource } from 'eventsource';
235
91
  import { BRAIN_EVENTS, STATUS, reconstructBrainTree, createBrainExecutionMachine, sendEvent } from '@positronic/core';
236
92
  import { useBrainMachine } from '../hooks/useBrainMachine.js';
237
93
  import { getApiBaseUrl, isApiLocalDevMode } from '../commands/helpers.js';
238
- import { getAuthHeader } from '../lib/jwt-auth.js';
94
+ import { authenticatedFetch } from '../lib/jwt-auth.js';
239
95
  import { ErrorComponent } from './error.js';
240
96
  import { EventsView } from './events-view.js';
241
97
  import { StateView } from './state-view.js';
@@ -250,9 +106,9 @@ var getCurrentStepIndex = function(steps) {
250
106
  return s.status === STATUS.RUNNING;
251
107
  });
252
108
  if (runningIndex >= 0) return runningIndex;
253
- // Find the last completed step
109
+ // Find the last completed/halted step
254
110
  for(var i = steps.length - 1; i >= 0; i--){
255
- if (steps[i].status === STATUS.COMPLETE || steps[i].status === STATUS.ERROR) {
111
+ if (steps[i].status === STATUS.COMPLETE || steps[i].status === STATUS.HALTED || steps[i].status === STATUS.ERROR) {
256
112
  return i;
257
113
  }
258
114
  }
@@ -261,7 +117,7 @@ var getCurrentStepIndex = function(steps) {
261
117
  // Count completed steps
262
118
  var getCompletedCount = function(steps) {
263
119
  return steps.filter(function(s) {
264
- return s.status === STATUS.COMPLETE;
120
+ return s.status === STATUS.COMPLETE || s.status === STATUS.HALTED;
265
121
  }).length;
266
122
  };
267
123
  // Get status indicator character
@@ -269,6 +125,8 @@ var getStatusChar = function(status) {
269
125
  switch(status){
270
126
  case STATUS.COMPLETE:
271
127
  return '✓';
128
+ case STATUS.HALTED:
129
+ return '-';
272
130
  case STATUS.ERROR:
273
131
  return '✗';
274
132
  case STATUS.RUNNING:
@@ -284,6 +142,8 @@ var getStatusColor = function(status) {
284
142
  switch(status){
285
143
  case STATUS.COMPLETE:
286
144
  return 'green';
145
+ case STATUS.HALTED:
146
+ return 'gray';
287
147
  case STATUS.ERROR:
288
148
  return 'red';
289
149
  case STATUS.RUNNING:
@@ -424,33 +284,9 @@ export var Watch = function(param) {
424
284
  useEffect(function() {
425
285
  var baseUrl = getApiBaseUrl();
426
286
  var url = "".concat(baseUrl, "/brains/runs/").concat(runId, "/watch");
427
- // Create authenticated fetch wrapper for production mode
428
- // Each fetch call gets a fresh JWT token (tokens have 30-second lifetime)
429
- var authenticatedFetch = function(fetchUrl, init) {
430
- return _async_to_generator(function() {
431
- var authHeader;
432
- return _ts_generator(this, function(_state) {
433
- switch(_state.label){
434
- case 0:
435
- return [
436
- 4,
437
- getAuthHeader()
438
- ];
439
- case 1:
440
- authHeader = _state.sent();
441
- return [
442
- 2,
443
- fetch(fetchUrl, _object_spread_props(_object_spread({}, init), {
444
- headers: _object_spread({}, init === null || init === void 0 ? void 0 : init.headers, authHeader)
445
- }))
446
- ];
447
- }
448
- });
449
- })();
450
- };
451
- var es = new EventSource(url, !isApiLocalDevMode() ? {
287
+ var es = new EventSource(url, {
452
288
  fetch: authenticatedFetch
453
- } : undefined);
289
+ });
454
290
  // Reset connection state for new connection
455
291
  // Note: rootBrain and isComplete are handled by the new machine (via useMemo)
456
292
  setIsConnected(false);
@@ -66,6 +66,45 @@ function _instanceof(left, right) {
66
66
  return left instanceof right;
67
67
  }
68
68
  }
69
+ function _object_spread(target) {
70
+ for(var i = 1; i < arguments.length; i++){
71
+ var source = arguments[i] != null ? arguments[i] : {};
72
+ var ownKeys = Object.keys(source);
73
+ if (typeof Object.getOwnPropertySymbols === "function") {
74
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
75
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
76
+ }));
77
+ }
78
+ ownKeys.forEach(function(key) {
79
+ _define_property(target, key, source[key]);
80
+ });
81
+ }
82
+ return target;
83
+ }
84
+ function ownKeys(object, enumerableOnly) {
85
+ var keys = Object.keys(object);
86
+ if (Object.getOwnPropertySymbols) {
87
+ var symbols = Object.getOwnPropertySymbols(object);
88
+ if (enumerableOnly) {
89
+ symbols = symbols.filter(function(sym) {
90
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
91
+ });
92
+ }
93
+ keys.push.apply(keys, symbols);
94
+ }
95
+ return keys;
96
+ }
97
+ function _object_spread_props(target, source) {
98
+ source = source != null ? source : {};
99
+ if (Object.getOwnPropertyDescriptors) {
100
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
101
+ } else {
102
+ ownKeys(Object(source)).forEach(function(key) {
103
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
104
+ });
105
+ }
106
+ return target;
107
+ }
69
108
  function _ts_generator(thisArg, body) {
70
109
  var f, y, t, _ = {
71
110
  label: 0,
@@ -541,31 +580,36 @@ var providerInstance = null;
541
580
  }
542
581
  /**
543
582
  * Get the Authorization header if auth is available
544
- * Throws if there's an auth configuration error
545
- * Returns empty object with warning if no key is configured
583
+ * Returns empty object if no key is configured (server will reject if auth is required)
584
+ * Only throws for unexpected errors during token creation
546
585
  */ export function getAuthHeader() {
547
586
  return _async_to_generator(function() {
548
- var provider, error, token;
587
+ var provider, token, error;
549
588
  return _ts_generator(this, function(_state) {
550
589
  switch(_state.label){
551
590
  case 0:
552
591
  provider = getJwtAuthProvider();
553
592
  if (!provider.isReady()) {
554
- error = provider.getError();
555
- if (error) {
556
- throw error;
557
- }
558
- console.warn('Warning: No SSH key configured for authentication. Run "px auth login" to configure.');
593
+ // No key configured - return empty headers
594
+ // The server will reject the request if authentication is required
559
595
  return [
560
596
  2,
561
597
  {}
562
598
  ];
563
599
  }
600
+ _state.label = 1;
601
+ case 1:
602
+ _state.trys.push([
603
+ 1,
604
+ 3,
605
+ ,
606
+ 4
607
+ ]);
564
608
  return [
565
609
  4,
566
610
  provider.createToken()
567
611
  ];
568
- case 1:
612
+ case 2:
569
613
  token = _state.sent();
570
614
  return [
571
615
  2,
@@ -573,7 +617,45 @@ var providerInstance = null;
573
617
  Authorization: "Bearer ".concat(token)
574
618
  }
575
619
  ];
620
+ case 3:
621
+ error = _state.sent();
622
+ // Token creation failed (e.g., ssh-agent not running for encrypted key)
623
+ // Return empty headers and let the server reject if auth is required
624
+ return [
625
+ 2,
626
+ {}
627
+ ];
628
+ case 4:
629
+ return [
630
+ 2
631
+ ];
576
632
  }
577
633
  });
578
634
  })();
579
635
  }
636
+ /**
637
+ * Authenticated fetch wrapper for use with EventSource or other
638
+ * consumers that need a fetch function with automatic JWT authentication.
639
+ * Each fetch call gets a fresh JWT token (tokens have 30-second lifetime).
640
+ */ export var authenticatedFetch = function(input, init) {
641
+ return _async_to_generator(function() {
642
+ var authHeader;
643
+ return _ts_generator(this, function(_state) {
644
+ switch(_state.label){
645
+ case 0:
646
+ return [
647
+ 4,
648
+ getAuthHeader()
649
+ ];
650
+ case 1:
651
+ authHeader = _state.sent();
652
+ return [
653
+ 2,
654
+ fetch(input, _object_spread_props(_object_spread({}, init), {
655
+ headers: _object_spread({}, init === null || init === void 0 ? void 0 : init.headers, authHeader)
656
+ }))
657
+ ];
658
+ }
659
+ });
660
+ })();
661
+ };
@@ -1,8 +1,16 @@
1
+ function _instanceof(left, right) {
2
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
3
+ return !!right[Symbol.hasInstance](left);
4
+ } else {
5
+ return left instanceof right;
6
+ }
7
+ }
1
8
  import sshpk from 'sshpk';
2
- import { readFileSync, readdirSync, existsSync } from 'fs';
9
+ import { readFileSync, readdirSync, existsSync, mkdirSync } from 'fs';
3
10
  import { homedir } from 'os';
4
11
  import { join } from 'path';
5
12
  import { createPublicKey } from 'crypto';
13
+ import { execSync } from 'child_process';
6
14
  /**
7
15
  * Discover available SSH keys in the ~/.ssh directory
8
16
  * Scans for common key files and returns metadata about each key
@@ -210,3 +218,45 @@ import { createPublicKey } from 'crypto';
210
218
  }
211
219
  return keyPath;
212
220
  }
221
+ /**
222
+ * Generate a new SSH key using ssh-keygen
223
+ * Creates an Ed25519 key with no passphrase
224
+ */ export function generateSSHKey() {
225
+ var keyPath = arguments.length > 0 && arguments[0] !== void 0 ? arguments[0] : join(homedir(), '.ssh', 'id_ed25519');
226
+ var expandedPath = expandPath(keyPath);
227
+ // Ensure the .ssh directory exists
228
+ var sshDir = join(homedir(), '.ssh');
229
+ if (!existsSync(sshDir)) {
230
+ mkdirSync(sshDir, {
231
+ mode: 448
232
+ });
233
+ }
234
+ // Check if key already exists
235
+ if (existsSync(expandedPath)) {
236
+ return {
237
+ success: false,
238
+ error: "Key already exists at ".concat(expandedPath),
239
+ path: expandedPath
240
+ };
241
+ }
242
+ try {
243
+ // Generate Ed25519 key with no passphrase
244
+ // -t ed25519: key type
245
+ // -N "": empty passphrase
246
+ // -f: output file path
247
+ // -C: comment (email/identifier)
248
+ execSync('ssh-keygen -t ed25519 -N "" -f "'.concat(expandedPath, '" -C "positronic-key"'), {
249
+ stdio: 'ignore'
250
+ });
251
+ return {
252
+ success: true,
253
+ path: expandedPath
254
+ };
255
+ } catch (error) {
256
+ return {
257
+ success: false,
258
+ error: _instanceof(error, Error) ? error.message : 'Failed to generate SSH key',
259
+ path: expandedPath
260
+ };
261
+ }
262
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/commands/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUtD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;AAGhE,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC;AAMzC;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,OAAc,GAAG,IAAI,CAGtF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAGD,eAAO,MAAM,SAAS;qBACG,MAAM,YAAY,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC;IAgDxE;;OAEG;oCACmC,MAAM,YAAY,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC;CAkBxF,CAAC;AAEF,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBAsF5E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,EAAE,CAsCxE;AAeD,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;IAC9C,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5B,KAAK,IAAI,CAAC;AAEX;;GAEG;AACH,wBAAsB,aAAa,CACjC,eAAe,EAAE,MAAM,EACvB,MAAM,GAAE,SAAqB,EAC7B,UAAU,CAAC,EAAE,oBAAoB,GAChC,OAAO,CAAC,UAAU,CAAC,CA+KrB;AAqKD;;GAEG;AACH,wBAAsB,aAAa,CACjC,eAAe,EAAE,MAAM,EACvB,MAAM,GAAE,SAAqB,mBAoB9B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAwCnE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAO3E;AAsCD;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,CAAC,EAAE,MAAM,EACb,SAAS,SAAO,GACf,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,SAAqB,EAC7B,UAAU,CAAC,EAAE,gBAAgB,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA2If"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/commands/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAUtD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,gBAAgB,GAAG,CAAC,QAAQ,EAAE,YAAY,KAAK,IAAI,CAAC;AAGhE,MAAM,MAAM,SAAS,GAAG,OAAO,SAAS,CAAC;AAMzC;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,GAAE,OAAc,GAAG,IAAI,CAGtF;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,OAAO,CAE3C;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAOtC;AAGD,eAAO,MAAM,SAAS;qBACG,MAAM,YAAY,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC;IA6CxE;;OAEG;oCACmC,MAAM,YAAY,WAAW,KAAG,OAAO,CAAC,QAAQ,CAAC;CAkBxF,CAAC;AAEF,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,iBAsF5E;AAED,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,EAAE,CAsCxE;AAeD,UAAU,UAAU;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAClD;AAED,MAAM,MAAM,oBAAoB,GAAG,CAAC,QAAQ,EAAE;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,UAAU,CAAC;IAC9C,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;CAC5B,KAAK,IAAI,CAAC;AAEX;;GAEG;AACH,wBAAsB,aAAa,CACjC,eAAe,EAAE,MAAM,EACvB,MAAM,GAAE,SAAqB,EAC7B,UAAU,CAAC,EAAE,oBAAoB,GAChC,OAAO,CAAC,UAAU,CAAC,CA+KrB;AAqKD;;GAEG;AACH,wBAAsB,aAAa,CACjC,eAAe,EAAE,MAAM,EACvB,MAAM,GAAE,SAAqB,mBAoB9B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAwCnE;AAED;;GAEG;AACH,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAO3E;AAsCD;;GAEG;AACH,wBAAsB,cAAc,CAClC,IAAI,CAAC,EAAE,MAAM,EACb,SAAS,SAAO,GACf,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,SAAqB,EAC7B,UAAU,CAAC,EAAE,gBAAgB,EAC7B,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CA2If"}
@@ -1 +1 @@
1
- {"version":3,"file":"event-detail.d.ts","sourceRoot":"","sources":["../../../src/components/event-detail.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,UAAU,gBAAgB;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AA+ND,eAAO,MAAM,WAAW,GAAI,oDAA2D,gBAAgB,4CAqDtG,CAAC"}
1
+ {"version":3,"file":"event-detail.d.ts","sourceRoot":"","sources":["../../../src/components/event-detail.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAEpD,UAAU,gBAAgB;IACxB,MAAM,EAAE,WAAW,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAiOD,eAAO,MAAM,WAAW,GAAI,oDAA2D,gBAAgB,4CAqDtG,CAAC"}
@@ -0,0 +1,7 @@
1
+ interface ProjectAuthSetupProps {
2
+ projectDir: string;
3
+ onComplete: () => void;
4
+ }
5
+ export declare const ProjectAuthSetup: ({ projectDir, onComplete }: ProjectAuthSetupProps) => import("react/jsx-runtime").JSX.Element | null;
6
+ export {};
7
+ //# sourceMappingURL=project-auth-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-auth-setup.d.ts","sourceRoot":"","sources":["../../../src/components/project-auth-setup.tsx"],"names":[],"mappings":"AAcA,UAAU,qBAAqB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,IAAI,CAAC;CACxB;AAUD,eAAO,MAAM,gBAAgB,GAAI,4BAA4B,qBAAqB,mDAiMjF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"project-create.d.ts","sourceRoot":"","sources":["../../../src/components/project-create.tsx"],"names":[],"mappings":"AAKA,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,aAAa,GAAI,oBAAoB,kBAAkB,4CAyEnE,CAAC"}
1
+ {"version":3,"file":"project-create.d.ts","sourceRoot":"","sources":["../../../src/components/project-create.tsx"],"names":[],"mappings":"AAMA,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB;AAID,eAAO,MAAM,aAAa,GAAI,oBAAoB,kBAAkB,4CAqGnE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"top-navigator.d.ts","sourceRoot":"","sources":["../../../src/components/top-navigator.tsx"],"names":[],"mappings":"AAeA,UAAU,iBAAiB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,eAAO,MAAM,YAAY,GAAI,iBAAiB,iBAAiB,4CAgU9D,CAAC"}
1
+ {"version":3,"file":"top-navigator.d.ts","sourceRoot":"","sources":["../../../src/components/top-navigator.tsx"],"names":[],"mappings":"AAeA,UAAU,iBAAiB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAID,eAAO,MAAM,YAAY,GAAI,iBAAiB,iBAAiB,4CAmT9D,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/components/watch.tsx"],"names":[],"mappings":"AAiMA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,KAAK,GAAI,wDAAuE,UAAU,4CAgftG,CAAC"}
1
+ {"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/components/watch.tsx"],"names":[],"mappings":"AAqMA,UAAU,UAAU;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,eAAO,MAAM,KAAK,GAAI,wDAAuE,UAAU,4CAmetG,CAAC"}
@@ -79,8 +79,14 @@ export declare function resetJwtAuthProvider(): void;
79
79
  export declare function isAuthAvailable(): boolean;
80
80
  /**
81
81
  * Get the Authorization header if auth is available
82
- * Throws if there's an auth configuration error
83
- * Returns empty object with warning if no key is configured
82
+ * Returns empty object if no key is configured (server will reject if auth is required)
83
+ * Only throws for unexpected errors during token creation
84
84
  */
85
85
  export declare function getAuthHeader(): Promise<Record<string, string>>;
86
+ /**
87
+ * Authenticated fetch wrapper for use with EventSource or other
88
+ * consumers that need a fetch function with automatic JWT authentication.
89
+ * Each fetch call gets a fresh JWT token (tokens have 30-second lifetime).
90
+ */
91
+ export declare const authenticatedFetch: typeof fetch;
86
92
  //# sourceMappingURL=jwt-auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"jwt-auth.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-auth.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAsB;IAGvC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,QAAQ,CAAS;;IAMzB,OAAO,CAAC,UAAU;IAqClB;;;;OAIG;IACH,OAAO,IAAI,OAAO;IAYlB;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI;IAIxB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAiCnB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBpC;;OAEG;YACW,iBAAiB;IAwB/B;;OAEG;YACW,gBAAgB;IAwC9B;;;OAGG;YACW,oBAAoB;CAuCnC;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAgBrE"}
1
+ {"version":3,"file":"jwt-auth.d.ts","sourceRoot":"","sources":["../../../src/lib/jwt-auth.ts"],"names":[],"mappings":"AAuBA;;;;GAIG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAsB;IAGvC,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAA0B;IAC1C,OAAO,CAAC,QAAQ,CAAS;;IAMzB,OAAO,CAAC,UAAU;IAqClB;;;;OAIG;IACH,OAAO,IAAI,OAAO;IAYlB;;OAEG;IACH,eAAe,IAAI,OAAO;IAI1B;;OAEG;IACH,QAAQ,IAAI,KAAK,GAAG,IAAI;IAIxB;;OAEG;IACH,cAAc,IAAI,MAAM,GAAG,IAAI;IAI/B;;OAEG;IACH,OAAO,CAAC,YAAY;IAQpB;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAqB9B;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAiCnB;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,MAAM,CAAC;IAoBpC;;OAEG;YACW,iBAAiB;IAwB/B;;OAEG;YACW,gBAAgB;IAwC9B;;;OAGG;YACW,oBAAoB;CAuCnC;AAKD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,eAAe,CAKpD;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CAE3C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,OAAO,CAEzC;AAED;;;;GAIG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAiBrE;AAED;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,EAAE,OAAO,KAYvC,CAAC"}
@@ -44,4 +44,14 @@ export declare function resolvePrivateKeyPath(configuredPath?: string | null): s
44
44
  * Expand a path that may contain ~ to the full path
45
45
  */
46
46
  export declare function expandPath(keyPath: string): string;
47
+ export interface GenerateSSHKeyResult {
48
+ success: boolean;
49
+ error?: string;
50
+ path: string;
51
+ }
52
+ /**
53
+ * Generate a new SSH key using ssh-keygen
54
+ * Creates an Ed25519 key with no passphrase
55
+ */
56
+ export declare function generateSSHKey(keyPath?: string): GenerateSSHKeyResult;
47
57
  //# sourceMappingURL=ssh-key-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ssh-key-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/ssh-key-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAmB,UAAU,EAAE,MAAM,QAAQ,CAAC;AAErD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,aAAa,EAAE,CAkDjD;AA0CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAiBpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAyBnE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAoB5E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD"}
1
+ {"version":3,"file":"ssh-key-utils.d.ts","sourceRoot":"","sources":["../../../src/lib/ssh-key-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAmB,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGrD,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,UAAU,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,aAAa,EAAE,CAkDjD;AA0CD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,UAAU,EAAE,MAAM,GAAG,UAAU,CAiBpE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,UAAU,CAyBnE;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,UAAU,EAAE,KAAK,CAAC,UAAU,GAAG,MAAM,CAG7E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAIlE;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAoB5E;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAKlD;AAED,MAAM,WAAW,oBAAoB;IACnC,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAA8C,GACtD,oBAAoB,CAuCtB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@positronic/cli",
3
- "version": "0.0.61",
3
+ "version": "0.0.63",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -23,9 +23,9 @@
23
23
  "clean": "rm -rf tsconfig.tsbuildinfo dist node_modules"
24
24
  },
25
25
  "dependencies": {
26
- "@positronic/core": "^0.0.61",
27
- "@positronic/spec": "^0.0.61",
28
- "@positronic/template-new-project": "^0.0.61",
26
+ "@positronic/core": "^0.0.63",
27
+ "@positronic/spec": "^0.0.63",
28
+ "@positronic/template-new-project": "^0.0.63",
29
29
  "caz": "^2.0.0",
30
30
  "chokidar": "^3.6.0",
31
31
  "dotenv": "^16.4.7",