@mnemonik/cli 7.107.3 → 7.108.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/dist/auth/status.d.ts +11 -0
- package/dist/auth/status.d.ts.map +1 -1
- package/dist/auth/status.js +32 -1
- package/dist/auth/status.js.map +1 -1
- package/dist/digests.json +31 -31
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +28 -4
- package/dist/help.js.map +1 -1
- package/dist/humanReason.d.ts.map +1 -1
- package/dist/humanReason.js +17 -2
- package/dist/humanReason.js.map +1 -1
- package/dist/output.d.ts +2 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +6 -0
- package/dist/output.js.map +1 -1
- package/dist/project.d.ts +4 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +39 -31
- package/dist/project.js.map +1 -1
- package/dist/router.d.ts +3 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +239 -71
- package/dist/router.js.map +1 -1
- package/dist/sbom.json +21 -21
- package/dist/scanner/control.d.ts +1 -1
- package/dist/scanner/control.d.ts.map +1 -1
- package/dist/scanner/control.js.map +1 -1
- package/dist/scanner-release.json +27 -27
- package/dist/transport/server.d.ts +14 -0
- package/dist/transport/server.d.ts.map +1 -1
- package/dist/transport/server.js +24 -6
- package/dist/transport/server.js.map +1 -1
- package/package.json +31 -31
package/dist/router.js
CHANGED
|
@@ -5271,7 +5271,8 @@ import {
|
|
|
5271
5271
|
runProjectCommand
|
|
5272
5272
|
} from "./project.js";
|
|
5273
5273
|
import { evaluateRoot } from "./project/eligibility.js";
|
|
5274
|
-
import {
|
|
5274
|
+
import { accountActions } from "./transport/server.js";
|
|
5275
|
+
import { grantTransport, grantHost, grantSummaryLines } from "./auth/status.js";
|
|
5275
5276
|
import { createCliAuth } from "./auth/index.js";
|
|
5276
5277
|
import { runEditorLogin } from "./auth/pkce.js";
|
|
5277
5278
|
import { currentInstallSession, ensureInstallSession } from "./auth/installSession.js";
|
|
@@ -5307,6 +5308,51 @@ var removedFolderLine = (name2) => ` \u2713 ${name2} is no longer connected.`;
|
|
|
5307
5308
|
var projectDeletionWarning = (name2) => `Deleting ${name2} removes its memories, code index and summaries for everyone. This cannot be undone.`;
|
|
5308
5309
|
var projectDeletedLine = (name2) => `Deleted ${name2}.`;
|
|
5309
5310
|
var NOTHING_DELETED_LINE = "Nothing was deleted.";
|
|
5311
|
+
var NOTHING_REMOVED_LINE = "Nothing was removed.";
|
|
5312
|
+
var SCANNER_UNINSTALL_PROMPT = "Uninstalling background indexing means your code on this machine is no longer\nindexed. Agents here lose code search and file context until you set it up\nagain with mnemonik scanner enable. This also withdraws your indexing consent\nfor this machine. Type yes to continue.";
|
|
5313
|
+
var SCANNER_REMOVED_LINE = "Background indexing removed from this machine.";
|
|
5314
|
+
async function revokeScannerCredential(deps, output, stateDir, saved) {
|
|
5315
|
+
const state = saved ?? JSON.parse(await readFile3(`${stateDir}/scanner/state.json`, "utf8"));
|
|
5316
|
+
const bearer = await ensureCliAuth(deps, output, false);
|
|
5317
|
+
const response = await (deps.grantFetch ?? fetch)(
|
|
5318
|
+
`${apiOrigin()}/api/v1/component-credentials/${encodeURIComponent(state.config.credentialFamilyId)}/revoke`,
|
|
5319
|
+
{ method: "POST", headers: { Authorization: `Bearer ${bearer}` } }
|
|
5320
|
+
);
|
|
5321
|
+
if (!response.ok) throw new Error(`revoke_failed_${response.status}`);
|
|
5322
|
+
}
|
|
5323
|
+
async function confirmScannerOptOut(parsed, deps, output) {
|
|
5324
|
+
if (parsed.flags.has("confirm")) return void 0;
|
|
5325
|
+
if (parsed.flags.has("json") || parsed.flags.has("non-interactive"))
|
|
5326
|
+
return actionRequired2(output, parsed.flags.has("json"), "Rerun with --confirm", "--confirm");
|
|
5327
|
+
output.line(SCANNER_UNINSTALL_PROMPT);
|
|
5328
|
+
const readline = createInterface({ input: deps.input ?? process.stdin, terminal: false });
|
|
5329
|
+
const answer = String((await readline[Symbol.asyncIterator]().next()).value ?? "").trim();
|
|
5330
|
+
readline.close();
|
|
5331
|
+
if (/^(?:y|yes)$/iu.test(answer)) return void 0;
|
|
5332
|
+
output.line(NOTHING_REMOVED_LINE);
|
|
5333
|
+
return 130;
|
|
5334
|
+
}
|
|
5335
|
+
async function uninstallScannerOptOut(deps, output, service, json) {
|
|
5336
|
+
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
5337
|
+
const saved = await readFile3(`${stateDir}/scanner/state.json`, "utf8").then(
|
|
5338
|
+
(text) => JSON.parse(text),
|
|
5339
|
+
(error) => {
|
|
5340
|
+
if (error.code === "ENOENT") return void 0;
|
|
5341
|
+
throw error;
|
|
5342
|
+
}
|
|
5343
|
+
);
|
|
5344
|
+
if (saved)
|
|
5345
|
+
try {
|
|
5346
|
+
await revokeScannerCredential(deps, output, stateDir, saved);
|
|
5347
|
+
} catch (error) {
|
|
5348
|
+
output.error(humanReason(error.message));
|
|
5349
|
+
return 3;
|
|
5350
|
+
}
|
|
5351
|
+
await service.uninstall();
|
|
5352
|
+
if (json) output.json({ status: "uninstalled", consent: saved ? "withdrawn" : "none" });
|
|
5353
|
+
else output.line(SCANNER_REMOVED_LINE);
|
|
5354
|
+
return 0;
|
|
5355
|
+
}
|
|
5310
5356
|
var dataDeletePrompt = (projectId) => `This deletes everything background indexing has sent for ${projectId} from your account. Type yes to continue.`;
|
|
5311
5357
|
var stillWatchedLine = (root) => `The folder is still being indexed. Run mnemonik remove ${root} to stop that.`;
|
|
5312
5358
|
var identityFileKeptLine = "This folder's .mnemonik.json still points at the deleted project. Connecting the folder again creates a new project.";
|
|
@@ -5364,6 +5410,9 @@ var values = /* @__PURE__ */ new Set([
|
|
|
5364
5410
|
]);
|
|
5365
5411
|
var help = helpScreen([]) ?? "";
|
|
5366
5412
|
function parse(args2) {
|
|
5413
|
+
return { ...parseArguments(args2), json: args2.includes("--json") };
|
|
5414
|
+
}
|
|
5415
|
+
function parseArguments(args2) {
|
|
5367
5416
|
const positionals = [];
|
|
5368
5417
|
const flags2 = /* @__PURE__ */ new Map();
|
|
5369
5418
|
const namedConfirm = args2[0] === "project" && args2[1] === "delete";
|
|
@@ -5404,6 +5453,42 @@ function parse(args2) {
|
|
|
5404
5453
|
}
|
|
5405
5454
|
return { positionals, flags: flags2 };
|
|
5406
5455
|
}
|
|
5456
|
+
function commandPath(positionals) {
|
|
5457
|
+
for (let length = positionals.length; length > 0; length--)
|
|
5458
|
+
if (helpScreen(positionals.slice(0, length))) return positionals.slice(0, length);
|
|
5459
|
+
return [];
|
|
5460
|
+
}
|
|
5461
|
+
function usageFailure(output, parsed, failure, human) {
|
|
5462
|
+
if (parsed.json) {
|
|
5463
|
+
const command = failure.reason === "unknown_command" ? parsed.positionals[0] ?? "" : (failure.path ?? commandPath(parsed.positionals)).join(" ");
|
|
5464
|
+
output.json({
|
|
5465
|
+
status: "usage_error",
|
|
5466
|
+
reason: failure.reason,
|
|
5467
|
+
command,
|
|
5468
|
+
...failure.detail ? { detail: failure.detail } : {},
|
|
5469
|
+
action: failure.reason === "unknown_command" || !command ? "mnemonik --help" : `mnemonik ${command} --help`
|
|
5470
|
+
});
|
|
5471
|
+
} else if (typeof human === "string") output.error(human);
|
|
5472
|
+
else human();
|
|
5473
|
+
return 2;
|
|
5474
|
+
}
|
|
5475
|
+
function flagError(output, parsed, message) {
|
|
5476
|
+
const [, kind, detail] = /^(Unknown flag|Missing value for flag)(?: combination)?: (\S+)/u.exec(
|
|
5477
|
+
message
|
|
5478
|
+
) ?? [void 0, "Unknown flag"];
|
|
5479
|
+
const reason = kind === "Unknown flag" ? "invalid_flag" : "invalid_value";
|
|
5480
|
+
return usageFailure(output, parsed, { reason, detail }, message);
|
|
5481
|
+
}
|
|
5482
|
+
function usageReason(positionals, path) {
|
|
5483
|
+
if (!path.length) return { reason: "unknown_command" };
|
|
5484
|
+
for (let index = 1; index < path.length; index++)
|
|
5485
|
+
if (positionals[index] !== path[index])
|
|
5486
|
+
return positionals[index] === void 0 ? { reason: index === 1 ? "missing_subcommand" : "missing_argument" } : { reason: "unknown_subcommand", detail: positionals[index] };
|
|
5487
|
+
const extra = positionals[path.length];
|
|
5488
|
+
if (extra !== void 0)
|
|
5489
|
+
return { reason: path.length === 1 ? "unknown_subcommand" : "invalid_value", detail: extra };
|
|
5490
|
+
return { reason: path.length === 1 ? "missing_subcommand" : "missing_argument" };
|
|
5491
|
+
}
|
|
5407
5492
|
function allowed(parsed, names) {
|
|
5408
5493
|
const permitted = /* @__PURE__ */ new Set(["json", "non-interactive", "no-browser", "help", ...names]);
|
|
5409
5494
|
for (const name2 of parsed.flags.keys())
|
|
@@ -5444,9 +5529,9 @@ function auth(deps, output, noBrowser) {
|
|
|
5444
5529
|
print: (line) => output.line(line)
|
|
5445
5530
|
});
|
|
5446
5531
|
}
|
|
5447
|
-
async function ensureCliAuth(deps, output, noBrowser, showIdentity = true) {
|
|
5532
|
+
async function ensureCliAuth(deps, output, noBrowser, showIdentity = true, fresh = false) {
|
|
5448
5533
|
const cliAuth = auth(deps, output, noBrowser);
|
|
5449
|
-
let bearer = await cliAuth.getCliBearer().catch((error) => {
|
|
5534
|
+
let bearer = fresh ? { status: "ACTION_REQUIRED", reason: "renew" } : await cliAuth.getCliBearer().catch((error) => {
|
|
5450
5535
|
if (isCredentialSessionUnavailableError(error))
|
|
5451
5536
|
return { status: "ACTION_REQUIRED", reason: error.reason };
|
|
5452
5537
|
throw error;
|
|
@@ -5507,13 +5592,27 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5507
5592
|
const component = parsed.flags.get("component");
|
|
5508
5593
|
const fullUninstall = command === "uninstall" && !host && !component;
|
|
5509
5594
|
if (host && !hostOrder.includes(host) || component && !["hooks", "mcp"].includes(String(component)))
|
|
5510
|
-
return
|
|
5595
|
+
return usageFailure(
|
|
5596
|
+
output,
|
|
5597
|
+
parsed,
|
|
5598
|
+
{
|
|
5599
|
+
reason: "invalid_value",
|
|
5600
|
+
detail: String(host && !hostOrder.includes(host) ? host : component)
|
|
5601
|
+
},
|
|
5602
|
+
"Invalid host or component"
|
|
5603
|
+
);
|
|
5511
5604
|
if (command === "uninstall") await abandonInterrupted(state);
|
|
5512
5605
|
let selections;
|
|
5513
5606
|
if (command === "install") {
|
|
5514
5607
|
const names = String(parsed.flags.get("hosts") ?? hostOrder.join(",")).split(",");
|
|
5515
|
-
|
|
5516
|
-
|
|
5608
|
+
const unknownHost = names.find((name2) => !hostOrder.includes(name2));
|
|
5609
|
+
if (unknownHost !== void 0)
|
|
5610
|
+
return usageFailure(
|
|
5611
|
+
output,
|
|
5612
|
+
parsed,
|
|
5613
|
+
{ reason: "invalid_value", detail: unknownHost },
|
|
5614
|
+
"Invalid hosts"
|
|
5615
|
+
);
|
|
5517
5616
|
const components = String(parsed.flags.get("components") ?? "hooks,mcp").split(",");
|
|
5518
5617
|
if (components.some((c) => !["hooks", "mcp"].includes(c)))
|
|
5519
5618
|
return placeholder(output, json, "install scanner", "scanner setup");
|
|
@@ -5843,7 +5942,7 @@ async function installCommand(parsed, deps, output) {
|
|
|
5843
5942
|
"no-browser",
|
|
5844
5943
|
"dry-run"
|
|
5845
5944
|
]);
|
|
5846
|
-
if (invalid) return output
|
|
5945
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
5847
5946
|
if (!deps.install && !parsed.flags.has("dry-run")) {
|
|
5848
5947
|
const { joinedInstall } = await import("./install/journey.js");
|
|
5849
5948
|
const state = deps.hostManagement?.stateDir ?? deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
@@ -5895,7 +5994,7 @@ function refusalStateDir(deps) {
|
|
|
5895
5994
|
}
|
|
5896
5995
|
async function doctorCommand(parsed, deps, output) {
|
|
5897
5996
|
const invalid = allowed(parsed, []);
|
|
5898
|
-
if (invalid) return output
|
|
5997
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
5899
5998
|
const result = await runPreflight({ cwd: deps.cwd, home: deps.home, ...deps.preflight });
|
|
5900
5999
|
output.setContext({ home: deps.home ?? homedir3(), projectRoot: result.project.root });
|
|
5901
6000
|
const document = await collectStatusDocument({
|
|
@@ -5926,6 +6025,7 @@ async function doctorCommand(parsed, deps, output) {
|
|
|
5926
6025
|
renderStatusSummaries(document, output, { diagnostics: true });
|
|
5927
6026
|
await renderRefusals(refusalStateDir(deps), output, true);
|
|
5928
6027
|
}
|
|
6028
|
+
await reportCurrentInstallation(deps, output);
|
|
5929
6029
|
return document.installation.state === "READY" ? 0 : document.installation.state === "FAILED" ? 1 : 3;
|
|
5930
6030
|
}
|
|
5931
6031
|
async function collectCurrentInstallation(deps, output) {
|
|
@@ -6000,9 +6100,11 @@ async function deleteProjectCommand(parsed, rest, deps, output) {
|
|
|
6000
6100
|
const send = deps.grantFetch ?? fetch;
|
|
6001
6101
|
const listed = await send(`${apiOrigin()}/api/v1/users/me/projects?days=0&limit=200`, {
|
|
6002
6102
|
headers: { Authorization: `Bearer ${bearer}` }
|
|
6003
|
-
});
|
|
6004
|
-
if (!listed
|
|
6005
|
-
|
|
6103
|
+
}).catch(() => void 0);
|
|
6104
|
+
if (!listed?.ok) {
|
|
6105
|
+
const reason = !listed ? "unreachable" : listed.status === 401 || listed.status === 403 ? "renew" : "server_error";
|
|
6106
|
+
if (json) output.json({ status: "action_required", reason, action: accountActions[reason] });
|
|
6107
|
+
else output.error(humanReason(reason));
|
|
6006
6108
|
return 3;
|
|
6007
6109
|
}
|
|
6008
6110
|
const listing = await listed.json().catch(() => []);
|
|
@@ -6085,10 +6187,19 @@ async function runCli(args2, deps = {}) {
|
|
|
6085
6187
|
const output = new Output(stdout, stderr, {
|
|
6086
6188
|
home: deps.home ?? homedir3()
|
|
6087
6189
|
});
|
|
6088
|
-
const usageError = (positionals
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6190
|
+
const usageError = (positionals, failure = usageReason(
|
|
6191
|
+
parsed.positionals,
|
|
6192
|
+
positionals
|
|
6193
|
+
)) => usageFailure(
|
|
6194
|
+
output,
|
|
6195
|
+
parsed,
|
|
6196
|
+
{ path: positionals, ...failure },
|
|
6197
|
+
() => stderr.write(helpScreen(positionals) ?? help)
|
|
6198
|
+
);
|
|
6199
|
+
const argumentError = (screen, words, given, most) => usageError(
|
|
6200
|
+
screen,
|
|
6201
|
+
given.length > most ? { reason: "invalid_value", detail: given[most], path: words } : { reason: "missing_argument", path: words }
|
|
6202
|
+
);
|
|
6092
6203
|
if (helpIndex !== -1) {
|
|
6093
6204
|
const positionals = args2.slice(0, helpIndex).filter((argument) => !argument.startsWith("--"));
|
|
6094
6205
|
const screen = helpScreen(positionals);
|
|
@@ -6099,10 +6210,10 @@ async function runCli(args2, deps = {}) {
|
|
|
6099
6210
|
stderr.write(
|
|
6100
6211
|
"WARNING: MNEMONIK_DEV_RELEASE_DIR uses development artifacts; readiness remains LIMITED.\n"
|
|
6101
6212
|
);
|
|
6102
|
-
if (parsed.error) return output
|
|
6213
|
+
if (parsed.error) return flagError(output, parsed, parsed.error);
|
|
6103
6214
|
if (parsed.flags.has("version")) {
|
|
6104
6215
|
if (parsed.positionals.length || parsed.flags.size !== 1)
|
|
6105
|
-
return output
|
|
6216
|
+
return flagError(output, parsed, "Unknown flag combination: --version");
|
|
6106
6217
|
output.line(await packageVersion());
|
|
6107
6218
|
return 0;
|
|
6108
6219
|
}
|
|
@@ -6124,7 +6235,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6124
6235
|
...action === "list" ? [] : ["accept-indexing", "apply"]
|
|
6125
6236
|
]);
|
|
6126
6237
|
if (invalid || !["add", "remove", "list"].includes(action ?? "") || actionArguments.length !== (action === "list" ? 0 : 1))
|
|
6127
|
-
return invalid ? (output
|
|
6238
|
+
return invalid ? flagError(output, parsed, invalid) : !["add", "remove", "list"].includes(action ?? "") ? usageError([command]) : argumentError(
|
|
6239
|
+
[command],
|
|
6240
|
+
command === "roots" ? [command, action ?? ""] : [command],
|
|
6241
|
+
actionArguments.map(String),
|
|
6242
|
+
action === "list" ? 0 : 1
|
|
6243
|
+
);
|
|
6128
6244
|
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
6129
6245
|
const saved = JSON.parse(
|
|
6130
6246
|
await readFile3(`${stateDir}/scanner/state.json`, "utf8").catch(() => "null")
|
|
@@ -6208,16 +6324,13 @@ async function runCli(args2, deps = {}) {
|
|
|
6208
6324
|
if (command === "auth" && subcommand === "logout" && parsed.flags.get("component") === "scanner") {
|
|
6209
6325
|
const invalid = allowed(parsed, ["component"]);
|
|
6210
6326
|
if (invalid || rest.length)
|
|
6211
|
-
return invalid ? (output
|
|
6327
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["auth", "logout"]);
|
|
6212
6328
|
try {
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
`${apiOrigin()}/api/v1/component-credentials/${encodeURIComponent(saved.config.credentialFamilyId)}/revoke`,
|
|
6218
|
-
{ method: "POST", headers: { Authorization: `Bearer ${bearer}` } }
|
|
6329
|
+
await revokeScannerCredential(
|
|
6330
|
+
deps,
|
|
6331
|
+
output,
|
|
6332
|
+
deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home)
|
|
6219
6333
|
);
|
|
6220
|
-
if (!response.ok) throw new Error(`revoke_failed_${response.status}`);
|
|
6221
6334
|
const result = {
|
|
6222
6335
|
status: "revoked",
|
|
6223
6336
|
verbs: ["revoke access"],
|
|
@@ -6239,7 +6352,7 @@ async function runCli(args2, deps = {}) {
|
|
|
6239
6352
|
const invalid = allowed(parsed, ["project", "confirm"]);
|
|
6240
6353
|
const project = parsed.flags.get("project");
|
|
6241
6354
|
if (invalid || subcommand !== "delete" || rest.length || typeof project !== "string")
|
|
6242
|
-
return invalid ? (output
|
|
6355
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["data", "delete"]);
|
|
6243
6356
|
if (!parsed.flags.has("confirm")) {
|
|
6244
6357
|
if (parsed.flags.has("non-interactive") || parsed.flags.has("json"))
|
|
6245
6358
|
return actionRequired2(
|
|
@@ -6273,7 +6386,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6273
6386
|
}
|
|
6274
6387
|
if ((command === "update" || command === "uninstall") && parsed.flags.get("component") === "scanner") {
|
|
6275
6388
|
const invalid = allowed(parsed, ["component", ...command === "uninstall" ? ["confirm"] : []]);
|
|
6276
|
-
if (invalid || subcommand)
|
|
6389
|
+
if (invalid || subcommand)
|
|
6390
|
+
return invalid ? flagError(output, parsed, invalid) : usageError([command]);
|
|
6391
|
+
if (command === "uninstall") {
|
|
6392
|
+
const declined = await confirmScannerOptOut(parsed, deps, output);
|
|
6393
|
+
if (declined !== void 0) return declined;
|
|
6394
|
+
}
|
|
6277
6395
|
try {
|
|
6278
6396
|
const options = {
|
|
6279
6397
|
stateDir: deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home),
|
|
@@ -6304,19 +6422,13 @@ async function runCli(args2, deps = {}) {
|
|
|
6304
6422
|
output.line(
|
|
6305
6423
|
result.status === "updated" ? "Mnemonik updated." : "Mnemonik is up to date."
|
|
6306
6424
|
);
|
|
6307
|
-
} else
|
|
6308
|
-
await
|
|
6309
|
-
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
if (parsed.flags.has("json")) output.json(result);
|
|
6315
|
-
else
|
|
6316
|
-
output.line(
|
|
6317
|
-
"Stopped collection; removed local software. Credentials, cloud data and consent retained."
|
|
6318
|
-
);
|
|
6319
|
-
}
|
|
6425
|
+
} else
|
|
6426
|
+
return await uninstallScannerOptOut(
|
|
6427
|
+
deps,
|
|
6428
|
+
output,
|
|
6429
|
+
scannerService(options),
|
|
6430
|
+
parsed.flags.has("json")
|
|
6431
|
+
);
|
|
6320
6432
|
return 0;
|
|
6321
6433
|
} catch (error) {
|
|
6322
6434
|
const failure = scannerFailure(error);
|
|
@@ -6350,7 +6462,8 @@ async function runCli(args2, deps = {}) {
|
|
|
6350
6462
|
parsed,
|
|
6351
6463
|
command === "repair" ? ["host", "component", "apply"] : command === "update" ? ["host", "automatic"] : ["host", "component", "confirm"]
|
|
6352
6464
|
);
|
|
6353
|
-
if (invalid || subcommand)
|
|
6465
|
+
if (invalid || subcommand)
|
|
6466
|
+
return invalid ? flagError(output, parsed, invalid) : usageError([command]);
|
|
6354
6467
|
if (command === "uninstall" && parsed.flags.has("non-interactive")) {
|
|
6355
6468
|
const missing = requireConsent(parsed, output, ["confirm"]);
|
|
6356
6469
|
if (missing !== void 0) return missing;
|
|
@@ -6360,7 +6473,8 @@ async function runCli(args2, deps = {}) {
|
|
|
6360
6473
|
}
|
|
6361
6474
|
if (command === "update") {
|
|
6362
6475
|
const invalid = allowed(parsed, ["automatic"]);
|
|
6363
|
-
if (invalid || subcommand)
|
|
6476
|
+
if (invalid || subcommand)
|
|
6477
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["update"]);
|
|
6364
6478
|
const runtimeUpdate = deps.runtimeUpdate;
|
|
6365
6479
|
if (!runtimeUpdate)
|
|
6366
6480
|
return placeholder(
|
|
@@ -6393,7 +6507,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6393
6507
|
const invalid = allowed(parsed, subcommand === "preview" ? ["out"] : []);
|
|
6394
6508
|
const bundleId = rest[0];
|
|
6395
6509
|
if (invalid || !["preview", "send"].includes(subcommand ?? "") || subcommand === "preview" && rest.length || subcommand === "send" && (rest.length !== 1 || !bundleId))
|
|
6396
|
-
return invalid ? (output
|
|
6510
|
+
return invalid ? flagError(output, parsed, invalid) : subcommand === "preview" || subcommand === "send" ? argumentError(
|
|
6511
|
+
["diagnostics"],
|
|
6512
|
+
["diagnostics", subcommand],
|
|
6513
|
+
rest,
|
|
6514
|
+
subcommand === "send" ? 1 : 0
|
|
6515
|
+
) : usageError(["diagnostics"]);
|
|
6397
6516
|
try {
|
|
6398
6517
|
const result = subcommand === "preview" ? await previewDiagnostics(
|
|
6399
6518
|
parsed.flags.get("out"),
|
|
@@ -6434,7 +6553,8 @@ Preview: ${preview.path}
|
|
|
6434
6553
|
}
|
|
6435
6554
|
if (command === "status") {
|
|
6436
6555
|
const invalid = allowed(parsed, []);
|
|
6437
|
-
if (invalid || subcommand)
|
|
6556
|
+
if (invalid || subcommand)
|
|
6557
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["status"]);
|
|
6438
6558
|
const document = await collectCurrentInstallation(deps, output);
|
|
6439
6559
|
const version = await packageVersion();
|
|
6440
6560
|
const store = new RuntimeStore(
|
|
@@ -6453,9 +6573,9 @@ Preview: ${preview.path}
|
|
|
6453
6573
|
}
|
|
6454
6574
|
if (command === "connect") {
|
|
6455
6575
|
const invalid = allowed(parsed, []);
|
|
6456
|
-
if (invalid) return output
|
|
6576
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6457
6577
|
if (!subcommand || rest.length || !hostOrder.includes(subcommand))
|
|
6458
|
-
return usageError(["connect"]);
|
|
6578
|
+
return subcommand && !hostOrder.includes(subcommand) ? usageError(["connect"], { reason: "invalid_value", detail: subcommand }) : argumentError(["connect"], ["connect"], [subcommand ?? "", ...rest].filter(Boolean), 1);
|
|
6459
6579
|
const host = subcommand;
|
|
6460
6580
|
const editor = (await localEditorStatus(deps.home ?? homedir3())).find(
|
|
6461
6581
|
(candidate) => candidate.host === host
|
|
@@ -6493,21 +6613,28 @@ Preview: ${preview.path}
|
|
|
6493
6613
|
if (subcommand === "delete") {
|
|
6494
6614
|
const unknown = allowed(parsed, ["confirm"]);
|
|
6495
6615
|
if (unknown || rest.length > 1)
|
|
6496
|
-
return unknown ? (output
|
|
6616
|
+
return unknown ? flagError(output, parsed, unknown) : argumentError(["project", "delete"], ["project", "delete"], rest, 1);
|
|
6497
6617
|
return deleteProjectCommand(parsed, rest, deps, output);
|
|
6498
6618
|
}
|
|
6499
6619
|
const invalid = allowed(
|
|
6500
6620
|
parsed,
|
|
6501
6621
|
subcommand === "ensure" ? ["agent"] : subcommand === "status" ? [] : subcommand === "link" ? ["apply", "non-git", "confirm-mismatch", "replace"] : ["apply", "non-git", "owner"]
|
|
6502
6622
|
);
|
|
6503
|
-
if (invalid) return output
|
|
6623
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6504
6624
|
if (subcommand === "ensure") {
|
|
6505
6625
|
if (rest.length) return usageError(["project", "ensure"]);
|
|
6506
6626
|
return ensureProjectForAgent({
|
|
6507
6627
|
output,
|
|
6508
6628
|
cwd: deps.cwd ?? process.cwd(),
|
|
6509
6629
|
executor: deps.projectExecutor,
|
|
6510
|
-
input: deps.input ?? process.stdin
|
|
6630
|
+
input: deps.input ?? process.stdin,
|
|
6631
|
+
handoff: parsed.flags.has("agent"),
|
|
6632
|
+
// The same sign-in reader status and every other command use.
|
|
6633
|
+
runtime: {
|
|
6634
|
+
stateDir: deps.projectStateDir ?? deps.installStateDir,
|
|
6635
|
+
fetch: deps.grantFetch,
|
|
6636
|
+
getCliBearer: auth(deps, output, true).getCliBearer
|
|
6637
|
+
}
|
|
6511
6638
|
});
|
|
6512
6639
|
}
|
|
6513
6640
|
if (subcommand !== "status" && subcommand !== "setup" && parsed.flags.has("non-interactive")) {
|
|
@@ -6515,7 +6642,12 @@ Preview: ${preview.path}
|
|
|
6515
6642
|
if (missing !== void 0) return missing;
|
|
6516
6643
|
}
|
|
6517
6644
|
if (subcommand === "link" && (rest.length < 1 || rest.length > 2) || subcommand !== "link" && rest.length > 1)
|
|
6518
|
-
return
|
|
6645
|
+
return argumentError(
|
|
6646
|
+
["project", subcommand],
|
|
6647
|
+
["project", subcommand],
|
|
6648
|
+
rest,
|
|
6649
|
+
subcommand === "link" ? 2 : 1
|
|
6650
|
+
);
|
|
6519
6651
|
return runProjectCommand(
|
|
6520
6652
|
{
|
|
6521
6653
|
command: subcommand,
|
|
@@ -6543,17 +6675,25 @@ Preview: ${preview.path}
|
|
|
6543
6675
|
if (command === "identity") {
|
|
6544
6676
|
if (subcommand !== "migrate") return usageError(["identity", "migrate"]);
|
|
6545
6677
|
const invalid = allowed(parsed, ["report", "backup", "apply", "verify", "rollback"]);
|
|
6546
|
-
if (invalid) return output
|
|
6678
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6547
6679
|
const selected = ["report", "backup", "apply", "verify", "rollback"].filter(
|
|
6548
6680
|
(flag) => parsed.flags.has(flag)
|
|
6549
6681
|
);
|
|
6550
6682
|
if (selected.length > 1)
|
|
6551
|
-
return
|
|
6683
|
+
return usageFailure(
|
|
6684
|
+
output,
|
|
6685
|
+
parsed,
|
|
6686
|
+
{ reason: "invalid_flag", detail: `--${selected[1]}` },
|
|
6552
6687
|
"Choose one migration phase: --report, --backup, --apply, --verify, or --rollback"
|
|
6553
|
-
)
|
|
6688
|
+
);
|
|
6554
6689
|
const mode = selected[0] ?? "report";
|
|
6555
6690
|
if (rest.length && mode !== "report" && mode !== "backup")
|
|
6556
|
-
return
|
|
6691
|
+
return usageFailure(
|
|
6692
|
+
output,
|
|
6693
|
+
parsed,
|
|
6694
|
+
{ reason: "invalid_value", detail: rest[0] },
|
|
6695
|
+
"Paths are only accepted by --report and --backup"
|
|
6696
|
+
);
|
|
6557
6697
|
let result;
|
|
6558
6698
|
try {
|
|
6559
6699
|
result = await runIdentityMigration({
|
|
@@ -6597,10 +6737,14 @@ Preview: ${preview.path}
|
|
|
6597
6737
|
);
|
|
6598
6738
|
const invalid = allowed(
|
|
6599
6739
|
parsed,
|
|
6600
|
-
subcommand === "enable" ? ["accept-indexing", "apply", "scan-roots", "exclusions", "no-browser"] : subcommand === "export-preview" ? ["out"] : []
|
|
6740
|
+
subcommand === "enable" ? ["accept-indexing", "apply", "scan-roots", "exclusions", "no-browser"] : subcommand === "export-preview" ? ["out"] : subcommand === "uninstall" ? ["confirm"] : []
|
|
6601
6741
|
);
|
|
6602
|
-
if (invalid) return output
|
|
6742
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6603
6743
|
if (subcommand === "enable") return enableCommand(parsed, deps, output);
|
|
6744
|
+
if (subcommand === "uninstall") {
|
|
6745
|
+
const declined = await confirmScannerOptOut(parsed, deps, output);
|
|
6746
|
+
if (declined !== void 0) return declined;
|
|
6747
|
+
}
|
|
6604
6748
|
if (subcommand === "status" && deps.scannerStatus) {
|
|
6605
6749
|
const status = await deps.scannerStatus();
|
|
6606
6750
|
const omitted = status.repositories.filter((repository) => !repository.selected).map((repository) => ({
|
|
@@ -6691,10 +6835,12 @@ Preview: ${preview.path}
|
|
|
6691
6835
|
}
|
|
6692
6836
|
await service.start();
|
|
6693
6837
|
} else if (subcommand === "stop") {
|
|
6838
|
+
await controlScanner("stop", options).catch(() => void 0);
|
|
6694
6839
|
await service.stop();
|
|
6695
6840
|
if ((deps.scannerService?.platform ?? process.platform) === "darwin")
|
|
6696
6841
|
output.line("Background indexing will start again when this Mac restarts.");
|
|
6697
|
-
} else if (subcommand === "uninstall")
|
|
6842
|
+
} else if (subcommand === "uninstall")
|
|
6843
|
+
return await uninstallScannerOptOut(deps, output, service, json);
|
|
6698
6844
|
const includesStatus = ["status", "pause", "resume"].includes(subcommand);
|
|
6699
6845
|
const supervisor = includesStatus ? await service.status() : void 0;
|
|
6700
6846
|
const receipt = includesStatus ? await scannerReceipt(options.stateDir) : void 0;
|
|
@@ -6737,16 +6883,29 @@ Preview: ${preview.path}
|
|
|
6737
6883
|
"reopen-install",
|
|
6738
6884
|
...subcommand === "logout" ? ["confirm"] : []
|
|
6739
6885
|
]);
|
|
6740
|
-
if (invalid || rest.length || !["login", "status", "logout"].includes(subcommand ?? "") || parsed.flags.has("reopen-install") && subcommand !== "login")
|
|
6741
|
-
return invalid ? (output
|
|
6742
|
-
subcommand && helpScreen(["auth", subcommand]) ? ["auth", subcommand] : ["auth"]
|
|
6886
|
+
if (invalid || rest.length || !["login", "renew", "status", "logout"].includes(subcommand ?? "") || parsed.flags.has("reopen-install") && subcommand !== "login" && subcommand !== "renew")
|
|
6887
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(
|
|
6888
|
+
subcommand && helpScreen(["auth", subcommand]) ? ["auth", subcommand] : ["auth"],
|
|
6889
|
+
!rest.length && ["login", "renew", "status", "logout"].includes(subcommand ?? "") ? { reason: "invalid_flag", detail: "--reopen-install" } : void 0
|
|
6743
6890
|
);
|
|
6744
6891
|
const host = parsed.flags.get("host");
|
|
6745
|
-
if (host && !hostOrder.includes(host))
|
|
6746
|
-
|
|
6747
|
-
|
|
6892
|
+
if (host && !hostOrder.includes(host))
|
|
6893
|
+
return usageFailure(
|
|
6894
|
+
output,
|
|
6895
|
+
parsed,
|
|
6896
|
+
{ reason: "invalid_value", detail: String(host) },
|
|
6897
|
+
"Invalid host"
|
|
6898
|
+
);
|
|
6899
|
+
if (subcommand === "login" || subcommand === "renew") {
|
|
6900
|
+
if (host)
|
|
6901
|
+
return usageFailure(
|
|
6902
|
+
output,
|
|
6903
|
+
parsed,
|
|
6904
|
+
{ reason: "invalid_flag", detail: "--host" },
|
|
6905
|
+
"Use mnemonik connect <host> for a host login"
|
|
6906
|
+
);
|
|
6748
6907
|
const noBrowser = parsed.flags.has("no-browser");
|
|
6749
|
-
const bearer = await ensureCliAuth(deps, output, noBrowser);
|
|
6908
|
+
const bearer = await ensureCliAuth(deps, output, noBrowser, true, subcommand === "renew");
|
|
6750
6909
|
if (parsed.flags.has("reopen-install")) {
|
|
6751
6910
|
const current = await currentInstallSession(bearer, deps.grantFetch);
|
|
6752
6911
|
if (current) {
|
|
@@ -6806,11 +6965,17 @@ Preview: ${preview.path}
|
|
|
6806
6965
|
return (!grantHostName || hostOrder.includes(grantHostName)) && (!host || grantHostName === host);
|
|
6807
6966
|
}).map((g) => ({ ...g, host: grantHost(g) ?? g.clientName ?? g.clientId }));
|
|
6808
6967
|
if (parsed.flags.has("json")) output.json({ account: status.account, grants });
|
|
6809
|
-
else
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6968
|
+
else if (!grants.length)
|
|
6969
|
+
output.line(
|
|
6970
|
+
host ? `${launchHostLabels[host]} is not signed in.` : humanReason("not_signed_in")
|
|
6971
|
+
);
|
|
6972
|
+
else {
|
|
6973
|
+
output.signedInAs(status.email);
|
|
6974
|
+
for (const line of grantSummaryLines(grants, launchHostLabels)) output.line(line);
|
|
6975
|
+
output.line(
|
|
6976
|
+
"Older sign-ins stay valid until `mnemonik auth logout`. `mnemonik auth status --json` lists every one."
|
|
6977
|
+
);
|
|
6978
|
+
}
|
|
6814
6979
|
return 0;
|
|
6815
6980
|
}
|
|
6816
6981
|
const confirmed = parsed.flags.has("confirm") || await managed.offerRevoke?.(host) || !parsed.flags.has("json") && !parsed.flags.has("non-interactive") && (await chooseHostProfile(deps.input ?? process.stdin, output, [
|
|
@@ -6836,7 +7001,7 @@ Preview: ${preview.path}
|
|
|
6836
7001
|
if (command === "logout") {
|
|
6837
7002
|
if (subcommand) return usageError(["logout"]);
|
|
6838
7003
|
const invalid = allowed(parsed, []);
|
|
6839
|
-
if (invalid) return output
|
|
7004
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6840
7005
|
await auth(deps, output, false).logout();
|
|
6841
7006
|
if (parsed.flags.has("json")) output.json({ status: "logged_out" });
|
|
6842
7007
|
else output.line("Logged out.");
|
|
@@ -6849,6 +7014,9 @@ export {
|
|
|
6849
7014
|
CODEX_SIGNED_IN_MESSAGE,
|
|
6850
7015
|
CONNECT_NOT_APPROVED_MESSAGE,
|
|
6851
7016
|
NOTHING_DELETED_LINE,
|
|
7017
|
+
NOTHING_REMOVED_LINE,
|
|
7018
|
+
SCANNER_REMOVED_LINE,
|
|
7019
|
+
SCANNER_UNINSTALL_PROMPT,
|
|
6852
7020
|
alreadyConnectedFolderLine,
|
|
6853
7021
|
connectFolderPrompt,
|
|
6854
7022
|
connectedFolderLine,
|