loopshouse 0.2.0 → 0.2.1
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 +19 -19
- package/dist/loops.js +150 -28
- package/package.json +9 -3
package/README.md
CHANGED
|
@@ -46,25 +46,25 @@ listings); ideator conversations persist per hackathon in `~/.loops/sessions/`.
|
|
|
46
46
|
|
|
47
47
|
## Commands
|
|
48
48
|
|
|
49
|
-
| Group
|
|
50
|
-
|
|
51
|
-
| root
|
|
52
|
-
| `auth`
|
|
53
|
-
| `hackathon` | `ideate` (1 credit/turn; stateful session, `--withProject`, `--new`), `session` (show/`--clear`), `submit`
|
|
54
|
-
| `project`
|
|
55
|
-
| `knowledge` | `query` (1 credit/query — graph-RAG evidence from a sponsor's docs)
|
|
56
|
-
| `artifact`
|
|
57
|
-
| root
|
|
49
|
+
| Group | Commands |
|
|
50
|
+
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
+
| root | `add <slug> [sponsorSlug]` (interactive setup: CLI install/update, skill into agents, auth) |
|
|
52
|
+
| `auth` | `login`, `verify`, `status`, `logout` |
|
|
53
|
+
| `hackathon` | `ideate` (1 credit/turn; stateful session, `--withProject`, `--new`), `session` (show/`--clear`), `submit` |
|
|
54
|
+
| `project` | `get` (your one project for a hackathon), `create`, `update` (PATCH — only passed fields change; no project id, yours is resolved) |
|
|
55
|
+
| `knowledge` | `query` (1 credit/query — graph-RAG evidence from a sponsor's docs) |
|
|
56
|
+
| `artifact` | `list`, `save`, `update`, `remove` (ideation scratchpad) |
|
|
57
|
+
| root | `credits` (remaining agent credits), `evaluate` (per-sponsor evaluator prompt; your project auto-included) |
|
|
58
58
|
|
|
59
59
|
## Authentication
|
|
60
60
|
|
|
61
61
|
Auth uses Supabase Auth against the Loops platform. Three flows:
|
|
62
62
|
|
|
63
|
-
| Flow
|
|
64
|
-
|
|
65
|
-
| GitHub OAuth | `loops auth login --provider github`
|
|
66
|
-
| Google OAuth | `loops auth login --provider google`
|
|
67
|
-
| Email OTP
|
|
63
|
+
| Flow | Command |
|
|
64
|
+
| ------------ | --------------------------------------------------------------------------------------------- |
|
|
65
|
+
| GitHub OAuth | `loops auth login --provider github` |
|
|
66
|
+
| Google OAuth | `loops auth login --provider google` |
|
|
67
|
+
| Email OTP | `loops auth login --email you@x.com` then `loops auth verify --email you@x.com --code 123456` |
|
|
68
68
|
|
|
69
69
|
OAuth runs a localhost callback server (default port `54321`, `--port` to
|
|
70
70
|
change), opens your browser, and exchanges the PKCE code for a session.
|
|
@@ -82,11 +82,11 @@ loops --llms # print the machine-readable command manifest
|
|
|
82
82
|
|
|
83
83
|
## Configuration
|
|
84
84
|
|
|
85
|
-
| Env var
|
|
86
|
-
|
|
87
|
-
| `LOOPS_PLATFORM_URL`
|
|
88
|
-
| `LOOPS_SUPABASE_URL`
|
|
89
|
-
| `LOOPS_SUPABASE_ANON_KEY` | (baked)
|
|
85
|
+
| Env var | Default | Purpose |
|
|
86
|
+
| ------------------------- | ----------------------------------- | -------------------- |
|
|
87
|
+
| `LOOPS_PLATFORM_URL` | `https://loops-platform.vercel.app` | Platform API origin |
|
|
88
|
+
| `LOOPS_SUPABASE_URL` | (baked) | Supabase project URL |
|
|
89
|
+
| `LOOPS_SUPABASE_ANON_KEY` | (baked) | Supabase anon key |
|
|
90
90
|
|
|
91
91
|
Point these at `http://localhost:3000` + your local Supabase to develop against
|
|
92
92
|
a local stack.
|
package/dist/loops.js
CHANGED
|
@@ -50978,7 +50978,7 @@ import path4 from "node:path";
|
|
|
50978
50978
|
import fs4 from "node:fs";
|
|
50979
50979
|
var SUPABASE_URL = process.env.LOOPS_SUPABASE_URL ?? "https://ennlvrjxpqexvgfhfiaw.supabase.co";
|
|
50980
50980
|
var SUPABASE_ANON_KEY = process.env.LOOPS_SUPABASE_ANON_KEY ?? "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImVubmx2cmp4cHFleHZnZmhmaWF3Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NzgwOTY3NTEsImV4cCI6MjA5MzY3Mjc1MX0.chKog_0lD39fqQi7R8pwhvTLWxEdwNidS-_BFtlknXE";
|
|
50981
|
-
var VERSION = "0.2.
|
|
50981
|
+
var VERSION = "0.2.1";
|
|
50982
50982
|
var PLATFORM_URL = (process.env.LOOPS_PLATFORM_URL ?? "https://www.loops.house").replace(/\/+$/, "");
|
|
50983
50983
|
var CONFIG_DIR = path4.join(os4.homedir(), ".loops");
|
|
50984
50984
|
var CREDENTIALS_PATH = path4.join(CONFIG_DIR, "credentials.json");
|
|
@@ -51052,7 +51052,11 @@ var DEFAULT_CALLBACK_PORT = 54321;
|
|
|
51052
51052
|
function openBrowser(url2) {
|
|
51053
51053
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
51054
51054
|
try {
|
|
51055
|
-
const child = spawn(cmd, [url2], {
|
|
51055
|
+
const child = spawn(cmd, [url2], {
|
|
51056
|
+
stdio: "ignore",
|
|
51057
|
+
detached: true,
|
|
51058
|
+
shell: process.platform === "win32"
|
|
51059
|
+
});
|
|
51056
51060
|
child.on("error", () => {});
|
|
51057
51061
|
child.unref();
|
|
51058
51062
|
} catch {}
|
|
@@ -51104,6 +51108,11 @@ function callbackPage(ok, detail) {
|
|
|
51104
51108
|
}
|
|
51105
51109
|
function waitForOAuthCallback(port) {
|
|
51106
51110
|
return new Promise((resolve3) => {
|
|
51111
|
+
const finish = (result) => {
|
|
51112
|
+
clearTimeout(timer);
|
|
51113
|
+
server.close();
|
|
51114
|
+
resolve3(result);
|
|
51115
|
+
};
|
|
51107
51116
|
const server = createServer((req, res) => {
|
|
51108
51117
|
const reqUrl = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
51109
51118
|
if (reqUrl.pathname !== "/callback") {
|
|
@@ -51112,18 +51121,19 @@ function waitForOAuthCallback(port) {
|
|
|
51112
51121
|
}
|
|
51113
51122
|
const code = reqUrl.searchParams.get("code");
|
|
51114
51123
|
const errDetail = reqUrl.searchParams.get("error_description");
|
|
51115
|
-
res.writeHead(200, {
|
|
51116
|
-
|
|
51124
|
+
res.writeHead(200, {
|
|
51125
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
51126
|
+
Connection: "close"
|
|
51127
|
+
}).end(callbackPage(Boolean(code), errDetail ?? undefined));
|
|
51117
51128
|
if (code)
|
|
51118
|
-
|
|
51129
|
+
finish({ ok: true, code });
|
|
51119
51130
|
else
|
|
51120
|
-
|
|
51131
|
+
finish({ ok: false, message: errDetail || "No authorization code received" });
|
|
51121
51132
|
});
|
|
51122
|
-
server.on("error", (e) =>
|
|
51133
|
+
server.on("error", (e) => finish({ ok: false, message: `Loopback server failed: ${e.message}` }));
|
|
51123
51134
|
server.listen(port);
|
|
51124
|
-
setTimeout(() => {
|
|
51125
|
-
|
|
51126
|
-
resolve3({ ok: false, message: "Timed out waiting for the browser callback (2 min)" });
|
|
51135
|
+
const timer = setTimeout(() => {
|
|
51136
|
+
finish({ ok: false, message: "Timed out waiting for the browser callback (2 min)" });
|
|
51127
51137
|
}, 120000);
|
|
51128
51138
|
});
|
|
51129
51139
|
}
|
|
@@ -51177,13 +51187,55 @@ async function oauthLogin(provider, port, onUrl) {
|
|
|
51177
51187
|
});
|
|
51178
51188
|
return { email: sess.user?.email, userId: sess.user?.id };
|
|
51179
51189
|
}
|
|
51190
|
+
async function linkOAuthIdentity(provider, port, onUrl) {
|
|
51191
|
+
const creds = loadCredentials();
|
|
51192
|
+
if (!creds)
|
|
51193
|
+
throw new Error("Not signed in — run `loops auth login` first.");
|
|
51194
|
+
const supabase = createSupabase();
|
|
51195
|
+
const { error: sessErr } = await supabase.auth.setSession({
|
|
51196
|
+
access_token: creds.access_token,
|
|
51197
|
+
refresh_token: creds.refresh_token
|
|
51198
|
+
});
|
|
51199
|
+
if (sessErr)
|
|
51200
|
+
throw new Error(`Session expired — run \`loops auth login\` first (${sessErr.message})`);
|
|
51201
|
+
const redirectTo = `http://localhost:${port}/callback`;
|
|
51202
|
+
const { data, error: error51 } = await supabase.auth.linkIdentity({
|
|
51203
|
+
provider,
|
|
51204
|
+
options: {
|
|
51205
|
+
redirectTo,
|
|
51206
|
+
skipBrowserRedirect: true,
|
|
51207
|
+
queryParams: { prompt: "select_account" }
|
|
51208
|
+
}
|
|
51209
|
+
});
|
|
51210
|
+
if (error51 || !data?.url)
|
|
51211
|
+
throw new Error(error51?.message ?? "Failed to start identity linking");
|
|
51212
|
+
const callback = waitForOAuthCallback(port);
|
|
51213
|
+
onUrl?.(data.url);
|
|
51214
|
+
openBrowser(data.url);
|
|
51215
|
+
const result = await callback;
|
|
51216
|
+
if (!result.ok)
|
|
51217
|
+
throw new Error(result.message);
|
|
51218
|
+
const { data: sess, error: exErr } = await supabase.auth.exchangeCodeForSession(result.code);
|
|
51219
|
+
if (exErr || !sess.session)
|
|
51220
|
+
throw new Error(exErr?.message ?? "Code exchange failed");
|
|
51221
|
+
saveCredentials({
|
|
51222
|
+
access_token: sess.session.access_token,
|
|
51223
|
+
refresh_token: sess.session.refresh_token,
|
|
51224
|
+
expires_at: sess.session.expires_at
|
|
51225
|
+
});
|
|
51226
|
+
return {
|
|
51227
|
+
email: sess.user?.email,
|
|
51228
|
+
userId: sess.user?.id,
|
|
51229
|
+
identities: (sess.user?.identities ?? []).map((i) => i.provider)
|
|
51230
|
+
};
|
|
51231
|
+
}
|
|
51180
51232
|
var auth = exports_Cli.create("auth", {
|
|
51181
51233
|
description: "Authenticate with the Loops House platform"
|
|
51182
51234
|
});
|
|
51183
51235
|
auth.command("login", {
|
|
51184
51236
|
description: "Log in via browser OAuth (GitHub/Google) or an email one-time code",
|
|
51185
51237
|
options: exports_external.object({
|
|
51186
|
-
provider: exports_external.enum(["github", "google"]).optional().describe("OAuth provider (default
|
|
51238
|
+
provider: exports_external.enum(["github", "google"]).optional().describe("OAuth provider (default google). Ignored when --email is set."),
|
|
51187
51239
|
email: exports_external.string().email().optional().describe("Log in with an email one-time code instead of a browser"),
|
|
51188
51240
|
port: exports_external.number().default(DEFAULT_CALLBACK_PORT).describe("Local port for the OAuth callback server")
|
|
51189
51241
|
}),
|
|
@@ -51195,8 +51247,8 @@ auth.command("login", {
|
|
|
51195
51247
|
message: exports_external.string().optional()
|
|
51196
51248
|
}),
|
|
51197
51249
|
examples: [
|
|
51198
|
-
{ options: { provider: "github" }, description: "Log in with GitHub" },
|
|
51199
51250
|
{ options: { provider: "google" }, description: "Log in with Google" },
|
|
51251
|
+
{ options: { provider: "github" }, description: "Log in with GitHub" },
|
|
51200
51252
|
{ options: { email: "you@example.com" }, description: "Send an email one-time code" }
|
|
51201
51253
|
],
|
|
51202
51254
|
async run({ options, error: error51, agent }) {
|
|
@@ -51212,7 +51264,11 @@ auth.command("login", {
|
|
|
51212
51264
|
const res = await verifyOtp(options.email, code);
|
|
51213
51265
|
return { status: "authenticated", ...res };
|
|
51214
51266
|
} catch (e) {
|
|
51215
|
-
return error51({
|
|
51267
|
+
return error51({
|
|
51268
|
+
code: "OTP_VERIFY_FAILED",
|
|
51269
|
+
message: e.message,
|
|
51270
|
+
retryable: true
|
|
51271
|
+
});
|
|
51216
51272
|
}
|
|
51217
51273
|
}
|
|
51218
51274
|
return {
|
|
@@ -51221,7 +51277,7 @@ auth.command("login", {
|
|
|
51221
51277
|
message: `Code sent to ${options.email}. Verify with: loops auth verify --email ${options.email} --code <code>`
|
|
51222
51278
|
};
|
|
51223
51279
|
}
|
|
51224
|
-
const provider = options.provider ?? "
|
|
51280
|
+
const provider = options.provider ?? "google";
|
|
51225
51281
|
try {
|
|
51226
51282
|
const res = await oauthLogin(provider, options.port, (url2) => {
|
|
51227
51283
|
if (!agent) {
|
|
@@ -51250,7 +51306,10 @@ auth.command("verify", {
|
|
|
51250
51306
|
userId: exports_external.string().optional()
|
|
51251
51307
|
}),
|
|
51252
51308
|
examples: [
|
|
51253
|
-
{
|
|
51309
|
+
{
|
|
51310
|
+
options: { email: "you@example.com", code: "123456" },
|
|
51311
|
+
description: "Verify the emailed code"
|
|
51312
|
+
}
|
|
51254
51313
|
],
|
|
51255
51314
|
async run({ options, error: error51 }) {
|
|
51256
51315
|
try {
|
|
@@ -51261,6 +51320,41 @@ auth.command("verify", {
|
|
|
51261
51320
|
}
|
|
51262
51321
|
}
|
|
51263
51322
|
});
|
|
51323
|
+
auth.command("link", {
|
|
51324
|
+
description: "Attach a GitHub/Google identity to the account you're signed in to. Use when provider sign-in fails with 'multiple accounts with the same email' — after linking, that provider always signs in to THIS account.",
|
|
51325
|
+
options: exports_external.object({
|
|
51326
|
+
provider: exports_external.enum(["github", "google"]).describe("OAuth provider identity to link"),
|
|
51327
|
+
port: exports_external.number().default(DEFAULT_CALLBACK_PORT).describe("Local port for the OAuth callback server")
|
|
51328
|
+
}),
|
|
51329
|
+
alias: { provider: "p" },
|
|
51330
|
+
output: exports_external.object({
|
|
51331
|
+
status: exports_external.string(),
|
|
51332
|
+
email: exports_external.string().optional(),
|
|
51333
|
+
userId: exports_external.string().optional(),
|
|
51334
|
+
identities: exports_external.array(exports_external.string())
|
|
51335
|
+
}),
|
|
51336
|
+
examples: [
|
|
51337
|
+
{
|
|
51338
|
+
options: { provider: "github" },
|
|
51339
|
+
description: "Link your GitHub identity to the signed-in account"
|
|
51340
|
+
}
|
|
51341
|
+
],
|
|
51342
|
+
async run({ options, error: error51, agent }) {
|
|
51343
|
+
try {
|
|
51344
|
+
const res = await linkOAuthIdentity(options.provider, options.port, (url2) => {
|
|
51345
|
+
if (!agent) {
|
|
51346
|
+
console.error(`Opening browser to link your ${options.provider} identity…`);
|
|
51347
|
+
console.error(`If it doesn't open, visit:
|
|
51348
|
+
${url2}
|
|
51349
|
+
`);
|
|
51350
|
+
}
|
|
51351
|
+
});
|
|
51352
|
+
return { status: "linked", ...res };
|
|
51353
|
+
} catch (e) {
|
|
51354
|
+
return error51({ code: "LINK_FAILED", message: e.message, retryable: true });
|
|
51355
|
+
}
|
|
51356
|
+
}
|
|
51357
|
+
});
|
|
51264
51358
|
auth.command("status", {
|
|
51265
51359
|
description: "Show the current authentication status",
|
|
51266
51360
|
output: exports_external.object({
|
|
@@ -51293,7 +51387,11 @@ var NOT_AUTHENTICATED = {
|
|
|
51293
51387
|
description: "To authenticate:",
|
|
51294
51388
|
commands: [
|
|
51295
51389
|
{ command: "auth login", description: "Log in via GitHub or Google (browser)" },
|
|
51296
|
-
{
|
|
51390
|
+
{
|
|
51391
|
+
command: "auth login",
|
|
51392
|
+
options: { email: true },
|
|
51393
|
+
description: "Log in with an email one-time code"
|
|
51394
|
+
}
|
|
51297
51395
|
]
|
|
51298
51396
|
}
|
|
51299
51397
|
};
|
|
@@ -51491,7 +51589,10 @@ hackathon.command("ideate", {
|
|
|
51491
51589
|
output: exports_external.object({ response: exports_external.string(), sessionTurns: exports_external.number() }),
|
|
51492
51590
|
examples: [
|
|
51493
51591
|
{
|
|
51494
|
-
options: {
|
|
51592
|
+
options: {
|
|
51593
|
+
hackathonSlug: "my-hackathon",
|
|
51594
|
+
message: "Suggest a project using the sponsor APIs"
|
|
51595
|
+
},
|
|
51495
51596
|
description: "Ask the mentor for an idea"
|
|
51496
51597
|
},
|
|
51497
51598
|
{
|
|
@@ -51560,7 +51661,11 @@ hackathon.command("submit", {
|
|
|
51560
51661
|
output: submissionOutput,
|
|
51561
51662
|
examples: [
|
|
51562
51663
|
{
|
|
51563
|
-
options: {
|
|
51664
|
+
options: {
|
|
51665
|
+
hackathonSlug: "my-hackathon",
|
|
51666
|
+
name: "My Project",
|
|
51667
|
+
repoUrl: "https://github.com/me/proj"
|
|
51668
|
+
},
|
|
51564
51669
|
description: "Submit a project"
|
|
51565
51670
|
}
|
|
51566
51671
|
],
|
|
@@ -51612,9 +51717,7 @@ project.command("get", {
|
|
|
51612
51717
|
exists: exports_external.boolean(),
|
|
51613
51718
|
project: projectShape.nullable()
|
|
51614
51719
|
}),
|
|
51615
|
-
examples: [
|
|
51616
|
-
{ options: { hackathonSlug: "my-hackathon" }, description: "Look up your project" }
|
|
51617
|
-
],
|
|
51720
|
+
examples: [{ options: { hackathonSlug: "my-hackathon" }, description: "Look up your project" }],
|
|
51618
51721
|
run: authed(async ({ options, session, ok }) => {
|
|
51619
51722
|
const result = await apiGet(session.accessToken, `/api/v1/hackathons/${options.hackathonSlug}/my-project`);
|
|
51620
51723
|
return ok(result, {
|
|
@@ -51699,7 +51802,9 @@ knowledge.command("query", {
|
|
|
51699
51802
|
hackathonSlug: exports_external.string().describe("Hackathon slug the sponsor belongs to"),
|
|
51700
51803
|
sponsorSlug: exports_external.string().describe("Sponsor slug whose knowledge graph to query"),
|
|
51701
51804
|
query: exports_external.string().describe("A focused question about the sponsor's products, docs, or SDKs"),
|
|
51702
|
-
mode: exports_external.enum(["mix", "local", "global", "hybrid", "naive", "bypass"]).optional().describe("'mix' = balanced (default), 'local' = entity-centric, 'global' = relation-centric")
|
|
51805
|
+
mode: exports_external.enum(["mix", "local", "global", "hybrid", "naive", "bypass"]).optional().describe("'mix' = balanced (default), 'local' = entity-centric, 'global' = relation-centric"),
|
|
51806
|
+
hlKeywords: exports_external.array(exports_external.string()).optional().describe("2-5 high-level concept keywords — supplying them skips a server-side LLM call"),
|
|
51807
|
+
llKeywords: exports_external.array(exports_external.string()).optional().describe("2-5 specific low-level terms (APIs, product names) that focus retrieval")
|
|
51703
51808
|
}),
|
|
51704
51809
|
alias: { sponsorSlug: "s", query: "q" },
|
|
51705
51810
|
output: exports_external.object({ evidence: exports_external.string() }),
|
|
@@ -51713,7 +51818,12 @@ knowledge.command("query", {
|
|
|
51713
51818
|
description: "Ask about a sponsor's SDK"
|
|
51714
51819
|
}
|
|
51715
51820
|
],
|
|
51716
|
-
run: authed(({ options, session }) => apiPost(session.accessToken, `/api/v1/hackathons/${options.hackathonSlug}/sponsors/${options.sponsorSlug}/knowledge/query`, {
|
|
51821
|
+
run: authed(({ options, session }) => apiPost(session.accessToken, `/api/v1/hackathons/${options.hackathonSlug}/sponsors/${options.sponsorSlug}/knowledge/query`, {
|
|
51822
|
+
query: options.query,
|
|
51823
|
+
mode: options.mode,
|
|
51824
|
+
hlKeywords: options.hlKeywords,
|
|
51825
|
+
llKeywords: options.llKeywords
|
|
51826
|
+
}))
|
|
51717
51827
|
});
|
|
51718
51828
|
|
|
51719
51829
|
// src/artifact.ts
|
|
@@ -53496,7 +53606,11 @@ var TARGETS = {
|
|
|
53496
53606
|
};
|
|
53497
53607
|
var ALL_TARGETS = Object.keys(TARGETS);
|
|
53498
53608
|
function npm(args, timeout = 60000) {
|
|
53499
|
-
const r2 = spawnSync("npm", args, {
|
|
53609
|
+
const r2 = spawnSync("npm", args, {
|
|
53610
|
+
encoding: "utf8",
|
|
53611
|
+
timeout,
|
|
53612
|
+
shell: process.platform === "win32"
|
|
53613
|
+
});
|
|
53500
53614
|
return { ok: r2.status === 0, stdout: r2.stdout ?? "" };
|
|
53501
53615
|
}
|
|
53502
53616
|
function globalCliVersion() {
|
|
@@ -53669,7 +53783,7 @@ var cli = exports_Cli.create("loops", {
|
|
|
53669
53783
|
description: "Loops House CLI — authenticate, ideate with AI, query sponsor knowledge graphs, and submit projects from your terminal or AI agent. Scoped to one hackathon at a time.",
|
|
53670
53784
|
sync: {
|
|
53671
53785
|
suggestions: [
|
|
53672
|
-
"log in to loops with
|
|
53786
|
+
"log in to loops with google",
|
|
53673
53787
|
"ideate a project for a hackathon",
|
|
53674
53788
|
"query a sponsor's knowledge graph",
|
|
53675
53789
|
"evaluate my project against a sponsor"
|
|
@@ -53702,8 +53816,15 @@ cli.command("add", {
|
|
|
53702
53816
|
}),
|
|
53703
53817
|
examples: [
|
|
53704
53818
|
{ args: { hackathonSlug: "my-hackathon" }, description: "Interactive setup for a hackathon" },
|
|
53705
|
-
{
|
|
53706
|
-
|
|
53819
|
+
{
|
|
53820
|
+
args: { hackathonSlug: "my-hackathon", sponsorSlug: "acme" },
|
|
53821
|
+
description: "Install Acme's sponsor-focused skill"
|
|
53822
|
+
},
|
|
53823
|
+
{
|
|
53824
|
+
args: { hackathonSlug: "my-hackathon" },
|
|
53825
|
+
options: { yes: true },
|
|
53826
|
+
description: "Non-interactive, defaults"
|
|
53827
|
+
}
|
|
53707
53828
|
],
|
|
53708
53829
|
run: ({ args, options, error: error51 }) => runAdd(args.hackathonSlug, args.sponsorSlug, options, error51)
|
|
53709
53830
|
});
|
|
@@ -53749,4 +53870,5 @@ cli.command("evaluate", {
|
|
|
53749
53870
|
});
|
|
53750
53871
|
})
|
|
53751
53872
|
});
|
|
53752
|
-
cli.serve();
|
|
53873
|
+
await cli.serve();
|
|
53874
|
+
process.exit();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loopshouse",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Loops House CLI — manage hackathon projects, ideate with AI, query sponsor knowledge graphs, and submit from your terminal or AI agent",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,7 +19,10 @@
|
|
|
19
19
|
"dev": "bun run bin/loops.ts",
|
|
20
20
|
"build": "bun build bin/loops.ts --outdir dist --target node && node -e \"const fs=require('fs');const f='dist/loops.js';let c=fs.readFileSync(f,'utf8').replace(/^#!.*\\n/,'');fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c);fs.chmodSync(f,0o755)\"",
|
|
21
21
|
"typecheck": "tsc --noEmit",
|
|
22
|
-
"prepublishOnly": "bun run build"
|
|
22
|
+
"prepublishOnly": "bun run build",
|
|
23
|
+
"lint": "eslint . --max-warnings=0",
|
|
24
|
+
"format": "prettier --write .",
|
|
25
|
+
"format:check": "prettier --check ."
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
25
28
|
"@clack/prompts": "^1.5.1",
|
|
@@ -29,6 +32,9 @@
|
|
|
29
32
|
},
|
|
30
33
|
"devDependencies": {
|
|
31
34
|
"@types/node": "^20",
|
|
32
|
-
"
|
|
35
|
+
"eslint": "^10.4.1",
|
|
36
|
+
"prettier": "^3.8.4",
|
|
37
|
+
"typescript": "^5",
|
|
38
|
+
"typescript-eslint": "^8.61.0"
|
|
33
39
|
}
|
|
34
40
|
}
|