@mnemonik/cli 7.107.2 → 7.108.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/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 +238 -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({
|
|
@@ -6000,9 +6099,11 @@ async function deleteProjectCommand(parsed, rest, deps, output) {
|
|
|
6000
6099
|
const send = deps.grantFetch ?? fetch;
|
|
6001
6100
|
const listed = await send(`${apiOrigin()}/api/v1/users/me/projects?days=0&limit=200`, {
|
|
6002
6101
|
headers: { Authorization: `Bearer ${bearer}` }
|
|
6003
|
-
});
|
|
6004
|
-
if (!listed
|
|
6005
|
-
|
|
6102
|
+
}).catch(() => void 0);
|
|
6103
|
+
if (!listed?.ok) {
|
|
6104
|
+
const reason = !listed ? "unreachable" : listed.status === 401 || listed.status === 403 ? "renew" : "server_error";
|
|
6105
|
+
if (json) output.json({ status: "action_required", reason, action: accountActions[reason] });
|
|
6106
|
+
else output.error(humanReason(reason));
|
|
6006
6107
|
return 3;
|
|
6007
6108
|
}
|
|
6008
6109
|
const listing = await listed.json().catch(() => []);
|
|
@@ -6085,10 +6186,19 @@ async function runCli(args2, deps = {}) {
|
|
|
6085
6186
|
const output = new Output(stdout, stderr, {
|
|
6086
6187
|
home: deps.home ?? homedir3()
|
|
6087
6188
|
});
|
|
6088
|
-
const usageError = (positionals
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6189
|
+
const usageError = (positionals, failure = usageReason(
|
|
6190
|
+
parsed.positionals,
|
|
6191
|
+
positionals
|
|
6192
|
+
)) => usageFailure(
|
|
6193
|
+
output,
|
|
6194
|
+
parsed,
|
|
6195
|
+
{ path: positionals, ...failure },
|
|
6196
|
+
() => stderr.write(helpScreen(positionals) ?? help)
|
|
6197
|
+
);
|
|
6198
|
+
const argumentError = (screen, words, given, most) => usageError(
|
|
6199
|
+
screen,
|
|
6200
|
+
given.length > most ? { reason: "invalid_value", detail: given[most], path: words } : { reason: "missing_argument", path: words }
|
|
6201
|
+
);
|
|
6092
6202
|
if (helpIndex !== -1) {
|
|
6093
6203
|
const positionals = args2.slice(0, helpIndex).filter((argument) => !argument.startsWith("--"));
|
|
6094
6204
|
const screen = helpScreen(positionals);
|
|
@@ -6099,10 +6209,10 @@ async function runCli(args2, deps = {}) {
|
|
|
6099
6209
|
stderr.write(
|
|
6100
6210
|
"WARNING: MNEMONIK_DEV_RELEASE_DIR uses development artifacts; readiness remains LIMITED.\n"
|
|
6101
6211
|
);
|
|
6102
|
-
if (parsed.error) return output
|
|
6212
|
+
if (parsed.error) return flagError(output, parsed, parsed.error);
|
|
6103
6213
|
if (parsed.flags.has("version")) {
|
|
6104
6214
|
if (parsed.positionals.length || parsed.flags.size !== 1)
|
|
6105
|
-
return output
|
|
6215
|
+
return flagError(output, parsed, "Unknown flag combination: --version");
|
|
6106
6216
|
output.line(await packageVersion());
|
|
6107
6217
|
return 0;
|
|
6108
6218
|
}
|
|
@@ -6124,7 +6234,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6124
6234
|
...action === "list" ? [] : ["accept-indexing", "apply"]
|
|
6125
6235
|
]);
|
|
6126
6236
|
if (invalid || !["add", "remove", "list"].includes(action ?? "") || actionArguments.length !== (action === "list" ? 0 : 1))
|
|
6127
|
-
return invalid ? (output
|
|
6237
|
+
return invalid ? flagError(output, parsed, invalid) : !["add", "remove", "list"].includes(action ?? "") ? usageError([command]) : argumentError(
|
|
6238
|
+
[command],
|
|
6239
|
+
command === "roots" ? [command, action ?? ""] : [command],
|
|
6240
|
+
actionArguments.map(String),
|
|
6241
|
+
action === "list" ? 0 : 1
|
|
6242
|
+
);
|
|
6128
6243
|
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
6129
6244
|
const saved = JSON.parse(
|
|
6130
6245
|
await readFile3(`${stateDir}/scanner/state.json`, "utf8").catch(() => "null")
|
|
@@ -6208,16 +6323,13 @@ async function runCli(args2, deps = {}) {
|
|
|
6208
6323
|
if (command === "auth" && subcommand === "logout" && parsed.flags.get("component") === "scanner") {
|
|
6209
6324
|
const invalid = allowed(parsed, ["component"]);
|
|
6210
6325
|
if (invalid || rest.length)
|
|
6211
|
-
return invalid ? (output
|
|
6326
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["auth", "logout"]);
|
|
6212
6327
|
try {
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6217
|
-
`${apiOrigin()}/api/v1/component-credentials/${encodeURIComponent(saved.config.credentialFamilyId)}/revoke`,
|
|
6218
|
-
{ method: "POST", headers: { Authorization: `Bearer ${bearer}` } }
|
|
6328
|
+
await revokeScannerCredential(
|
|
6329
|
+
deps,
|
|
6330
|
+
output,
|
|
6331
|
+
deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home)
|
|
6219
6332
|
);
|
|
6220
|
-
if (!response.ok) throw new Error(`revoke_failed_${response.status}`);
|
|
6221
6333
|
const result = {
|
|
6222
6334
|
status: "revoked",
|
|
6223
6335
|
verbs: ["revoke access"],
|
|
@@ -6239,7 +6351,7 @@ async function runCli(args2, deps = {}) {
|
|
|
6239
6351
|
const invalid = allowed(parsed, ["project", "confirm"]);
|
|
6240
6352
|
const project = parsed.flags.get("project");
|
|
6241
6353
|
if (invalid || subcommand !== "delete" || rest.length || typeof project !== "string")
|
|
6242
|
-
return invalid ? (output
|
|
6354
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["data", "delete"]);
|
|
6243
6355
|
if (!parsed.flags.has("confirm")) {
|
|
6244
6356
|
if (parsed.flags.has("non-interactive") || parsed.flags.has("json"))
|
|
6245
6357
|
return actionRequired2(
|
|
@@ -6273,7 +6385,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6273
6385
|
}
|
|
6274
6386
|
if ((command === "update" || command === "uninstall") && parsed.flags.get("component") === "scanner") {
|
|
6275
6387
|
const invalid = allowed(parsed, ["component", ...command === "uninstall" ? ["confirm"] : []]);
|
|
6276
|
-
if (invalid || subcommand)
|
|
6388
|
+
if (invalid || subcommand)
|
|
6389
|
+
return invalid ? flagError(output, parsed, invalid) : usageError([command]);
|
|
6390
|
+
if (command === "uninstall") {
|
|
6391
|
+
const declined = await confirmScannerOptOut(parsed, deps, output);
|
|
6392
|
+
if (declined !== void 0) return declined;
|
|
6393
|
+
}
|
|
6277
6394
|
try {
|
|
6278
6395
|
const options = {
|
|
6279
6396
|
stateDir: deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home),
|
|
@@ -6304,19 +6421,13 @@ async function runCli(args2, deps = {}) {
|
|
|
6304
6421
|
output.line(
|
|
6305
6422
|
result.status === "updated" ? "Mnemonik updated." : "Mnemonik is up to date."
|
|
6306
6423
|
);
|
|
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
|
-
}
|
|
6424
|
+
} else
|
|
6425
|
+
return await uninstallScannerOptOut(
|
|
6426
|
+
deps,
|
|
6427
|
+
output,
|
|
6428
|
+
scannerService(options),
|
|
6429
|
+
parsed.flags.has("json")
|
|
6430
|
+
);
|
|
6320
6431
|
return 0;
|
|
6321
6432
|
} catch (error) {
|
|
6322
6433
|
const failure = scannerFailure(error);
|
|
@@ -6350,7 +6461,8 @@ async function runCli(args2, deps = {}) {
|
|
|
6350
6461
|
parsed,
|
|
6351
6462
|
command === "repair" ? ["host", "component", "apply"] : command === "update" ? ["host", "automatic"] : ["host", "component", "confirm"]
|
|
6352
6463
|
);
|
|
6353
|
-
if (invalid || subcommand)
|
|
6464
|
+
if (invalid || subcommand)
|
|
6465
|
+
return invalid ? flagError(output, parsed, invalid) : usageError([command]);
|
|
6354
6466
|
if (command === "uninstall" && parsed.flags.has("non-interactive")) {
|
|
6355
6467
|
const missing = requireConsent(parsed, output, ["confirm"]);
|
|
6356
6468
|
if (missing !== void 0) return missing;
|
|
@@ -6360,7 +6472,8 @@ async function runCli(args2, deps = {}) {
|
|
|
6360
6472
|
}
|
|
6361
6473
|
if (command === "update") {
|
|
6362
6474
|
const invalid = allowed(parsed, ["automatic"]);
|
|
6363
|
-
if (invalid || subcommand)
|
|
6475
|
+
if (invalid || subcommand)
|
|
6476
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["update"]);
|
|
6364
6477
|
const runtimeUpdate = deps.runtimeUpdate;
|
|
6365
6478
|
if (!runtimeUpdate)
|
|
6366
6479
|
return placeholder(
|
|
@@ -6393,7 +6506,12 @@ async function runCli(args2, deps = {}) {
|
|
|
6393
6506
|
const invalid = allowed(parsed, subcommand === "preview" ? ["out"] : []);
|
|
6394
6507
|
const bundleId = rest[0];
|
|
6395
6508
|
if (invalid || !["preview", "send"].includes(subcommand ?? "") || subcommand === "preview" && rest.length || subcommand === "send" && (rest.length !== 1 || !bundleId))
|
|
6396
|
-
return invalid ? (output
|
|
6509
|
+
return invalid ? flagError(output, parsed, invalid) : subcommand === "preview" || subcommand === "send" ? argumentError(
|
|
6510
|
+
["diagnostics"],
|
|
6511
|
+
["diagnostics", subcommand],
|
|
6512
|
+
rest,
|
|
6513
|
+
subcommand === "send" ? 1 : 0
|
|
6514
|
+
) : usageError(["diagnostics"]);
|
|
6397
6515
|
try {
|
|
6398
6516
|
const result = subcommand === "preview" ? await previewDiagnostics(
|
|
6399
6517
|
parsed.flags.get("out"),
|
|
@@ -6434,7 +6552,8 @@ Preview: ${preview.path}
|
|
|
6434
6552
|
}
|
|
6435
6553
|
if (command === "status") {
|
|
6436
6554
|
const invalid = allowed(parsed, []);
|
|
6437
|
-
if (invalid || subcommand)
|
|
6555
|
+
if (invalid || subcommand)
|
|
6556
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(["status"]);
|
|
6438
6557
|
const document = await collectCurrentInstallation(deps, output);
|
|
6439
6558
|
const version = await packageVersion();
|
|
6440
6559
|
const store = new RuntimeStore(
|
|
@@ -6453,9 +6572,9 @@ Preview: ${preview.path}
|
|
|
6453
6572
|
}
|
|
6454
6573
|
if (command === "connect") {
|
|
6455
6574
|
const invalid = allowed(parsed, []);
|
|
6456
|
-
if (invalid) return output
|
|
6575
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6457
6576
|
if (!subcommand || rest.length || !hostOrder.includes(subcommand))
|
|
6458
|
-
return usageError(["connect"]);
|
|
6577
|
+
return subcommand && !hostOrder.includes(subcommand) ? usageError(["connect"], { reason: "invalid_value", detail: subcommand }) : argumentError(["connect"], ["connect"], [subcommand ?? "", ...rest].filter(Boolean), 1);
|
|
6459
6578
|
const host = subcommand;
|
|
6460
6579
|
const editor = (await localEditorStatus(deps.home ?? homedir3())).find(
|
|
6461
6580
|
(candidate) => candidate.host === host
|
|
@@ -6493,21 +6612,28 @@ Preview: ${preview.path}
|
|
|
6493
6612
|
if (subcommand === "delete") {
|
|
6494
6613
|
const unknown = allowed(parsed, ["confirm"]);
|
|
6495
6614
|
if (unknown || rest.length > 1)
|
|
6496
|
-
return unknown ? (output
|
|
6615
|
+
return unknown ? flagError(output, parsed, unknown) : argumentError(["project", "delete"], ["project", "delete"], rest, 1);
|
|
6497
6616
|
return deleteProjectCommand(parsed, rest, deps, output);
|
|
6498
6617
|
}
|
|
6499
6618
|
const invalid = allowed(
|
|
6500
6619
|
parsed,
|
|
6501
6620
|
subcommand === "ensure" ? ["agent"] : subcommand === "status" ? [] : subcommand === "link" ? ["apply", "non-git", "confirm-mismatch", "replace"] : ["apply", "non-git", "owner"]
|
|
6502
6621
|
);
|
|
6503
|
-
if (invalid) return output
|
|
6622
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6504
6623
|
if (subcommand === "ensure") {
|
|
6505
6624
|
if (rest.length) return usageError(["project", "ensure"]);
|
|
6506
6625
|
return ensureProjectForAgent({
|
|
6507
6626
|
output,
|
|
6508
6627
|
cwd: deps.cwd ?? process.cwd(),
|
|
6509
6628
|
executor: deps.projectExecutor,
|
|
6510
|
-
input: deps.input ?? process.stdin
|
|
6629
|
+
input: deps.input ?? process.stdin,
|
|
6630
|
+
handoff: parsed.flags.has("agent"),
|
|
6631
|
+
// The same sign-in reader status and every other command use.
|
|
6632
|
+
runtime: {
|
|
6633
|
+
stateDir: deps.projectStateDir ?? deps.installStateDir,
|
|
6634
|
+
fetch: deps.grantFetch,
|
|
6635
|
+
getCliBearer: auth(deps, output, true).getCliBearer
|
|
6636
|
+
}
|
|
6511
6637
|
});
|
|
6512
6638
|
}
|
|
6513
6639
|
if (subcommand !== "status" && subcommand !== "setup" && parsed.flags.has("non-interactive")) {
|
|
@@ -6515,7 +6641,12 @@ Preview: ${preview.path}
|
|
|
6515
6641
|
if (missing !== void 0) return missing;
|
|
6516
6642
|
}
|
|
6517
6643
|
if (subcommand === "link" && (rest.length < 1 || rest.length > 2) || subcommand !== "link" && rest.length > 1)
|
|
6518
|
-
return
|
|
6644
|
+
return argumentError(
|
|
6645
|
+
["project", subcommand],
|
|
6646
|
+
["project", subcommand],
|
|
6647
|
+
rest,
|
|
6648
|
+
subcommand === "link" ? 2 : 1
|
|
6649
|
+
);
|
|
6519
6650
|
return runProjectCommand(
|
|
6520
6651
|
{
|
|
6521
6652
|
command: subcommand,
|
|
@@ -6543,17 +6674,25 @@ Preview: ${preview.path}
|
|
|
6543
6674
|
if (command === "identity") {
|
|
6544
6675
|
if (subcommand !== "migrate") return usageError(["identity", "migrate"]);
|
|
6545
6676
|
const invalid = allowed(parsed, ["report", "backup", "apply", "verify", "rollback"]);
|
|
6546
|
-
if (invalid) return output
|
|
6677
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6547
6678
|
const selected = ["report", "backup", "apply", "verify", "rollback"].filter(
|
|
6548
6679
|
(flag) => parsed.flags.has(flag)
|
|
6549
6680
|
);
|
|
6550
6681
|
if (selected.length > 1)
|
|
6551
|
-
return
|
|
6682
|
+
return usageFailure(
|
|
6683
|
+
output,
|
|
6684
|
+
parsed,
|
|
6685
|
+
{ reason: "invalid_flag", detail: `--${selected[1]}` },
|
|
6552
6686
|
"Choose one migration phase: --report, --backup, --apply, --verify, or --rollback"
|
|
6553
|
-
)
|
|
6687
|
+
);
|
|
6554
6688
|
const mode = selected[0] ?? "report";
|
|
6555
6689
|
if (rest.length && mode !== "report" && mode !== "backup")
|
|
6556
|
-
return
|
|
6690
|
+
return usageFailure(
|
|
6691
|
+
output,
|
|
6692
|
+
parsed,
|
|
6693
|
+
{ reason: "invalid_value", detail: rest[0] },
|
|
6694
|
+
"Paths are only accepted by --report and --backup"
|
|
6695
|
+
);
|
|
6557
6696
|
let result;
|
|
6558
6697
|
try {
|
|
6559
6698
|
result = await runIdentityMigration({
|
|
@@ -6597,10 +6736,14 @@ Preview: ${preview.path}
|
|
|
6597
6736
|
);
|
|
6598
6737
|
const invalid = allowed(
|
|
6599
6738
|
parsed,
|
|
6600
|
-
subcommand === "enable" ? ["accept-indexing", "apply", "scan-roots", "exclusions", "no-browser"] : subcommand === "export-preview" ? ["out"] : []
|
|
6739
|
+
subcommand === "enable" ? ["accept-indexing", "apply", "scan-roots", "exclusions", "no-browser"] : subcommand === "export-preview" ? ["out"] : subcommand === "uninstall" ? ["confirm"] : []
|
|
6601
6740
|
);
|
|
6602
|
-
if (invalid) return output
|
|
6741
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6603
6742
|
if (subcommand === "enable") return enableCommand(parsed, deps, output);
|
|
6743
|
+
if (subcommand === "uninstall") {
|
|
6744
|
+
const declined = await confirmScannerOptOut(parsed, deps, output);
|
|
6745
|
+
if (declined !== void 0) return declined;
|
|
6746
|
+
}
|
|
6604
6747
|
if (subcommand === "status" && deps.scannerStatus) {
|
|
6605
6748
|
const status = await deps.scannerStatus();
|
|
6606
6749
|
const omitted = status.repositories.filter((repository) => !repository.selected).map((repository) => ({
|
|
@@ -6691,10 +6834,12 @@ Preview: ${preview.path}
|
|
|
6691
6834
|
}
|
|
6692
6835
|
await service.start();
|
|
6693
6836
|
} else if (subcommand === "stop") {
|
|
6837
|
+
await controlScanner("stop", options).catch(() => void 0);
|
|
6694
6838
|
await service.stop();
|
|
6695
6839
|
if ((deps.scannerService?.platform ?? process.platform) === "darwin")
|
|
6696
6840
|
output.line("Background indexing will start again when this Mac restarts.");
|
|
6697
|
-
} else if (subcommand === "uninstall")
|
|
6841
|
+
} else if (subcommand === "uninstall")
|
|
6842
|
+
return await uninstallScannerOptOut(deps, output, service, json);
|
|
6698
6843
|
const includesStatus = ["status", "pause", "resume"].includes(subcommand);
|
|
6699
6844
|
const supervisor = includesStatus ? await service.status() : void 0;
|
|
6700
6845
|
const receipt = includesStatus ? await scannerReceipt(options.stateDir) : void 0;
|
|
@@ -6737,16 +6882,29 @@ Preview: ${preview.path}
|
|
|
6737
6882
|
"reopen-install",
|
|
6738
6883
|
...subcommand === "logout" ? ["confirm"] : []
|
|
6739
6884
|
]);
|
|
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"]
|
|
6885
|
+
if (invalid || rest.length || !["login", "renew", "status", "logout"].includes(subcommand ?? "") || parsed.flags.has("reopen-install") && subcommand !== "login" && subcommand !== "renew")
|
|
6886
|
+
return invalid ? flagError(output, parsed, invalid) : usageError(
|
|
6887
|
+
subcommand && helpScreen(["auth", subcommand]) ? ["auth", subcommand] : ["auth"],
|
|
6888
|
+
!rest.length && ["login", "renew", "status", "logout"].includes(subcommand ?? "") ? { reason: "invalid_flag", detail: "--reopen-install" } : void 0
|
|
6743
6889
|
);
|
|
6744
6890
|
const host = parsed.flags.get("host");
|
|
6745
|
-
if (host && !hostOrder.includes(host))
|
|
6746
|
-
|
|
6747
|
-
|
|
6891
|
+
if (host && !hostOrder.includes(host))
|
|
6892
|
+
return usageFailure(
|
|
6893
|
+
output,
|
|
6894
|
+
parsed,
|
|
6895
|
+
{ reason: "invalid_value", detail: String(host) },
|
|
6896
|
+
"Invalid host"
|
|
6897
|
+
);
|
|
6898
|
+
if (subcommand === "login" || subcommand === "renew") {
|
|
6899
|
+
if (host)
|
|
6900
|
+
return usageFailure(
|
|
6901
|
+
output,
|
|
6902
|
+
parsed,
|
|
6903
|
+
{ reason: "invalid_flag", detail: "--host" },
|
|
6904
|
+
"Use mnemonik connect <host> for a host login"
|
|
6905
|
+
);
|
|
6748
6906
|
const noBrowser = parsed.flags.has("no-browser");
|
|
6749
|
-
const bearer = await ensureCliAuth(deps, output, noBrowser);
|
|
6907
|
+
const bearer = await ensureCliAuth(deps, output, noBrowser, true, subcommand === "renew");
|
|
6750
6908
|
if (parsed.flags.has("reopen-install")) {
|
|
6751
6909
|
const current = await currentInstallSession(bearer, deps.grantFetch);
|
|
6752
6910
|
if (current) {
|
|
@@ -6806,11 +6964,17 @@ Preview: ${preview.path}
|
|
|
6806
6964
|
return (!grantHostName || hostOrder.includes(grantHostName)) && (!host || grantHostName === host);
|
|
6807
6965
|
}).map((g) => ({ ...g, host: grantHost(g) ?? g.clientName ?? g.clientId }));
|
|
6808
6966
|
if (parsed.flags.has("json")) output.json({ account: status.account, grants });
|
|
6809
|
-
else
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6967
|
+
else if (!grants.length)
|
|
6968
|
+
output.line(
|
|
6969
|
+
host ? `${launchHostLabels[host]} is not signed in.` : humanReason("not_signed_in")
|
|
6970
|
+
);
|
|
6971
|
+
else {
|
|
6972
|
+
output.signedInAs(status.email);
|
|
6973
|
+
for (const line of grantSummaryLines(grants, launchHostLabels)) output.line(line);
|
|
6974
|
+
output.line(
|
|
6975
|
+
"Older sign-ins stay valid until `mnemonik auth logout`. `mnemonik auth status --json` lists every one."
|
|
6976
|
+
);
|
|
6977
|
+
}
|
|
6814
6978
|
return 0;
|
|
6815
6979
|
}
|
|
6816
6980
|
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 +7000,7 @@ Preview: ${preview.path}
|
|
|
6836
7000
|
if (command === "logout") {
|
|
6837
7001
|
if (subcommand) return usageError(["logout"]);
|
|
6838
7002
|
const invalid = allowed(parsed, []);
|
|
6839
|
-
if (invalid) return output
|
|
7003
|
+
if (invalid) return flagError(output, parsed, invalid);
|
|
6840
7004
|
await auth(deps, output, false).logout();
|
|
6841
7005
|
if (parsed.flags.has("json")) output.json({ status: "logged_out" });
|
|
6842
7006
|
else output.line("Logged out.");
|
|
@@ -6849,6 +7013,9 @@ export {
|
|
|
6849
7013
|
CODEX_SIGNED_IN_MESSAGE,
|
|
6850
7014
|
CONNECT_NOT_APPROVED_MESSAGE,
|
|
6851
7015
|
NOTHING_DELETED_LINE,
|
|
7016
|
+
NOTHING_REMOVED_LINE,
|
|
7017
|
+
SCANNER_REMOVED_LINE,
|
|
7018
|
+
SCANNER_UNINSTALL_PROMPT,
|
|
6852
7019
|
alreadyConnectedFolderLine,
|
|
6853
7020
|
connectFolderPrompt,
|
|
6854
7021
|
connectedFolderLine,
|