visionos-monorepo 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/worktrees/competent-burnell-8d1330/README.md +138 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/package.json +35 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/scripts/copy-web-assets.mjs +12 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/commands/logout.ts +12 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/commands/open.ts +19 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/commands/start.ts +97 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/commands/status.ts +23 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/commands/userinfo.ts +47 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/index.ts +23 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/lib/auth.ts +84 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/lib/browser.ts +37 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/lib/localState.ts +80 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/lib/runtime.ts +203 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/runtime/index.ts +36 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/src/types/inquirer.d.ts +9 -0
- package/.claude/worktrees/competent-burnell-8d1330/cli/tsconfig.json +19 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/index.html +15 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/package.json +27 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/postcss.config.cjs +7 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/App.tsx +57 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/components/CliAuthPage.tsx +385 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/components/ManifestoPage.tsx +946 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/components/TrackCard.tsx +19 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/lib/api.ts +58 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/main.tsx +11 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/styles/index.css +33 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/src/styles/manifesto.css +1398 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/tailwind.config.ts +36 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/tsconfig.json +25 -0
- package/.claude/worktrees/competent-burnell-8d1330/client/vite.config.ts +20 -0
- package/.claude/worktrees/competent-burnell-8d1330/package-lock.json +5278 -0
- package/.claude/worktrees/competent-burnell-8d1330/package.json +24 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/package.json +25 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/app.ts +71 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/config/env.ts +14 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/features/auth/sessionStore.ts +74 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/index.ts +8 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/routes/auth.ts +112 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/src/routes/health.ts +14 -0
- package/.claude/worktrees/competent-burnell-8d1330/server/tsconfig.json +19 -0
- package/.claude/worktrees/competent-burnell-8d1330/shared/package.json +24 -0
- package/.claude/worktrees/competent-burnell-8d1330/shared/src/index.ts +91 -0
- package/.claude/worktrees/competent-burnell-8d1330/shared/tsconfig.json +16 -0
- package/.claude/worktrees/competent-burnell-8d1330/tsconfig.base.json +12 -0
- package/.claude/worktrees/competent-burnell-8d1330/visionos-manifesto/index.html +392 -0
- package/.claude/worktrees/competent-burnell-8d1330/visionos-manifesto/script.js +146 -0
- package/.claude/worktrees/competent-burnell-8d1330/visionos-manifesto/styles.css +1082 -0
- package/.claude/worktrees/vigilant-napier-0de76f/README.md +138 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/package.json +35 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/scripts/copy-web-assets.mjs +12 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/commands/logout.ts +12 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/commands/open.ts +19 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/commands/start.ts +97 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/commands/status.ts +23 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/commands/userinfo.ts +47 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/index.ts +23 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/lib/auth.ts +84 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/lib/browser.ts +37 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/lib/localState.ts +80 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/lib/runtime.ts +203 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/runtime/index.ts +36 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/src/types/inquirer.d.ts +9 -0
- package/.claude/worktrees/vigilant-napier-0de76f/cli/tsconfig.json +19 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/index.html +15 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/package.json +27 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/postcss.config.cjs +7 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/App.tsx +57 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/components/CliAuthPage.tsx +385 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/components/ManifestoPage.tsx +946 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/components/TrackCard.tsx +19 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/lib/api.ts +58 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/main.tsx +11 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/styles/index.css +33 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/src/styles/manifesto.css +1398 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/tailwind.config.ts +36 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/tsconfig.json +25 -0
- package/.claude/worktrees/vigilant-napier-0de76f/client/vite.config.ts +20 -0
- package/.claude/worktrees/vigilant-napier-0de76f/package-lock.json +5278 -0
- package/.claude/worktrees/vigilant-napier-0de76f/package.json +24 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/package.json +25 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/app.ts +71 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/config/env.ts +14 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/features/auth/sessionStore.ts +74 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/index.ts +8 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/routes/auth.ts +112 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/src/routes/health.ts +14 -0
- package/.claude/worktrees/vigilant-napier-0de76f/server/tsconfig.json +19 -0
- package/.claude/worktrees/vigilant-napier-0de76f/shared/package.json +24 -0
- package/.claude/worktrees/vigilant-napier-0de76f/shared/src/index.ts +91 -0
- package/.claude/worktrees/vigilant-napier-0de76f/shared/tsconfig.json +16 -0
- package/.claude/worktrees/vigilant-napier-0de76f/tsconfig.base.json +12 -0
- package/.claude/worktrees/vigilant-napier-0de76f/visionos-manifesto/index.html +392 -0
- package/.claude/worktrees/vigilant-napier-0de76f/visionos-manifesto/script.js +146 -0
- package/.claude/worktrees/vigilant-napier-0de76f/visionos-manifesto/styles.css +1082 -0
- package/.github/workflows/publish.yml +30 -0
- package/README.md +175 -0
- package/cli/README.md +165 -0
- package/cli/package.json +36 -0
- package/cli/scripts/copy-web-assets.mjs +12 -0
- package/cli/src/commands/lessons.ts +68 -0
- package/cli/src/commands/login.ts +46 -0
- package/cli/src/commands/logout.ts +12 -0
- package/cli/src/commands/open.ts +29 -0
- package/cli/src/commands/start.ts +146 -0
- package/cli/src/commands/status.ts +28 -0
- package/cli/src/commands/userinfo.ts +59 -0
- package/cli/src/index.ts +109 -0
- package/cli/src/lib/auth.ts +84 -0
- package/cli/src/lib/browser.ts +37 -0
- package/cli/src/lib/content.ts +57 -0
- package/cli/src/lib/lessonPrinter.ts +38 -0
- package/cli/src/lib/lessonRunner.ts +381 -0
- package/cli/src/lib/localState.ts +114 -0
- package/cli/src/lib/loginFlow.ts +74 -0
- package/cli/src/lib/progress.ts +94 -0
- package/cli/src/lib/runtime.ts +220 -0
- package/cli/src/lib/validator.ts +401 -0
- package/cli/src/runtime/index.ts +108 -0
- package/cli/src/types/inquirer.d.ts +9 -0
- package/cli/tsconfig.json +19 -0
- package/client/index.html +15 -0
- package/client/package.json +27 -0
- package/client/postcss.config.cjs +7 -0
- package/client/src/App.tsx +102 -0
- package/client/src/components/AccountPage.tsx +79 -0
- package/client/src/components/AuthPanel.tsx +312 -0
- package/client/src/components/CliAuthPage.tsx +367 -0
- package/client/src/components/CreatorPortal.tsx +885 -0
- package/client/src/components/ErrorBoundary.tsx +92 -0
- package/client/src/components/ManifestoPage.tsx +1126 -0
- package/client/src/components/TrackCard.tsx +19 -0
- package/client/src/lib/api.ts +215 -0
- package/client/src/main.tsx +14 -0
- package/client/src/styles/index.css +33 -0
- package/client/src/styles/manifesto.css +1828 -0
- package/client/tailwind.config.ts +36 -0
- package/client/tsconfig.json +25 -0
- package/client/vercel.json +8 -0
- package/client/vite.config.ts +33 -0
- package/package.json +27 -0
- package/server/package.json +26 -0
- package/server/src/app.ts +132 -0
- package/server/src/config/env.ts +135 -0
- package/server/src/features/accounts/accountStore.ts +359 -0
- package/server/src/features/accounts/contentStore.ts +264 -0
- package/server/src/features/accounts/password.ts +26 -0
- package/server/src/features/auth/sessionStore.ts +79 -0
- package/server/src/index.ts +8 -0
- package/server/src/routes/auth.ts +328 -0
- package/server/src/routes/content.ts +174 -0
- package/server/src/routes/health.ts +14 -0
- package/server/src/routes/progress.ts +105 -0
- package/server/tsconfig.json +19 -0
- package/shared/package.json +24 -0
- package/shared/src/index.ts +455 -0
- package/shared/tsconfig.json +16 -0
- package/tsconfig.base.json +12 -0
- package/visionos-manifesto/index.html +392 -0
- package/visionos-manifesto/script.js +146 -0
- package/visionos-manifesto/styles.css +1082 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Publish CLI to npm
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- 'v*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout repository
|
|
13
|
+
uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Setup Node.js
|
|
16
|
+
uses: actions/setup-node@v4
|
|
17
|
+
with:
|
|
18
|
+
node-version: '20'
|
|
19
|
+
registry-url: 'https://registry.npmjs.org'
|
|
20
|
+
|
|
21
|
+
- name: Install dependencies
|
|
22
|
+
run: npm ci
|
|
23
|
+
|
|
24
|
+
- name: Build monorepo packages
|
|
25
|
+
run: npm run build
|
|
26
|
+
|
|
27
|
+
- name: Publish CLI package to npm
|
|
28
|
+
run: npm publish -w cli
|
|
29
|
+
env:
|
|
30
|
+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
package/README.md
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# VisionOS
|
|
2
|
+
|
|
3
|
+
VisionOS is a CLI-first learning platform for command-line practice across tracks such as Git, Linux, React CLI, and OS commands.
|
|
4
|
+
|
|
5
|
+
The current build includes:
|
|
6
|
+
|
|
7
|
+
- An installable `visionos-cli` package with a `visionos` binary
|
|
8
|
+
- An embedded local runtime that serves the web UI and API automatically
|
|
9
|
+
- Browser-based CLI authentication handoff
|
|
10
|
+
- Local user/session persistence in `~/.visionos/`
|
|
11
|
+
- Commands for `start`, `login`, `lessons`, `open`, `userinfo`, `status`, and `logout`
|
|
12
|
+
- A monorepo dev setup for separate server/client development
|
|
13
|
+
|
|
14
|
+
## Monorepo Layout
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
visionos/
|
|
18
|
+
├── brain/
|
|
19
|
+
├── cli/
|
|
20
|
+
├── client/
|
|
21
|
+
├── server/
|
|
22
|
+
├── shared/
|
|
23
|
+
└── README.md
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Install The CLI
|
|
27
|
+
|
|
28
|
+
The npm package name is `visionos-cli`, but the command you run is `visionos`.
|
|
29
|
+
|
|
30
|
+
### From npm
|
|
31
|
+
|
|
32
|
+
Once the package is published, install it globally with:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g visionos-cli
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Then run:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
visionos start
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### From this repository
|
|
45
|
+
|
|
46
|
+
This repo is not published automatically. To build the installable tarball locally:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install
|
|
50
|
+
npm run pack:cli
|
|
51
|
+
npm install -g ./visionos-cli-0.1.1.tgz
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
After that, the CLI works the same way:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
visionos start
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
You do not need `npm run dev:cli -- start` for installed usage.
|
|
61
|
+
|
|
62
|
+
## CLI Commands
|
|
63
|
+
|
|
64
|
+
> [!TIP]
|
|
65
|
+
> For a comprehensive guide covering options, internal behaviors, offline state configuration, and validation mechanics, refer directly to the [CLI Documentation](file:///Users/adityapathania/Codes/Chitkara/Projects/IP-project/VisionOS/cli/README.md).
|
|
66
|
+
|
|
67
|
+
- `visionos start`
|
|
68
|
+
Starts the local VisionOS runtime if needed, opens browser account login when required, lets the learner choose a beginner lesson, and saves the selected lesson as current progress.
|
|
69
|
+
|
|
70
|
+
- `visionos login`
|
|
71
|
+
Opens the browser account flow so a learner can log in or create a MongoDB-backed account.
|
|
72
|
+
|
|
73
|
+
- `visionos lessons`
|
|
74
|
+
Browses beginner lessons for Git, Linux, React CLI, and OS Commands.
|
|
75
|
+
|
|
76
|
+
- `visionos lessons --track git`
|
|
77
|
+
Shows beginner lessons for a specific track.
|
|
78
|
+
|
|
79
|
+
- `visionos open`
|
|
80
|
+
Opens the local VisionOS web interface without restarting the monorepo dev servers.
|
|
81
|
+
|
|
82
|
+
- `visionos userinfo`
|
|
83
|
+
Shows the locally stored learner profile from `~/.visionos/user.json`.
|
|
84
|
+
|
|
85
|
+
- `visionos userinfo --json`
|
|
86
|
+
Prints the stored learner profile, runtime info, and state file paths as JSON.
|
|
87
|
+
|
|
88
|
+
- `visionos status`
|
|
89
|
+
Shows whether the embedded runtime is running and whether a learner profile is stored.
|
|
90
|
+
|
|
91
|
+
- `visionos logout`
|
|
92
|
+
Removes the locally stored learner profile.
|
|
93
|
+
|
|
94
|
+
## Installed Runtime Behavior
|
|
95
|
+
|
|
96
|
+
- `visionos start` boots a local embedded runtime on `127.0.0.1` using an available port.
|
|
97
|
+
- The runtime serves both the React frontend and the API from the same origin.
|
|
98
|
+
- The browser auth page writes the authenticated learner profile to `~/.visionos/user.json`.
|
|
99
|
+
- The account bearer token is stored separately in `~/.visionos/account.json`.
|
|
100
|
+
- Runtime metadata is stored in `~/.visionos/runtime.json`.
|
|
101
|
+
|
|
102
|
+
## Development Workflow
|
|
103
|
+
|
|
104
|
+
If you want to work on the monorepo directly instead of using the installed package:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npm install
|
|
108
|
+
npm run dev
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
That starts:
|
|
112
|
+
|
|
113
|
+
- React on `http://localhost:5173`
|
|
114
|
+
- Express on `http://127.0.0.1:4000`
|
|
115
|
+
|
|
116
|
+
You can still run the CLI in dev mode with:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
npm run dev:cli -- start
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The backend API stays available at `http://127.0.0.1:4000`.
|
|
123
|
+
|
|
124
|
+
## Workspace Scripts
|
|
125
|
+
|
|
126
|
+
- `npm run build` builds every workspace in dependency order, including the packaged CLI runtime assets
|
|
127
|
+
- `npm run pack:cli` builds the repo and creates `visionos-cli-0.1.1.tgz`
|
|
128
|
+
- `npm run dev` starts the Express API and React frontend together
|
|
129
|
+
- `npm run dev:cli` starts the CLI in development mode
|
|
130
|
+
- `npm run dev:server` starts the Express API with file watching
|
|
131
|
+
- `npm run dev:client` starts the React frontend
|
|
132
|
+
|
|
133
|
+
## Current Web Surface
|
|
134
|
+
|
|
135
|
+
- `/` serves the VisionOS homepage and runtime dashboard
|
|
136
|
+
- `/login` serves the account login page
|
|
137
|
+
- `/register` serves the account registration page
|
|
138
|
+
- `/?cliAuthSession=...` serves the browser auth confirmation page
|
|
139
|
+
- `/health` returns API health JSON
|
|
140
|
+
- `/auth/me` returns the stored learner profile for the current machine
|
|
141
|
+
- `/auth/register`, `/auth/login`, and `/auth/google` authenticate MongoDB-backed accounts
|
|
142
|
+
- `/progress` reads and saves MongoDB-backed learner progress for the signed-in account
|
|
143
|
+
- `/runtime/info` returns the current app/API origin information
|
|
144
|
+
|
|
145
|
+
## Account Storage
|
|
146
|
+
|
|
147
|
+
VisionOS account and progress storage uses MongoDB.
|
|
148
|
+
|
|
149
|
+
Server environment:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
MONGODB_URI=mongodb://127.0.0.1:27017
|
|
153
|
+
MONGODB_DB=visionos
|
|
154
|
+
GOOGLE_CLIENT_ID=
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Client environment:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
VITE_GOOGLE_CLIENT_ID=
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Password accounts are stored in MongoDB with salted `scrypt` password hashes. Google login is available in the UI and works once both `GOOGLE_CLIENT_ID` and `VITE_GOOGLE_CLIENT_ID` are configured.
|
|
164
|
+
|
|
165
|
+
## Current Limitations
|
|
166
|
+
|
|
167
|
+
- The lesson execution engine is not implemented yet
|
|
168
|
+
- Progress persistence endpoints exist, but the lesson runner does not write real lesson progress yet
|
|
169
|
+
- The package is ready to publish, but publishing to npm has not been done from this repository
|
|
170
|
+
|
|
171
|
+
## Next Milestones
|
|
172
|
+
|
|
173
|
+
- Command execution and validation engine
|
|
174
|
+
- Local progress persistence and backend sync
|
|
175
|
+
- Resume support across CLI and web experiences
|
package/cli/README.md
ADDED
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
# VisionOS Command Line Interface (CLI)
|
|
2
|
+
|
|
3
|
+
The `visionos-cli` package provides the `visionos` binary—a high-fidelity, interactive, and terminal-first educational environment. It guides users through hands-on learning tracks (Git, Linux, OS, React) with physical workspace analysis and real-time command syntax validation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 Installation & Setup
|
|
8
|
+
|
|
9
|
+
### Installing Globally
|
|
10
|
+
To install the `visionos` CLI executable globally from npm:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install -g visionos-cli
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
### Building & Installing Locally
|
|
17
|
+
To build and install the CLI from this monorepo directory:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Navigate to monorepo root and execute build
|
|
21
|
+
npm run build
|
|
22
|
+
|
|
23
|
+
# Package the CLI into a tarball
|
|
24
|
+
npm run pack:cli
|
|
25
|
+
|
|
26
|
+
# Globally install the generated package tarball
|
|
27
|
+
npm install -g ./visionos-cli-*.tgz
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Verify your installation by running:
|
|
31
|
+
```bash
|
|
32
|
+
visionos --version
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 🛠 Command Reference
|
|
38
|
+
|
|
39
|
+
### `visionos start`
|
|
40
|
+
Starts a guided, interactive terminal-based learning session.
|
|
41
|
+
|
|
42
|
+
* **Description**: Boots the local embedded runtime (if stopped), handles session authorization checks, prompts you to select a learning track, handles resume state checkpoints, configures your practice directory, and launches you into the step-by-step interactive lesson runner.
|
|
43
|
+
* **Interactive Engine Flow**:
|
|
44
|
+
1. **Authentication Check**: Verifies active session token. Launches browser sign-in if credentials are missing.
|
|
45
|
+
2. **Track Selector**: Queries all available tracks from MongoDB (or local offline catalog fallback).
|
|
46
|
+
3. **Checkpoint Detection**: Automatically detects your progress. Offers to **Resume Last Lesson**, **Start from Beginning**, or **Browse Catalog**.
|
|
47
|
+
4. **Workspace Choice**: Prompts you to practice in the **Default isolated sandbox** or a **Custom directory**.
|
|
48
|
+
5. **Step Execution Loop**: Prints lesson title, estimated minutes, step instructions, and expected result verification commands. Executes commands, displays real OS system stdout/stderr outputs, and intercepts typos or failed exit codes to render descriptive mistake cards.
|
|
49
|
+
* **Usage**:
|
|
50
|
+
```bash
|
|
51
|
+
visionos start
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
### `visionos login`
|
|
57
|
+
Authenticates the terminal with your cloud-backed learner account.
|
|
58
|
+
|
|
59
|
+
* **Description**: Spins up a local temporary embedded bridge server, launches your system browser to coordinate a secure MongoDB or Google authentication token handoff, and saves credentials under `~/.visionos/account.json` and `~/.visionos/user.json`.
|
|
60
|
+
* **Options**:
|
|
61
|
+
* `-t, --track <trackId>`: Directly attach a specific learning track (e.g. `git`, `linux`, `os-commands`) to the browser login session to skip intermediate track prompts.
|
|
62
|
+
* **Usage**:
|
|
63
|
+
```bash
|
|
64
|
+
visionos login
|
|
65
|
+
visionos login --track os-commands
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
### `visionos lessons`
|
|
71
|
+
Browse and preview the interactive track curriculum.
|
|
72
|
+
|
|
73
|
+
* **Description**: Lists all structured lessons, estimated completion times, and step counts for each learning path.
|
|
74
|
+
* **Options**:
|
|
75
|
+
* `-t, --track <trackId>`: Filter and display lessons belonging exclusively to the specified track.
|
|
76
|
+
* `-l, --lesson <lessonId>`: Directly preview details (steps, objectives, verification commands, and descriptions) for a specific lesson without starting it.
|
|
77
|
+
* **Usage**:
|
|
78
|
+
```bash
|
|
79
|
+
# Interactive track search
|
|
80
|
+
visionos lessons
|
|
81
|
+
|
|
82
|
+
# View all lessons in the Git track
|
|
83
|
+
visionos lessons --track git
|
|
84
|
+
|
|
85
|
+
# Inspect a specific rebase lesson
|
|
86
|
+
visionos lessons --lesson git-github-connect
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
---
|
|
90
|
+
|
|
91
|
+
### `visionos open`
|
|
92
|
+
Instantly opens the VisionOS web learning dashboard.
|
|
93
|
+
|
|
94
|
+
* **Description**: Evaluates active local runtime parameters and opens the dashboard inside your default system browser. Automatically injects your local account credentials securely via one-time URL tokens so you bypass manual login screens.
|
|
95
|
+
* **Usage**:
|
|
96
|
+
```bash
|
|
97
|
+
visionos open
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
### `visionos userinfo`
|
|
103
|
+
Inspects and displays details about your locally stored learner profile.
|
|
104
|
+
|
|
105
|
+
* **Description**: Reads and formats cached session data, active progress tracks, authentication dates, and configuration folder structures.
|
|
106
|
+
* **Options**:
|
|
107
|
+
* `--json`: Prints the entire structured learner profile, active paths, and runtime metadata as a raw JSON block (perfect for script hooks or advanced telemetry debugging).
|
|
108
|
+
* **Usage**:
|
|
109
|
+
```bash
|
|
110
|
+
# Formatted terminal display
|
|
111
|
+
visionos userinfo
|
|
112
|
+
|
|
113
|
+
# Print machine-readable JSON
|
|
114
|
+
visionos userinfo --json
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
### `visionos status`
|
|
120
|
+
Show the embedded VisionOS runtime and connectivity status.
|
|
121
|
+
|
|
122
|
+
* **Description**: Runs a diagnostic inspect check on active local runtime configurations. Reports background process IDs (PIDs), target API server endpoints, web dashboard URLs, and authentication status.
|
|
123
|
+
* **Usage**:
|
|
124
|
+
```bash
|
|
125
|
+
visionos status
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
### `visionos logout`
|
|
131
|
+
Removes the locally stored VisionOS learner session.
|
|
132
|
+
|
|
133
|
+
* **Description**: Securely clears all cached profile states, local accounts, and session metadata from the `~/.visionos/` directory.
|
|
134
|
+
* **Usage**:
|
|
135
|
+
```bash
|
|
136
|
+
visionos logout
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## 💾 State & Sandbox Architecture
|
|
142
|
+
|
|
143
|
+
VisionOS operates with a highly robust system structure designed for sandbox isolation and hybrid data replication:
|
|
144
|
+
|
|
145
|
+
### 1. File Configuration Directory (`~/.visionos/`)
|
|
146
|
+
The CLI stores internal state and configurations in the user's home folder:
|
|
147
|
+
* `~/.visionos/account.json`: Stores secure token parameters for API authorization.
|
|
148
|
+
* `~/.visionos/user.json`: Caches core learner profile details (name, email, current track key).
|
|
149
|
+
* `~/.visionos/runtime.json`: Keeps track of current local embedded server specifications (ports, endpoints, PIDs).
|
|
150
|
+
* `~/.visionos/progress.json`: Stores local backup checkpoints for completed lessons/steps. Automatically synchronizes with the MongoDB remote server once internet connection is established.
|
|
151
|
+
|
|
152
|
+
### 2. Workspace Sandbox Isolation
|
|
153
|
+
When executing dynamic steps, learners are offered two practice directories:
|
|
154
|
+
* **Default isolated sandbox (`~/.visionos/sandbox/<lesson-id>`)**: A completely secure, isolated repository rebuilt from scratch at every lesson boot. Bounded operations guarantee zero impact on your computer's home directory.
|
|
155
|
+
* **Custom workspace directory**: Allows learners to select a path of their choice on their system.
|
|
156
|
+
> [!IMPORTANT]
|
|
157
|
+
> When working inside a custom workspace, all clean/reset triggers are disabled. The CLI operates in a pure **read-only inspection mode**, ensuring none of your personal files are ever modified or deleted.
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 🔍 Validation Engine Modes
|
|
162
|
+
Every learning step defines a validation rule that is dynamically validated by the local parser without compiling TypeScript code:
|
|
163
|
+
* **`syntax` Mode**: The user runs the command. The engine runs it in the sandbox, captures real OS stdout/stderr, and confirms successful exit codes (exit 0). Intercepts errors (e.g. typos, options flags) to display rich troubleshooting mistake alerts.
|
|
164
|
+
* **`file-exists` Mode**: Scans the workspace to physically confirm folder or file creation rules.
|
|
165
|
+
* **`file-contains` Mode**: Inspects the file contents to verify exact characters, branch bindings, or repository commits exist.
|
package/cli/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "visionos-cli",
|
|
3
|
+
"version": "0.1.7",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"visionos": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=18.18.0"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsup src/index.ts src/runtime/index.ts --format esm --clean --out-dir dist && node ./scripts/copy-web-assets.mjs",
|
|
16
|
+
"dev": "tsx src/index.ts",
|
|
17
|
+
"lint": "tsc --noEmit -p tsconfig.json"
|
|
18
|
+
},
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"chalk": "^5.3.0",
|
|
21
|
+
"commander": "^12.1.0",
|
|
22
|
+
"cors": "^2.8.5",
|
|
23
|
+
"dotenv": "^16.4.5",
|
|
24
|
+
"express": "^4.21.1",
|
|
25
|
+
"inquirer": "^9.3.7",
|
|
26
|
+
"mongodb": "^6.21.0"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/cors": "^2.8.17",
|
|
30
|
+
"@types/express": "^4.17.21",
|
|
31
|
+
"@types/node": "^22.10.1",
|
|
32
|
+
"tsup": "^8.3.0",
|
|
33
|
+
"tsx": "^4.19.1",
|
|
34
|
+
"typescript": "^5.6.3"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
|
|
5
|
+
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
const cliDir = path.resolve(currentDir, "..");
|
|
7
|
+
const sourceDir = path.resolve(cliDir, "../client/dist");
|
|
8
|
+
const targetDir = path.resolve(cliDir, "./dist/web");
|
|
9
|
+
|
|
10
|
+
await fs.rm(targetDir, { force: true, recursive: true });
|
|
11
|
+
await fs.mkdir(path.dirname(targetDir), { recursive: true });
|
|
12
|
+
await fs.cp(sourceDir, targetDir, { recursive: true });
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import {
|
|
5
|
+
LEARNING_TRACKS,
|
|
6
|
+
getLessonById,
|
|
7
|
+
getLessonsForTrack,
|
|
8
|
+
type LearningTrackId
|
|
9
|
+
} from "../../../shared/src/index.js";
|
|
10
|
+
import { printLessonCatalog, printLessonPreview } from "../lib/lessonPrinter.js";
|
|
11
|
+
|
|
12
|
+
export function createLessonsCommand() {
|
|
13
|
+
return new Command("lessons")
|
|
14
|
+
.description("Browse beginner lessons for each VisionOS track.")
|
|
15
|
+
.option("-t, --track <trackId>", "Show lessons for a specific track.")
|
|
16
|
+
.option("-l, --lesson <lessonId>", "Preview a specific lesson.")
|
|
17
|
+
.action(async ({ lesson, track }: { lesson?: string; track?: LearningTrackId }) => {
|
|
18
|
+
if (lesson) {
|
|
19
|
+
const selectedLesson = getLessonById(lesson);
|
|
20
|
+
|
|
21
|
+
if (!selectedLesson) {
|
|
22
|
+
console.error(chalk.red(`Lesson not found: ${lesson}`));
|
|
23
|
+
process.exitCode = 1;
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
printLessonPreview(selectedLesson);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const trackId = track ?? (await promptForTrack());
|
|
32
|
+
|
|
33
|
+
printLessonCatalog(trackId);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export async function promptForLesson(trackId: LearningTrackId) {
|
|
38
|
+
const lessons = getLessonsForTrack(trackId);
|
|
39
|
+
const { lessonId } = await inquirer.prompt<{ lessonId: string }>([
|
|
40
|
+
{
|
|
41
|
+
type: "list",
|
|
42
|
+
name: "lessonId",
|
|
43
|
+
message: "Choose a beginner lesson:",
|
|
44
|
+
choices: lessons.map((lesson) => ({
|
|
45
|
+
name: `${lesson.title} - ${lesson.summary}`,
|
|
46
|
+
value: lesson.id
|
|
47
|
+
}))
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
return getLessonById(lessonId);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function promptForTrack() {
|
|
55
|
+
const { trackId } = await inquirer.prompt<{ trackId: LearningTrackId }>([
|
|
56
|
+
{
|
|
57
|
+
type: "list",
|
|
58
|
+
name: "trackId",
|
|
59
|
+
message: "Choose a learning track:",
|
|
60
|
+
choices: LEARNING_TRACKS.map((track) => ({
|
|
61
|
+
name: `${track.label} - ${track.description}`,
|
|
62
|
+
value: track.id
|
|
63
|
+
}))
|
|
64
|
+
}
|
|
65
|
+
]);
|
|
66
|
+
|
|
67
|
+
return trackId;
|
|
68
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import { LEARNING_TRACKS, type LearningTrackId } from "../../../shared/src/index.js";
|
|
5
|
+
import { VisionOsApiError } from "../lib/auth.js";
|
|
6
|
+
import { runBrowserLogin } from "../lib/loginFlow.js";
|
|
7
|
+
|
|
8
|
+
export function createLoginCommand() {
|
|
9
|
+
return new Command("login")
|
|
10
|
+
.description("Log in to a VisionOS account through the browser.")
|
|
11
|
+
.option("-t, --track <trackId>", "Learning track to attach to this login session.")
|
|
12
|
+
.action(async ({ track }: { track?: LearningTrackId }) => {
|
|
13
|
+
try {
|
|
14
|
+
const trackId = track ?? (await promptForTrack());
|
|
15
|
+
|
|
16
|
+
await runBrowserLogin(trackId);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
if (error instanceof VisionOsApiError) {
|
|
19
|
+
console.error(chalk.red("Unable to complete VisionOS account login."));
|
|
20
|
+
console.error(chalk.gray(error.message));
|
|
21
|
+
} else if (error instanceof Error) {
|
|
22
|
+
console.error(chalk.red(error.message));
|
|
23
|
+
} else {
|
|
24
|
+
console.error(chalk.red("An unexpected error interrupted VisionOS account login."));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
process.exitCode = 1;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async function promptForTrack() {
|
|
33
|
+
const { trackId } = await inquirer.prompt<{ trackId: LearningTrackId }>([
|
|
34
|
+
{
|
|
35
|
+
type: "list",
|
|
36
|
+
name: "trackId",
|
|
37
|
+
message: "Choose a track for this login session:",
|
|
38
|
+
choices: LEARNING_TRACKS.map((track) => ({
|
|
39
|
+
name: `${track.label} - ${track.description}`,
|
|
40
|
+
value: track.id
|
|
41
|
+
}))
|
|
42
|
+
}
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
return trackId;
|
|
46
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { clearAccountState, clearUserProfile } from "../lib/localState.js";
|
|
4
|
+
|
|
5
|
+
export function createLogoutCommand() {
|
|
6
|
+
return new Command("logout")
|
|
7
|
+
.description("Remove the locally stored VisionOS learner profile.")
|
|
8
|
+
.action(async () => {
|
|
9
|
+
await Promise.all([clearAccountState(), clearUserProfile()]);
|
|
10
|
+
console.log(chalk.yellow("Cleared the local VisionOS account session and learner profile."));
|
|
11
|
+
});
|
|
12
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { openBrowser } from "../lib/browser.js";
|
|
4
|
+
import { ensureVisionOsRuntime } from "../lib/runtime.js";
|
|
5
|
+
import { readAccountState } from "../lib/localState.js";
|
|
6
|
+
|
|
7
|
+
export function createOpenCommand() {
|
|
8
|
+
return new Command("open")
|
|
9
|
+
.description("Open the VisionOS web interface.")
|
|
10
|
+
.action(async () => {
|
|
11
|
+
const runtime = await ensureVisionOsRuntime();
|
|
12
|
+
const account = await readAccountState();
|
|
13
|
+
|
|
14
|
+
let launchUrl = runtime.appUrl;
|
|
15
|
+
if (account?.token) {
|
|
16
|
+
const separator = launchUrl.includes("?") ? "&" : "?";
|
|
17
|
+
launchUrl = `${launchUrl}${separator}token=${encodeURIComponent(account.token)}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const browserOpened = await openBrowser(launchUrl);
|
|
21
|
+
|
|
22
|
+
console.log(chalk.cyan(`VisionOS web interface: ${runtime.appUrl}`));
|
|
23
|
+
|
|
24
|
+
if (!browserOpened) {
|
|
25
|
+
console.log(chalk.yellow("Open the URL above manually if your browser did not launch."));
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|