@femtomc/mu 0.1.0 → 26.2.14
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/index.d.ts.map +1 -1
- package/dist/index.js +110 -0
- package/package.json +7 -5
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,SAAS,GAAG;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CACjB,CAAC;AA6PF,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,IAAI,GAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,OAAO,CAAC,SAAS,CAAC,CAsCzF"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
1
2
|
import { existsSync } from "node:fs";
|
|
2
3
|
import { mkdir, readdir, readFile, writeFile } from "node:fs/promises";
|
|
3
4
|
import { dirname, join, relative, resolve } from "node:path";
|
|
@@ -209,6 +210,7 @@ function mainHelp() {
|
|
|
209
210
|
" forum <subcmd> Forum commands (JSON)",
|
|
210
211
|
" run <prompt...> Create root + run DAG loop",
|
|
211
212
|
" resume <root-id> Resume a DAG loop",
|
|
213
|
+
" login [<provider>] [--list] Authenticate with an AI provider",
|
|
212
214
|
" replay <id|path> [--backend pi] Replay a logged run (pi-only)",
|
|
213
215
|
"",
|
|
214
216
|
"Run `mu <command> --help` for details.",
|
|
@@ -240,6 +242,8 @@ export async function run(argv, opts = {}) {
|
|
|
240
242
|
return await cmdRun(rest, ctx);
|
|
241
243
|
case "resume":
|
|
242
244
|
return await cmdResume(rest, ctx);
|
|
245
|
+
case "login":
|
|
246
|
+
return await cmdLogin(rest);
|
|
243
247
|
case "replay":
|
|
244
248
|
return await cmdReplay(rest, ctx);
|
|
245
249
|
default:
|
|
@@ -1130,3 +1134,109 @@ async function cmdReplay(argv, ctx) {
|
|
|
1130
1134
|
const text = await readFile(path, "utf8");
|
|
1131
1135
|
return ok(text.length > 0 && !text.endsWith("\n") ? `${text}\n` : text);
|
|
1132
1136
|
}
|
|
1137
|
+
function readLine(prompt) {
|
|
1138
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
1139
|
+
return new Promise((resolve) => {
|
|
1140
|
+
rl.question(prompt, (answer) => {
|
|
1141
|
+
rl.close();
|
|
1142
|
+
resolve(answer);
|
|
1143
|
+
});
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
async function cmdLogin(argv) {
|
|
1147
|
+
if (hasHelpFlag(argv)) {
|
|
1148
|
+
return ok([
|
|
1149
|
+
"mu login - authenticate with an AI provider via OAuth",
|
|
1150
|
+
"",
|
|
1151
|
+
"Usage:",
|
|
1152
|
+
" mu login [<provider>] [--list] [--logout]",
|
|
1153
|
+
"",
|
|
1154
|
+
"Examples:",
|
|
1155
|
+
" mu login --list List available OAuth providers",
|
|
1156
|
+
" mu login openai-codex Login to OpenAI (ChatGPT Plus)",
|
|
1157
|
+
" mu login anthropic Login to Anthropic (Claude Pro/Max)",
|
|
1158
|
+
" mu login github-copilot Login to GitHub Copilot",
|
|
1159
|
+
" mu login google-gemini-cli Login to Google Gemini CLI",
|
|
1160
|
+
" mu login openai-codex --logout Remove stored credentials",
|
|
1161
|
+
"",
|
|
1162
|
+
"Credentials are stored in ~/.pi/agent/auth.json (shared with pi CLI).",
|
|
1163
|
+
].join("\n") + "\n");
|
|
1164
|
+
}
|
|
1165
|
+
// Lazy-import pi SDK to avoid loading it for every mu command.
|
|
1166
|
+
const { AuthStorage } = await import("@mariozechner/pi-coding-agent");
|
|
1167
|
+
const { getOAuthProviders } = await import("@mariozechner/pi-ai");
|
|
1168
|
+
const authStorage = new AuthStorage();
|
|
1169
|
+
const providers = getOAuthProviders();
|
|
1170
|
+
const { present: listMode, rest: argv0 } = popFlag(argv, "--list");
|
|
1171
|
+
const { present: logoutMode, rest: argv1 } = popFlag(argv0, "--logout");
|
|
1172
|
+
if (listMode || argv1.length === 0) {
|
|
1173
|
+
const lines = ["Available OAuth providers:", ""];
|
|
1174
|
+
for (const p of providers) {
|
|
1175
|
+
const hasAuth = authStorage.hasAuth(p.id);
|
|
1176
|
+
const status = hasAuth ? "[authenticated]" : "[not configured]";
|
|
1177
|
+
lines.push(` ${p.id.padEnd(24)} ${p.name.padEnd(30)} ${status}`);
|
|
1178
|
+
}
|
|
1179
|
+
lines.push("", "Environment variable auth (no login needed):");
|
|
1180
|
+
lines.push(" Set OPENAI_API_KEY, ANTHROPIC_API_KEY, GOOGLE_API_KEY, etc.");
|
|
1181
|
+
return ok(`${lines.join("\n")}\n`);
|
|
1182
|
+
}
|
|
1183
|
+
const providerId = argv1[0];
|
|
1184
|
+
const rest = argv1.slice(1);
|
|
1185
|
+
if (rest.length > 0) {
|
|
1186
|
+
return jsonError(`unknown args: ${rest.join(" ")}`, { recovery: ["mu login --help"] });
|
|
1187
|
+
}
|
|
1188
|
+
const provider = providers.find((p) => p.id === providerId);
|
|
1189
|
+
if (!provider) {
|
|
1190
|
+
const available = providers.map((p) => p.id).join(", ");
|
|
1191
|
+
return jsonError(`unknown provider: ${providerId}`, {
|
|
1192
|
+
recovery: [`mu login --list`, `Available: ${available}`],
|
|
1193
|
+
});
|
|
1194
|
+
}
|
|
1195
|
+
if (logoutMode) {
|
|
1196
|
+
authStorage.logout(providerId);
|
|
1197
|
+
return ok(`Logged out from ${provider.name} (${providerId})\n`);
|
|
1198
|
+
}
|
|
1199
|
+
try {
|
|
1200
|
+
await authStorage.login(providerId, {
|
|
1201
|
+
onAuth: (info) => {
|
|
1202
|
+
process.stderr.write(`\nOpen this URL to authenticate:\n ${info.url}\n\n`);
|
|
1203
|
+
if (info.instructions) {
|
|
1204
|
+
process.stderr.write(`${info.instructions}\n\n`);
|
|
1205
|
+
}
|
|
1206
|
+
// Try to open browser automatically.
|
|
1207
|
+
const open = (cmd, args) => {
|
|
1208
|
+
try {
|
|
1209
|
+
const { spawn } = require("node:child_process");
|
|
1210
|
+
spawn(cmd, args, { detached: true, stdio: "ignore" }).unref();
|
|
1211
|
+
}
|
|
1212
|
+
catch { }
|
|
1213
|
+
};
|
|
1214
|
+
if (process.platform === "darwin") {
|
|
1215
|
+
open("open", [info.url]);
|
|
1216
|
+
}
|
|
1217
|
+
else if (process.platform === "linux") {
|
|
1218
|
+
open("xdg-open", [info.url]);
|
|
1219
|
+
}
|
|
1220
|
+
},
|
|
1221
|
+
onPrompt: async (prompt) => {
|
|
1222
|
+
const msg = prompt.placeholder ? `${prompt.message} [${prompt.placeholder}]: ` : `${prompt.message}: `;
|
|
1223
|
+
const answer = await readLine(msg);
|
|
1224
|
+
if (!answer && prompt.placeholder)
|
|
1225
|
+
return prompt.placeholder;
|
|
1226
|
+
return answer;
|
|
1227
|
+
},
|
|
1228
|
+
onProgress: (message) => {
|
|
1229
|
+
process.stderr.write(`${message}\n`);
|
|
1230
|
+
},
|
|
1231
|
+
onManualCodeInput: async () => {
|
|
1232
|
+
return await readLine("Paste the authorization code or callback URL: ");
|
|
1233
|
+
},
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
catch (err) {
|
|
1237
|
+
return jsonError(`login failed: ${err instanceof Error ? err.message : String(err)}`, {
|
|
1238
|
+
recovery: [`mu login ${providerId}`],
|
|
1239
|
+
});
|
|
1240
|
+
}
|
|
1241
|
+
return ok(`Authenticated with ${provider.name} (${providerId})\n`);
|
|
1242
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@femtomc/mu",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.2.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"mu": "./dist/cli.js"
|
|
@@ -15,9 +15,11 @@
|
|
|
15
15
|
},
|
|
16
16
|
"files": ["dist/**"],
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@femtomc/mu-core": "
|
|
19
|
-
"@femtomc/mu-forum": "
|
|
20
|
-
"@femtomc/mu-issue": "
|
|
21
|
-
"@femtomc/mu-orchestrator": "
|
|
18
|
+
"@femtomc/mu-core": "26.2.14",
|
|
19
|
+
"@femtomc/mu-forum": "26.2.14",
|
|
20
|
+
"@femtomc/mu-issue": "26.2.14",
|
|
21
|
+
"@femtomc/mu-orchestrator": "26.2.14",
|
|
22
|
+
"@mariozechner/pi-coding-agent": "^0.52.12",
|
|
23
|
+
"@mariozechner/pi-ai": "^0.52.12"
|
|
22
24
|
}
|
|
23
25
|
}
|