uniquick 0.1.1 → 0.1.2
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/README.md +6 -6
- package/dist/cli.js +24 -3
- package/dist/mcp.js +57 -6
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,11 +5,11 @@ dashboards, live multiplayer pages, AI tools) to the University of Illinois
|
|
|
5
5
|
UniQuick platform. Visitors sign in silently with their `@illinois.edu` account;
|
|
6
6
|
data, file storage, realtime, and AI are provided by the platform.
|
|
7
7
|
|
|
8
|
-
Live at **https://
|
|
8
|
+
Live at **https://quick.disruptionlab.illinois.edu**.
|
|
9
9
|
|
|
10
10
|
## 1. Get a deploy token (once)
|
|
11
11
|
|
|
12
|
-
Open **https://
|
|
12
|
+
Open **https://quick.disruptionlab.illinois.edu/token**, sign in with your
|
|
13
13
|
`@illinois.edu` account, create a token, and copy it (shown once, looks like
|
|
14
14
|
`qk_...`). Treat it like a password; revoke it from the same page any time.
|
|
15
15
|
|
|
@@ -43,14 +43,14 @@ npx -y uniquick delete <slug> --yes
|
|
|
43
43
|
|
|
44
44
|
Site names are auto-prefixed with your netid (`my-site` → `netid-my-site`); the
|
|
45
45
|
create output shows the final id. Your site is served at
|
|
46
|
-
`https://
|
|
46
|
+
`https://quick.disruptionlab.illinois.edu/s/<slug>/`.
|
|
47
47
|
|
|
48
48
|
## Building a site
|
|
49
49
|
|
|
50
50
|
Make a folder with an `index.html` that loads the SDK:
|
|
51
51
|
|
|
52
52
|
```html
|
|
53
|
-
<script src="https://
|
|
53
|
+
<script src="https://quick.disruptionlab.illinois.edu/sdk.js"></script>
|
|
54
54
|
<script type="module">
|
|
55
55
|
await quick.ready; // silent SSO done
|
|
56
56
|
quick.user; // { name, upn }
|
|
@@ -62,14 +62,14 @@ Make a folder with an `index.html` that loads the SDK:
|
|
|
62
62
|
```
|
|
63
63
|
|
|
64
64
|
Full SDK reference (written for coding agents): paste
|
|
65
|
-
**https://
|
|
65
|
+
**https://quick.disruptionlab.illinois.edu/llms.txt** into your agent's context.
|
|
66
66
|
|
|
67
67
|
## Configuration
|
|
68
68
|
|
|
69
69
|
| Env | Default | Purpose |
|
|
70
70
|
|-----|---------|---------|
|
|
71
71
|
| `UNIQUICK_TOKEN` | — | Deploy token from `/token` (required) |
|
|
72
|
-
| `UNIQUICK_URL` | `https://
|
|
72
|
+
| `UNIQUICK_URL` | `https://quick.disruptionlab.illinois.edu` | Platform base URL |
|
|
73
73
|
| `UNIQUICK_DEPLOY_ROOT` | cwd | Directories the MCP `deploy_site` tool may read from |
|
|
74
74
|
|
|
75
75
|
Questions → vishal@illinois.edu.
|
package/dist/cli.js
CHANGED
|
@@ -96,7 +96,7 @@ function parseArgs(argv) {
|
|
|
96
96
|
}
|
|
97
97
|
return { command, positional, flags };
|
|
98
98
|
}
|
|
99
|
-
var BASE = (process.env.UNIQUICK_URL ?? "https://
|
|
99
|
+
var BASE = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
|
|
100
100
|
function fail(msg) {
|
|
101
101
|
console.error(`error: ${msg}`);
|
|
102
102
|
process.exit(1);
|
|
@@ -146,13 +146,14 @@ usage:
|
|
|
146
146
|
uniquick create <slug> --title <title> [--data-mode open|owner-write]
|
|
147
147
|
uniquick deploy <dir> --site <slug>
|
|
148
148
|
uniquick list
|
|
149
|
+
uniquick share <slug> [--description <text>] [--unshare]
|
|
149
150
|
uniquick delete <slug> --yes
|
|
150
151
|
uniquick token-check
|
|
151
152
|
|
|
152
153
|
(from a repo checkout, prefix any command with: npx tsx cli/uniquick.ts)
|
|
153
154
|
|
|
154
155
|
env:
|
|
155
|
-
UNIQUICK_URL platform base URL (default https://
|
|
156
|
+
UNIQUICK_URL platform base URL (default https://quick.disruptionlab.illinois.edu)
|
|
156
157
|
UNIQUICK_TOKEN deploy token from ${BASE}/token`;
|
|
157
158
|
async function main() {
|
|
158
159
|
const { command, positional, flags } = parseArgs(process.argv.slice(2));
|
|
@@ -180,8 +181,28 @@ async function main() {
|
|
|
180
181
|
if (!manifest.files.some((f) => f.path === "index.html")) {
|
|
181
182
|
console.error(`warning: no top-level index.html \u2014 ${BASE}/s/${site}/ will 404`);
|
|
182
183
|
}
|
|
183
|
-
await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
184
|
+
const res = await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
184
185
|
console.log(`Deployed ${manifest.files.length} file(s) -> ${BASE}/s/${site}/`);
|
|
186
|
+
if (res && res.gallery === false) {
|
|
187
|
+
console.log(
|
|
188
|
+
`
|
|
189
|
+
Want others at Illinois to discover it? Add it to the gallery:
|
|
190
|
+
npx -y uniquick share ${site} --description "one line about it"`
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
case "share": {
|
|
196
|
+
const slug = positional[0] ?? fail("usage: uniquick share <slug> [--description <text>] [--unshare]");
|
|
197
|
+
const unshare = flags.unshare === true;
|
|
198
|
+
const body = { gallery: !unshare };
|
|
199
|
+
if (typeof flags.description === "string") body.gallery_description = flags.description;
|
|
200
|
+
await api("PATCH", `/api/sites/${encodeURIComponent(slug)}`, body);
|
|
201
|
+
if (unshare) {
|
|
202
|
+
console.log(`Removed '${slug}' from the public gallery.`);
|
|
203
|
+
} else {
|
|
204
|
+
console.log(`Shared '${slug}' to the public gallery -> ${BASE}/gallery`);
|
|
205
|
+
}
|
|
185
206
|
break;
|
|
186
207
|
}
|
|
187
208
|
case "list": {
|
package/dist/mcp.js
CHANGED
|
@@ -113,7 +113,7 @@ function parseArgs(argv) {
|
|
|
113
113
|
}
|
|
114
114
|
return { command, positional, flags };
|
|
115
115
|
}
|
|
116
|
-
var BASE = (process.env.UNIQUICK_URL ?? "https://
|
|
116
|
+
var BASE = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
|
|
117
117
|
function fail(msg) {
|
|
118
118
|
console.error(`error: ${msg}`);
|
|
119
119
|
process.exit(1);
|
|
@@ -163,13 +163,14 @@ usage:
|
|
|
163
163
|
uniquick create <slug> --title <title> [--data-mode open|owner-write]
|
|
164
164
|
uniquick deploy <dir> --site <slug>
|
|
165
165
|
uniquick list
|
|
166
|
+
uniquick share <slug> [--description <text>] [--unshare]
|
|
166
167
|
uniquick delete <slug> --yes
|
|
167
168
|
uniquick token-check
|
|
168
169
|
|
|
169
170
|
(from a repo checkout, prefix any command with: npx tsx cli/uniquick.ts)
|
|
170
171
|
|
|
171
172
|
env:
|
|
172
|
-
UNIQUICK_URL platform base URL (default https://
|
|
173
|
+
UNIQUICK_URL platform base URL (default https://quick.disruptionlab.illinois.edu)
|
|
173
174
|
UNIQUICK_TOKEN deploy token from ${BASE}/token`;
|
|
174
175
|
async function main() {
|
|
175
176
|
const { command, positional, flags } = parseArgs(process.argv.slice(2));
|
|
@@ -197,8 +198,28 @@ async function main() {
|
|
|
197
198
|
if (!manifest.files.some((f) => f.path === "index.html")) {
|
|
198
199
|
console.error(`warning: no top-level index.html \u2014 ${BASE}/s/${site}/ will 404`);
|
|
199
200
|
}
|
|
200
|
-
await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
201
|
+
const res = await api("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
201
202
|
console.log(`Deployed ${manifest.files.length} file(s) -> ${BASE}/s/${site}/`);
|
|
203
|
+
if (res && res.gallery === false) {
|
|
204
|
+
console.log(
|
|
205
|
+
`
|
|
206
|
+
Want others at Illinois to discover it? Add it to the gallery:
|
|
207
|
+
npx -y uniquick share ${site} --description "one line about it"`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
case "share": {
|
|
213
|
+
const slug = positional[0] ?? fail("usage: uniquick share <slug> [--description <text>] [--unshare]");
|
|
214
|
+
const unshare = flags.unshare === true;
|
|
215
|
+
const body = { gallery: !unshare };
|
|
216
|
+
if (typeof flags.description === "string") body.gallery_description = flags.description;
|
|
217
|
+
await api("PATCH", `/api/sites/${encodeURIComponent(slug)}`, body);
|
|
218
|
+
if (unshare) {
|
|
219
|
+
console.log(`Removed '${slug}' from the public gallery.`);
|
|
220
|
+
} else {
|
|
221
|
+
console.log(`Shared '${slug}' to the public gallery -> ${BASE}/gallery`);
|
|
222
|
+
}
|
|
202
223
|
break;
|
|
203
224
|
}
|
|
204
225
|
case "list": {
|
|
@@ -240,7 +261,7 @@ if (isMain) {
|
|
|
240
261
|
}
|
|
241
262
|
|
|
242
263
|
// ../mcp/server.ts
|
|
243
|
-
var BASE2 = (process.env.UNIQUICK_URL ?? "https://
|
|
264
|
+
var BASE2 = (process.env.UNIQUICK_URL ?? "https://quick.disruptionlab.illinois.edu").replace(/\/+$/, "");
|
|
244
265
|
var TOKEN = process.env.UNIQUICK_TOKEN ?? "";
|
|
245
266
|
var DEPLOY_ROOT = resolve2(process.env.UNIQUICK_DEPLOY_ROOT ?? process.cwd());
|
|
246
267
|
var slugSchema = z.string().regex(/^[a-z0-9][a-z0-9-]{1,62}$/, "slug must match ^[a-z0-9][a-z0-9-]{1,62}$");
|
|
@@ -307,8 +328,38 @@ server.registerTool(
|
|
|
307
328
|
const manifest = buildManifest(real);
|
|
308
329
|
if (manifest.files.length === 0) throw new Error(`no files found in ${real}`);
|
|
309
330
|
const warn = manifest.files.some((f) => f.path === "index.html") ? "" : "\nWarning: no top-level index.html \u2014 the site root will 404.";
|
|
310
|
-
await api2("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
311
|
-
|
|
331
|
+
const result = await api2("POST", `/api/sites/${encodeURIComponent(site)}/deploy`, manifest);
|
|
332
|
+
const nudge = result && result.gallery === false ? `
|
|
333
|
+
|
|
334
|
+
Now that it's live, ask the user if they'd like to share this app on the public UniQuick gallery (${BASE2}/gallery) so others at Illinois can discover it. If they say yes, call share_to_gallery with a one-line description.` : "";
|
|
335
|
+
return ok(`Deployed ${manifest.files.length} file(s) to ${BASE2}/s/${site}/${warn}${nudge}`);
|
|
336
|
+
}
|
|
337
|
+
);
|
|
338
|
+
server.registerTool(
|
|
339
|
+
"share_to_gallery",
|
|
340
|
+
{
|
|
341
|
+
description: `Add a site to the public UniQuick gallery (${BASE2}/gallery) so anyone at Illinois can discover it. ALWAYS ask the user before calling this \u2014 the app is then listed publicly with the owner's name and a description. Provide a short one-line description of what the app does.`,
|
|
342
|
+
inputSchema: {
|
|
343
|
+
site: slugSchema.describe("Site slug to share"),
|
|
344
|
+
description: z.string().max(280).optional().describe("One-line description shown on the gallery card")
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
async ({ site, description }) => {
|
|
348
|
+
const body = { gallery: true };
|
|
349
|
+
if (description) body.gallery_description = description;
|
|
350
|
+
await api2("PATCH", `/api/sites/${encodeURIComponent(site)}`, body);
|
|
351
|
+
return ok(`Shared '${site}' to the public gallery -> ${BASE2}/gallery`);
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
server.registerTool(
|
|
355
|
+
"unshare_from_gallery",
|
|
356
|
+
{
|
|
357
|
+
description: "Remove a site from the public UniQuick gallery. It stays live at its /s/<slug>/ URL.",
|
|
358
|
+
inputSchema: { site: slugSchema.describe("Site slug to remove from the gallery") }
|
|
359
|
+
},
|
|
360
|
+
async ({ site }) => {
|
|
361
|
+
await api2("PATCH", `/api/sites/${encodeURIComponent(site)}`, { gallery: false });
|
|
362
|
+
return ok(`Removed '${site}' from the public gallery.`);
|
|
312
363
|
}
|
|
313
364
|
);
|
|
314
365
|
server.registerTool(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uniquick",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "CLI + MCP server for UniQuick — deploy AI-built sites to the UIUC UniQuick platform with one prompt.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -39,5 +39,5 @@
|
|
|
39
39
|
"url": "https://github.com/gies-ai-experiments/uniquick.git",
|
|
40
40
|
"directory": "npm"
|
|
41
41
|
},
|
|
42
|
-
"homepage": "https://
|
|
42
|
+
"homepage": "https://quick.disruptionlab.illinois.edu"
|
|
43
43
|
}
|