@oussema_mili/test-pkg-123 1.1.32

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 (49) hide show
  1. package/LICENSE +29 -0
  2. package/README.md +220 -0
  3. package/auth-callback.html +97 -0
  4. package/auth.js +276 -0
  5. package/cli-commands.js +1921 -0
  6. package/containerManager.js +304 -0
  7. package/daemon/agentRunner.js +491 -0
  8. package/daemon/daemonEntry.js +64 -0
  9. package/daemon/daemonManager.js +266 -0
  10. package/daemon/logManager.js +227 -0
  11. package/dist/styles.css +504 -0
  12. package/docker-actions/apps.js +3913 -0
  13. package/docker-actions/config-transformer.js +380 -0
  14. package/docker-actions/containers.js +355 -0
  15. package/docker-actions/general.js +171 -0
  16. package/docker-actions/images.js +1128 -0
  17. package/docker-actions/logs.js +224 -0
  18. package/docker-actions/metrics.js +270 -0
  19. package/docker-actions/registry.js +1100 -0
  20. package/docker-actions/setup-tasks.js +859 -0
  21. package/docker-actions/terminal.js +247 -0
  22. package/docker-actions/volumes.js +713 -0
  23. package/helper-functions.js +193 -0
  24. package/index.html +83 -0
  25. package/index.js +341 -0
  26. package/package.json +82 -0
  27. package/postcss.config.mjs +5 -0
  28. package/scripts/release.sh +212 -0
  29. package/setup/setupWizard.js +403 -0
  30. package/store/agentSessionStore.js +51 -0
  31. package/store/agentStore.js +113 -0
  32. package/store/configStore.js +171 -0
  33. package/store/daemonStore.js +217 -0
  34. package/store/deviceCredentialStore.js +107 -0
  35. package/store/npmTokenStore.js +65 -0
  36. package/store/registryStore.js +329 -0
  37. package/store/setupState.js +147 -0
  38. package/styles.css +1 -0
  39. package/utils/appLogger.js +223 -0
  40. package/utils/deviceInfo.js +98 -0
  41. package/utils/ecrAuth.js +225 -0
  42. package/utils/encryption.js +112 -0
  43. package/utils/envSetup.js +41 -0
  44. package/utils/errorHandler.js +327 -0
  45. package/utils/portUtils.js +59 -0
  46. package/utils/prerequisites.js +323 -0
  47. package/utils/prompts.js +318 -0
  48. package/utils/ssl-certificates.js +256 -0
  49. package/websocket-server.js +415 -0
@@ -0,0 +1,5 @@
1
+ export default {
2
+ plugins: {
3
+ "@tailwindcss/postcss": {},
4
+ },
5
+ };
@@ -0,0 +1,212 @@
1
+ #!/bin/bash
2
+
3
+ # Fenwave Agent Release Script
4
+ # Usage: ./scripts/release.sh [patch|minor|major|x.x.x]
5
+
6
+ set -e
7
+
8
+ # Colors
9
+ RED='\033[0;31m'
10
+ GREEN='\033[0;32m'
11
+ YELLOW='\033[1;33m'
12
+ BLUE='\033[0;34m'
13
+ NC='\033[0m' # No Color
14
+
15
+ # Functions
16
+ log_info() { echo -e "${BLUE}ℹ ${NC}$1"; }
17
+ log_success() { echo -e "${GREEN}✓ ${NC}$1"; }
18
+ log_warning() { echo -e "${YELLOW}⚠ ${NC}$1"; }
19
+ log_error() { echo -e "${RED}✗ ${NC}$1"; exit 1; }
20
+
21
+ # Check prerequisites
22
+ check_prerequisites() {
23
+ log_info "Checking prerequisites..."
24
+
25
+ command -v node >/dev/null 2>&1 || log_error "Node.js is required"
26
+ command -v npm >/dev/null 2>&1 || log_error "npm is required"
27
+ command -v gh >/dev/null 2>&1 || log_error "GitHub CLI (gh) is required"
28
+ command -v git >/dev/null 2>&1 || log_error "git is required"
29
+
30
+ # Check if logged into npm
31
+ npm whoami >/dev/null 2>&1 || log_error "Not logged into npm. Run 'npm login' first"
32
+
33
+ # Check if logged into GitHub CLI
34
+ gh auth status >/dev/null 2>&1 || log_error "Not logged into GitHub CLI. Run 'gh auth login' first"
35
+
36
+ # Check for uncommitted changes
37
+ if [[ -n $(git status --porcelain) ]]; then
38
+ log_error "Working directory has uncommitted changes. Commit or stash them first"
39
+ fi
40
+
41
+ # Check we're on main branch
42
+ CURRENT_BRANCH=$(git branch --show-current)
43
+ if [[ "$CURRENT_BRANCH" != "main" ]]; then
44
+ log_warning "Not on main branch (currently on: $CURRENT_BRANCH)"
45
+ read -p "Continue anyway? (y/N) " -n 1 -r
46
+ echo
47
+ [[ ! $REPLY =~ ^[Yy]$ ]] && exit 1
48
+ fi
49
+
50
+ # Pull latest changes
51
+ log_info "Pulling latest changes..."
52
+ git pull origin "$CURRENT_BRANCH"
53
+
54
+ log_success "Prerequisites check passed"
55
+ }
56
+
57
+ # Get version argument
58
+ get_version() {
59
+ VERSION_ARG=$1
60
+ CURRENT_VERSION=$(node -p "require('./package.json').version")
61
+
62
+ if [[ -z "$VERSION_ARG" ]]; then
63
+ echo "" >&2
64
+ echo "Current version: $CURRENT_VERSION" >&2
65
+ echo "" >&2
66
+ echo "Select version bump:" >&2
67
+ echo " 1) patch (x.x.X) - Bug fixes" >&2
68
+ echo " 2) minor (x.X.0) - New features" >&2
69
+ echo " 3) major (X.0.0) - Breaking changes" >&2
70
+ echo " 4) custom - Enter specific version" >&2
71
+ echo "" >&2
72
+ read -p "Choice [1-4]: " choice
73
+
74
+ case $choice in
75
+ 1) VERSION_ARG="patch" ;;
76
+ 2) VERSION_ARG="minor" ;;
77
+ 3) VERSION_ARG="major" ;;
78
+ 4) read -p "Enter version (e.g., 1.2.3): " VERSION_ARG ;;
79
+ *) log_error "Invalid choice" ;;
80
+ esac
81
+ fi
82
+
83
+ echo "$VERSION_ARG"
84
+ }
85
+
86
+ # Bump version
87
+ bump_version() {
88
+ local VERSION_TYPE=$1
89
+
90
+ log_info "Bumping version ($VERSION_TYPE)..." >&2
91
+
92
+ if [[ "$VERSION_TYPE" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
93
+ # Specific version provided
94
+ npm version "$VERSION_TYPE" --no-git-tag-version >/dev/null
95
+ else
96
+ # patch, minor, or major
97
+ npm version "$VERSION_TYPE" --no-git-tag-version >/dev/null
98
+ fi
99
+
100
+ NEW_VERSION=$(node -p "require('./package.json').version")
101
+ log_success "Version bumped to $NEW_VERSION" >&2
102
+
103
+ echo "$NEW_VERSION"
104
+ }
105
+
106
+ # Commit and tag
107
+ commit_and_tag() {
108
+ local VERSION=$1
109
+
110
+ log_info "Committing version bump..."
111
+
112
+ git add package.json package-lock.json 2>/dev/null || git add package.json
113
+ git commit -m "chore: release v$VERSION"
114
+
115
+ log_info "Creating git tag v$VERSION..."
116
+ git tag -a "v$VERSION" -m "Release v$VERSION"
117
+
118
+ log_success "Committed and tagged"
119
+ }
120
+
121
+ # Push to remote
122
+ push_to_remote() {
123
+ local VERSION=$1
124
+
125
+ log_info "Pushing to remote..."
126
+
127
+ git push origin "$(git branch --show-current)"
128
+ git push origin "v$VERSION"
129
+
130
+ log_success "Pushed to remote"
131
+ }
132
+
133
+ # Create GitHub release
134
+ create_github_release() {
135
+ local VERSION=$1
136
+
137
+ log_info "Creating GitHub release..."
138
+
139
+ # Get commits since last tag
140
+ LAST_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
141
+
142
+ if [[ -n "$LAST_TAG" ]]; then
143
+ CHANGES=$(git log "$LAST_TAG"..HEAD --pretty=format:"- %s" --no-merges | grep -v "chore: release")
144
+ else
145
+ CHANGES="- Initial release"
146
+ fi
147
+
148
+ # Create release notes
149
+ RELEASE_NOTES="## What's Changed
150
+
151
+ $CHANGES
152
+
153
+ **Full Changelog**: https://github.com/$(gh repo view --json nameWithOwner -q .nameWithOwner)/compare/${LAST_TAG:-v0.0.0}...v$VERSION"
154
+
155
+ gh release create "v$VERSION" \
156
+ --title "v$VERSION" \
157
+ --notes "$RELEASE_NOTES"
158
+
159
+ log_success "GitHub release created"
160
+ }
161
+
162
+ # Publish to npm
163
+ publish_to_npm() {
164
+ log_info "Publishing to npm..."
165
+
166
+ # Check if OTP is needed
167
+ read -p "Enter npm OTP (leave empty if not using 2FA): " OTP
168
+
169
+ if [[ -n "$OTP" ]]; then
170
+ npm publish --access public --otp="$OTP"
171
+ else
172
+ npm publish --access public
173
+ fi
174
+
175
+ log_success "Published to npm"
176
+ }
177
+
178
+ # Main
179
+ main() {
180
+ echo ""
181
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
182
+ echo " Fenwave Agent Release Script"
183
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
184
+ echo ""
185
+
186
+ check_prerequisites
187
+
188
+ VERSION_ARG=$(get_version "$1")
189
+ NEW_VERSION=$(bump_version "$VERSION_ARG")
190
+
191
+ echo ""
192
+ log_info "Ready to release v$NEW_VERSION"
193
+ read -p "Continue with release? (y/N) " -n 1 -r
194
+ echo ""
195
+ [[ ! $REPLY =~ ^[Yy]$ ]] && { log_warning "Release cancelled"; exit 0; }
196
+
197
+ commit_and_tag "$NEW_VERSION"
198
+ push_to_remote "$NEW_VERSION"
199
+ create_github_release "$NEW_VERSION"
200
+ publish_to_npm
201
+
202
+ echo ""
203
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
204
+ echo -e "${GREEN} Release v$NEW_VERSION completed successfully!${NC}"
205
+ echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
206
+ echo ""
207
+ echo " npm: https://www.npmjs.com/package/@fenwave/agent"
208
+ echo " GitHub: $(gh repo view --json url -q .url)/releases/tag/v$NEW_VERSION"
209
+ echo ""
210
+ }
211
+
212
+ main "$@"
@@ -0,0 +1,403 @@
1
+ import chalk from "chalk";
2
+ import { execSync } from "child_process";
3
+ import axios from "axios";
4
+ import {
5
+ checkPrerequisites,
6
+ displayPrerequisites,
7
+ getMissingPrerequisites,
8
+ } from "../utils/prerequisites.js";
9
+ import {
10
+ promptRegistrationToken,
11
+ promptConfirmation,
12
+ displayProgress,
13
+ displaySuccess,
14
+ displayError,
15
+ displayWarning,
16
+ displayInfo,
17
+ displayHeader,
18
+ displayStep,
19
+ displayKeyValue,
20
+ } from "../utils/prompts.js";
21
+ import {
22
+ handleError,
23
+ createError,
24
+ ErrorCode,
25
+ isUserCancellation,
26
+ } from "../utils/errorHandler.js";
27
+ import { getDeviceMetadata, displayDeviceInfo } from "../utils/deviceInfo.js";
28
+ import {
29
+ saveDeviceCredential,
30
+ isDeviceRegistered,
31
+ } from "../store/deviceCredentialStore.js";
32
+ import {
33
+ saveSetupProgress,
34
+ clearSetupState,
35
+ SetupStep,
36
+ isSetupInProgress,
37
+ } from "../store/setupState.js";
38
+ import { initializeConfig } from "../store/configStore.js";
39
+
40
+ const TOTAL_STEPS = 5; // Reduced - no ECR auth or NPM config needed (public package and GHCR)
41
+
42
+ /**
43
+ * Setup Wizard Orchestrator
44
+ * Guides user through complete agent setup
45
+ */
46
+ export class SetupWizard {
47
+ constructor(options = {}) {
48
+ this.backendUrl = options.backendUrl || "http://localhost:7007";
49
+ this.frontendUrl = options.frontendUrl || "http://localhost:3000";
50
+ this.skipPrerequisites = options.skipPrerequisites || false;
51
+ this.registrationToken = options.token || null;
52
+ }
53
+
54
+ /**
55
+ * Run the complete setup wizard
56
+ */
57
+ async run() {
58
+ try {
59
+ // Welcome message
60
+ this.displayWelcome();
61
+
62
+ // Initialize and save agent configuration
63
+ const agentConfig = {
64
+ backendUrl: this.backendUrl,
65
+ frontendUrl: this.frontendUrl,
66
+ };
67
+
68
+ initializeConfig(agentConfig);
69
+
70
+ displayInfo("Agent configuration initialized:");
71
+ displayKeyValue({
72
+ "Backend URL": this.backendUrl,
73
+ "Frontend URL": this.frontendUrl,
74
+ });
75
+ console.log("");
76
+
77
+ // Check if already registered
78
+ if (isDeviceRegistered()) {
79
+ displayWarning("Device is already registered!");
80
+ const shouldContinue = await promptConfirmation(
81
+ "Do you want to re-register (this will replace existing credentials)?",
82
+ false
83
+ );
84
+
85
+ if (!shouldContinue) {
86
+ displayInfo(
87
+ 'Setup cancelled. Use "fenwave status" to view current registration.'
88
+ );
89
+ return;
90
+ }
91
+ }
92
+
93
+ // Check for interrupted setup
94
+ if (isSetupInProgress()) {
95
+ const resume = await promptConfirmation(
96
+ "Found interrupted setup. Do you want to resume?",
97
+ true
98
+ );
99
+
100
+ if (!resume) {
101
+ clearSetupState();
102
+ }
103
+ }
104
+
105
+ // Step 1: Prerequisites Check
106
+ await this.checkPrerequisitesStep();
107
+
108
+ // Step 2: Device Registration
109
+ const registrationData = await this.registrationStep();
110
+
111
+ // Step 3: Pull DevApp Image (GHCR is public, no auth required)
112
+ await this.pullImageStep(registrationData);
113
+
114
+ // Step 4: Start Agent (optional)
115
+ await this.startAgentStep();
116
+
117
+ // Step 5: Complete
118
+ this.displayComplete(registrationData);
119
+
120
+ // Clear setup state
121
+ clearSetupState();
122
+ } catch (error) {
123
+ if (isUserCancellation(error)) {
124
+ displayWarning("\nSetup cancelled by user.");
125
+ displayInfo('Run "fenwave init" again to resume setup.\n');
126
+ } else {
127
+ handleError(error, "Setup Wizard");
128
+ }
129
+ process.exit(1);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Display welcome message
135
+ */
136
+ displayWelcome() {
137
+ displayHeader("Fenwave Dev Agent Setup Wizard");
138
+ console.log(
139
+ chalk.gray(
140
+ " This wizard will guide you through setting up the Fenwave Dev Agent.\n"
141
+ )
142
+ );
143
+ console.log(
144
+ chalk.gray(" You can interrupt the setup anytime and resume later.\n")
145
+ );
146
+ }
147
+
148
+ /**
149
+ * Step 1: Check prerequisites
150
+ */
151
+ async checkPrerequisitesStep() {
152
+ displayStep(1, TOTAL_STEPS, "Checking Prerequisites");
153
+
154
+ if (this.skipPrerequisites) {
155
+ displayInfo("Skipping prerequisites check (--skip-prerequisites flag)");
156
+ return;
157
+ }
158
+
159
+ const checkResults = await checkPrerequisites({
160
+ backendUrl: this.backendUrl,
161
+ });
162
+ const allPassed = displayPrerequisites(checkResults);
163
+
164
+ if (!allPassed) {
165
+ const missing = getMissingPrerequisites(checkResults);
166
+
167
+ console.log(chalk.yellow("\n⚠️ Missing prerequisites:\n"));
168
+ missing.forEach((item) => {
169
+ console.log(chalk.red(` ❌ ${item.name}: ${item.reason}`));
170
+ console.log(chalk.gray(` Action: ${item.action}\n`));
171
+ });
172
+
173
+ const shouldContinue = await promptConfirmation(
174
+ "Some prerequisites are missing. Continue anyway?",
175
+ false
176
+ );
177
+
178
+ if (!shouldContinue) {
179
+ throw createError(
180
+ ErrorCode.OPERATION_CANCELLED,
181
+ "Prerequisites check failed"
182
+ );
183
+ }
184
+ }
185
+
186
+ saveSetupProgress(SetupStep.PREREQUISITES, { allPassed });
187
+ }
188
+
189
+ /**
190
+ * Step 2: Device Registration
191
+ */
192
+ async registrationStep() {
193
+ displayStep(2, TOTAL_STEPS, "Device Registration");
194
+
195
+ // Get registration token
196
+ if (!this.registrationToken) {
197
+ this.registrationToken = await promptRegistrationToken(this.backendUrl);
198
+ }
199
+
200
+ // Collect device information
201
+ const deviceMetadata = await getDeviceMetadata();
202
+ displayInfo("Collected device information:");
203
+ displayDeviceInfo(deviceMetadata);
204
+
205
+ // Register device with backend
206
+ const registrationData = await displayProgress(
207
+ "Registering device with Fenwave...",
208
+ this.registerDevice(deviceMetadata)
209
+ );
210
+
211
+ // Save device credentials
212
+ saveDeviceCredential({
213
+ deviceId: registrationData.deviceId,
214
+ deviceCredential: registrationData.deviceCredential,
215
+ userEntityRef: registrationData.userEntityRef,
216
+ deviceName: deviceMetadata.deviceName,
217
+ platform: deviceMetadata.platform,
218
+ agentVersion: deviceMetadata.agentVersion,
219
+ });
220
+
221
+ displaySuccess(`Device registered: ${registrationData.deviceId}`);
222
+ console.log(chalk.gray(` User: ${registrationData.userEntityRef}\n`));
223
+
224
+ saveSetupProgress(SetupStep.REGISTRATION, {
225
+ deviceId: registrationData.deviceId,
226
+ deviceName: deviceMetadata.deviceName,
227
+ });
228
+
229
+ return registrationData;
230
+ }
231
+
232
+ /**
233
+ * Register device with backend
234
+ */
235
+ async registerDevice(deviceMetadata) {
236
+ try {
237
+ const response = await axios.post(
238
+ `${this.backendUrl}/api/agent-cli/register`,
239
+ {
240
+ installToken: this.registrationToken,
241
+ deviceInfo: {
242
+ deviceName: deviceMetadata.deviceName,
243
+ platform: deviceMetadata.platform,
244
+ osVersion: deviceMetadata.osVersion,
245
+ agentVersion: deviceMetadata.agentVersion,
246
+ metadata: deviceMetadata.metadata,
247
+ },
248
+ },
249
+ { timeout: 10000 }
250
+ );
251
+
252
+ return {
253
+ deviceId: response.data.deviceId,
254
+ deviceCredential: response.data.deviceCredential,
255
+ registryConfig: response.data.registryConfig,
256
+ userEntityRef: response.data.userEntityRef || "unknown",
257
+ };
258
+ } catch (error) {
259
+ if (error.response?.status === 401) {
260
+ throw createError(
261
+ ErrorCode.INVALID_TOKEN,
262
+ "Invalid or expired registration token"
263
+ );
264
+ }
265
+ if (error.response?.status === 429) {
266
+ throw createError(
267
+ ErrorCode.RATE_LIMIT_EXCEEDED,
268
+ "Too many registration attempts"
269
+ );
270
+ }
271
+ throw error;
272
+ }
273
+ }
274
+
275
+ /**
276
+ * Step 3: Pull Fenwave DevApp Image (GHCR is public, no auth required)
277
+ */
278
+ async pullImageStep(registrationData) {
279
+ displayStep(3, TOTAL_STEPS, "Pull Fenwave DevApp Image");
280
+
281
+ const shouldPull = await promptConfirmation(
282
+ "Pull Fenwave DevApp Docker image?",
283
+ true
284
+ );
285
+
286
+ if (!shouldPull) {
287
+ displayInfo("Skipping image pull");
288
+ saveSetupProgress(SetupStep.PULL_IMAGE, { skipped: true });
289
+ return;
290
+ }
291
+
292
+ const { dockerImage } = registrationData.registryConfig;
293
+
294
+ try {
295
+ displayInfo(`Pulling image: ${dockerImage}`);
296
+ displayWarning("This may take a few minutes...");
297
+
298
+ await this.pullDockerImage(dockerImage);
299
+
300
+ displaySuccess("Docker image pulled successfully");
301
+ saveSetupProgress(SetupStep.PULL_IMAGE, { dockerImage });
302
+ } catch (error) {
303
+ displayError("Failed to pull Docker image");
304
+
305
+ const shouldContinue = await promptConfirmation(
306
+ "Continue without pulling image?",
307
+ true
308
+ );
309
+ if (!shouldContinue) {
310
+ throw createError(
311
+ ErrorCode.DOCKER_PULL_FAILED,
312
+ "Docker image pull failed"
313
+ );
314
+ }
315
+
316
+ saveSetupProgress(SetupStep.PULL_IMAGE, { failed: true });
317
+ }
318
+ }
319
+
320
+ /**
321
+ * Pull Docker image
322
+ */
323
+ async pullDockerImage(imageName) {
324
+ return new Promise((resolve, reject) => {
325
+ try {
326
+ execSync(`docker pull ${imageName}`, {
327
+ stdio: "inherit",
328
+ });
329
+ resolve();
330
+ } catch (error) {
331
+ reject(error);
332
+ }
333
+ });
334
+ }
335
+
336
+ /**
337
+ * Step 4: Start Agent (optional)
338
+ */
339
+ async startAgentStep() {
340
+ displayStep(4, TOTAL_STEPS, "Start Agent Service");
341
+
342
+ const shouldStart = await promptConfirmation("Start the agent now?", true);
343
+
344
+ if (!shouldStart) {
345
+ displayInfo("You can start the agent later with: fenwave login");
346
+ saveSetupProgress(SetupStep.START_AGENT, { started: false });
347
+ return;
348
+ }
349
+
350
+ displayInfo("Starting agent requires authentication...");
351
+ displayInfo("Please run: fenwave login");
352
+
353
+ saveSetupProgress(SetupStep.START_AGENT, { started: false });
354
+ }
355
+
356
+ /**
357
+ * Display completion message
358
+ */
359
+ displayComplete(registrationData) {
360
+ displayStep(5, TOTAL_STEPS, "Setup Complete! 🎉");
361
+
362
+ console.log("");
363
+ displayHeader("Setup Summary");
364
+
365
+ displayKeyValue({
366
+ "Device ID": registrationData.deviceId,
367
+ "Device Name": registrationData.deviceName || "N/A",
368
+ Platform: registrationData.platform || "N/A",
369
+ User: registrationData.userEntityRef || "N/A",
370
+ });
371
+
372
+ console.log("");
373
+ console.log(chalk.green.bold("✅ Setup completed successfully!\n"));
374
+
375
+ console.log(chalk.bold("Next Steps:\n"));
376
+ console.log(chalk.gray(" 1. Start the agent:"));
377
+ console.log(chalk.cyan(" $ fenwave login\n"));
378
+ console.log(chalk.gray(" 2. Check agent status:"));
379
+ console.log(chalk.cyan(" $ fenwave status\n"));
380
+ console.log(chalk.gray(" 3. View agent information:"));
381
+ console.log(chalk.cyan(" $ fenwave info\n"));
382
+
383
+ console.log(chalk.bold("Documentation:\n"));
384
+ console.log(
385
+ chalk.gray(" • View all commands: ") + chalk.cyan("fenwave --help")
386
+ );
387
+ console.log(
388
+ chalk.gray(" • Setup guide: ") + chalk.cyan("fenwave setup-guide")
389
+ );
390
+ console.log("");
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Run setup wizard
396
+ *
397
+ * @param {Object} options - Wizard options
398
+ * @returns {Promise<void>}
399
+ */
400
+ export async function runSetupWizard(options = {}) {
401
+ const wizard = new SetupWizard(options);
402
+ await wizard.run();
403
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Agent Session Store
3
+ * Stores agent session information in memory
4
+ * This is a separate module to avoid circular dependencies
5
+ */
6
+
7
+ // Store agent session info (will be set when server starts)
8
+ let agentSessionInfo = {
9
+ agentId: null,
10
+ userEntityRef: null,
11
+ sessionExpiresAt: null,
12
+ };
13
+
14
+ /**
15
+ * Set agent session info
16
+ * @param {object} sessionInfo - Session information
17
+ */
18
+ function setAgentSessionInfo(sessionInfo) {
19
+ agentSessionInfo.agentId = sessionInfo.agentId || null;
20
+ agentSessionInfo.userEntityRef = sessionInfo.userEntityRef || null;
21
+ agentSessionInfo.sessionExpiresAt = sessionInfo.sessionExpiresAt || null;
22
+ }
23
+
24
+ /**
25
+ * Get agent session info
26
+ * @returns {object} Agent session info
27
+ */
28
+ function getAgentSessionInfo() {
29
+ return agentSessionInfo;
30
+ }
31
+
32
+ /**
33
+ * Clear agent session info
34
+ */
35
+ function clearAgentSessionInfo() {
36
+ agentSessionInfo.agentId = null;
37
+ agentSessionInfo.userEntityRef = null;
38
+ agentSessionInfo.sessionExpiresAt = null;
39
+ }
40
+
41
+ export default {
42
+ setAgentSessionInfo,
43
+ getAgentSessionInfo,
44
+ clearAgentSessionInfo,
45
+ };
46
+
47
+ export {
48
+ setAgentSessionInfo,
49
+ getAgentSessionInfo,
50
+ clearAgentSessionInfo,
51
+ };