@mnemonik/cli 7.104.11 → 7.105.0
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/pkce.d.ts +24 -0
- package/dist/auth/pkce.d.ts.map +1 -1
- package/dist/auth/pkce.js +73 -0
- package/dist/auth/pkce.js.map +1 -1
- package/dist/digests.json +35 -35
- package/dist/humanReason.d.ts +5 -2
- package/dist/humanReason.d.ts.map +1 -1
- package/dist/humanReason.js +81 -34
- package/dist/humanReason.js.map +1 -1
- package/dist/install/hosts.d.ts +2 -0
- package/dist/install/hosts.d.ts.map +1 -1
- package/dist/install/hosts.js +1 -0
- package/dist/install/hosts.js.map +1 -1
- package/dist/install/journey.d.ts +3 -0
- package/dist/install/journey.d.ts.map +1 -1
- package/dist/install/journey.js +55 -30
- package/dist/install/journey.js.map +1 -1
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +3 -1
- package/dist/preflight.js.map +1 -1
- package/dist/router.d.ts +10 -1
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +485 -38
- package/dist/router.js.map +1 -1
- package/dist/sbom.json +21 -21
- package/dist/scanner/enable.d.ts +1 -1
- package/dist/scanner/enable.d.ts.map +1 -1
- package/dist/scanner/enable.js +13 -8
- package/dist/scanner/enable.js.map +1 -1
- package/dist/scanner/service.js +2 -2
- package/dist/scanner/service.js.map +1 -1
- package/dist/scanner-release.json +19 -19
- package/dist/status.d.ts +6 -1
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +46 -37
- package/dist/status.js.map +1 -1
- package/package.json +31 -31
package/dist/router.js
CHANGED
|
@@ -517,17 +517,311 @@ var init_repositoryFingerprint = __esm({
|
|
|
517
517
|
});
|
|
518
518
|
|
|
519
519
|
// packages/shared/dist/projectIdentityFile.js
|
|
520
|
+
import { lstat, readFile } from "node:fs/promises";
|
|
521
|
+
import { join as join2 } from "node:path";
|
|
522
|
+
function parseIdentityFile(text) {
|
|
523
|
+
let value;
|
|
524
|
+
try {
|
|
525
|
+
value = JSON.parse(text);
|
|
526
|
+
} catch (error) {
|
|
527
|
+
return { kind: "malformed", detail: `unparseable JSON: ${error.message}` };
|
|
528
|
+
}
|
|
529
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
530
|
+
return { kind: "malformed", detail: "identity file must contain a JSON object" };
|
|
531
|
+
}
|
|
532
|
+
const record = value;
|
|
533
|
+
if (record.schemaVersion !== 1) {
|
|
534
|
+
return { kind: "unknown_version", version: record.schemaVersion };
|
|
535
|
+
}
|
|
536
|
+
const unknownKey = Object.keys(record).find((key) => !IDENTITY_KEYS.has(key));
|
|
537
|
+
if (unknownKey)
|
|
538
|
+
return { kind: "malformed", detail: `unknown key "${unknownKey}"` };
|
|
539
|
+
if (!isCanonicalUuid(record.projectId)) {
|
|
540
|
+
return { kind: "malformed", detail: '"projectId" must be a canonical RFC 4122 UUID string' };
|
|
541
|
+
}
|
|
542
|
+
if ("projectName" in record && typeof record.projectName !== "string") {
|
|
543
|
+
return { kind: "malformed", detail: '"projectName" must be a string when present' };
|
|
544
|
+
}
|
|
545
|
+
if ("repositoryFingerprint" in record && (!record.repositoryFingerprint || typeof record.repositoryFingerprint !== "object" || Array.isArray(record.repositoryFingerprint))) {
|
|
546
|
+
return { kind: "malformed", detail: '"repositoryFingerprint" must be an object when present' };
|
|
547
|
+
}
|
|
548
|
+
const fingerprint = record.repositoryFingerprint;
|
|
549
|
+
const unknownFingerprintKey = fingerprint ? Object.keys(fingerprint).find((key) => !FINGERPRINT_KEYS.has(key)) : void 0;
|
|
550
|
+
if (unknownFingerprintKey) {
|
|
551
|
+
return {
|
|
552
|
+
kind: "malformed",
|
|
553
|
+
detail: `unknown repositoryFingerprint key "${unknownFingerprintKey}"`
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
if (fingerprint && (fingerprint.algorithmVersion !== 1 || typeof fingerprint.hash !== "string")) {
|
|
557
|
+
return {
|
|
558
|
+
kind: "malformed",
|
|
559
|
+
detail: '"repositoryFingerprint" must contain algorithmVersion 1 and a string hash'
|
|
560
|
+
};
|
|
561
|
+
}
|
|
562
|
+
const repositoryFingerprint = fingerprint ? { algorithmVersion: 1, hash: fingerprint.hash } : void 0;
|
|
563
|
+
return {
|
|
564
|
+
kind: "ok",
|
|
565
|
+
identity: {
|
|
566
|
+
schemaVersion: 1,
|
|
567
|
+
projectId: record.projectId,
|
|
568
|
+
...record.projectName === void 0 ? {} : { projectName: record.projectName },
|
|
569
|
+
...repositoryFingerprint ? { repositoryFingerprint } : {}
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
async function readIdentityFile(dir, options = {}) {
|
|
574
|
+
const path = join2(dir, ".mnemonik.json");
|
|
575
|
+
try {
|
|
576
|
+
const stat = await lstat(path);
|
|
577
|
+
if (stat.isSymbolicLink())
|
|
578
|
+
return { kind: "malformed", detail: "symlink" };
|
|
579
|
+
if (!stat.isFile())
|
|
580
|
+
return { kind: "malformed", detail: "identity path is not a regular file" };
|
|
581
|
+
const text = await readFile(path, "utf8");
|
|
582
|
+
if (options.selectedRoot) {
|
|
583
|
+
try {
|
|
584
|
+
const value = JSON.parse(text);
|
|
585
|
+
if (value && typeof value === "object" && !Array.isArray(value) && !("projectId" in value))
|
|
586
|
+
return { kind: "absent" };
|
|
587
|
+
} catch {
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
return parseIdentityFile(text);
|
|
591
|
+
} catch (error) {
|
|
592
|
+
if (error.code === "ENOENT")
|
|
593
|
+
return { kind: "absent" };
|
|
594
|
+
return { kind: "malformed", detail: `cannot read identity file: ${error.message}` };
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
var CANONICAL_UUID, isCanonicalUuid, IDENTITY_KEYS, FINGERPRINT_KEYS;
|
|
520
598
|
var init_projectIdentityFile = __esm({
|
|
521
599
|
"packages/shared/dist/projectIdentityFile.js"() {
|
|
522
600
|
"use strict";
|
|
601
|
+
CANONICAL_UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
602
|
+
isCanonicalUuid = (value) => typeof value === "string" && CANONICAL_UUID.test(value);
|
|
603
|
+
IDENTITY_KEYS = /* @__PURE__ */ new Set([
|
|
604
|
+
"schemaVersion",
|
|
605
|
+
"projectId",
|
|
606
|
+
"projectName",
|
|
607
|
+
"repositoryFingerprint"
|
|
608
|
+
]);
|
|
609
|
+
FINGERPRINT_KEYS = /* @__PURE__ */ new Set(["algorithmVersion", "hash"]);
|
|
523
610
|
}
|
|
524
611
|
});
|
|
525
612
|
|
|
526
613
|
// packages/shared/dist/repositoryRoot.js
|
|
614
|
+
import { lstat as lstat2, readFile as readFile2 } from "node:fs/promises";
|
|
615
|
+
import { execFile } from "node:child_process";
|
|
616
|
+
import { homedir } from "node:os";
|
|
617
|
+
import { dirname as dirname2, join as join3, resolve } from "node:path";
|
|
618
|
+
function gitEnvironment() {
|
|
619
|
+
const env = {};
|
|
620
|
+
for (const key of GIT_ENV_KEYS) {
|
|
621
|
+
if (process.env[key] !== void 0)
|
|
622
|
+
env[key] = process.env[key];
|
|
623
|
+
}
|
|
624
|
+
env.LC_ALL = "C";
|
|
625
|
+
return env;
|
|
626
|
+
}
|
|
627
|
+
function runGit(cwd, args2) {
|
|
628
|
+
return new Promise((resolvePromise, reject) => {
|
|
629
|
+
execFile("git", args2, { cwd, timeout: GIT_TIMEOUT_MS, encoding: "utf8", env: gitEnvironment() }, (error, stdout, stderr) => {
|
|
630
|
+
if (error)
|
|
631
|
+
reject(Object.assign(error, { stdout, stderr }));
|
|
632
|
+
else
|
|
633
|
+
resolvePromise({ stdout, stderr });
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
async function boundaryAt(path) {
|
|
638
|
+
try {
|
|
639
|
+
const stat = await lstat2(join3(path, ".git"));
|
|
640
|
+
if (stat.isDirectory())
|
|
641
|
+
return { path, kind: "directory" };
|
|
642
|
+
if (stat.isFile())
|
|
643
|
+
return { path, kind: "file" };
|
|
644
|
+
} catch (error) {
|
|
645
|
+
const code = error.code;
|
|
646
|
+
if (code !== "ENOENT" && code !== "ENOTDIR")
|
|
647
|
+
throw error;
|
|
648
|
+
}
|
|
649
|
+
return void 0;
|
|
650
|
+
}
|
|
651
|
+
async function confirmedBoundaryAt(path) {
|
|
652
|
+
const boundary = await boundaryAt(path);
|
|
653
|
+
if (!boundary)
|
|
654
|
+
return void 0;
|
|
655
|
+
try {
|
|
656
|
+
const { stdout } = await runGit(path, ["rev-parse", "--git-dir"]);
|
|
657
|
+
return stdout.trim() ? boundary : void 0;
|
|
658
|
+
} catch {
|
|
659
|
+
return void 0;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
async function boundariesBetween(cwd, root) {
|
|
663
|
+
const boundaries = [];
|
|
664
|
+
let directory = cwd;
|
|
665
|
+
while (directory !== root) {
|
|
666
|
+
const boundary = await confirmedBoundaryAt(directory);
|
|
667
|
+
if (boundary)
|
|
668
|
+
boundaries.push(boundary);
|
|
669
|
+
const parent = dirname2(directory);
|
|
670
|
+
if (parent === directory)
|
|
671
|
+
break;
|
|
672
|
+
directory = parent;
|
|
673
|
+
}
|
|
674
|
+
return boundaries;
|
|
675
|
+
}
|
|
676
|
+
async function containingRepository(root) {
|
|
677
|
+
let directory = dirname2(root);
|
|
678
|
+
while (true) {
|
|
679
|
+
const boundary = await confirmedBoundaryAt(directory);
|
|
680
|
+
if (boundary)
|
|
681
|
+
return boundary;
|
|
682
|
+
const parent = dirname2(directory);
|
|
683
|
+
if (parent === directory)
|
|
684
|
+
return void 0;
|
|
685
|
+
directory = parent;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
async function canonicalBoundaryRoot(boundary) {
|
|
689
|
+
if (boundary.kind === "directory")
|
|
690
|
+
return boundary.path;
|
|
691
|
+
const pointer = /^gitdir:\s*(.+)\s*$/im.exec(await readFile2(join3(boundary.path, ".git"), "utf8"))?.[1];
|
|
692
|
+
if (!pointer)
|
|
693
|
+
return boundary.path;
|
|
694
|
+
const gitDir = resolve(boundary.path, pointer);
|
|
695
|
+
try {
|
|
696
|
+
const commonDir = resolve(gitDir, (await readFile2(join3(gitDir, "commondir"), "utf8")).trim());
|
|
697
|
+
return dirname2(commonDir);
|
|
698
|
+
} catch (error) {
|
|
699
|
+
if (error.code === "ENOENT")
|
|
700
|
+
return boundary.path;
|
|
701
|
+
throw error;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
async function resolveRepositoryRoot(cwd) {
|
|
705
|
+
const absoluteCwd = resolve(cwd);
|
|
706
|
+
try {
|
|
707
|
+
const { stdout } = await runGit(absoluteCwd, [
|
|
708
|
+
"rev-parse",
|
|
709
|
+
"--show-toplevel",
|
|
710
|
+
"--git-common-dir"
|
|
711
|
+
]);
|
|
712
|
+
const [rootLine, commonLine, ...extra] = stdout.trim().split(/\r?\n/);
|
|
713
|
+
if (!rootLine || !commonLine || extra.length) {
|
|
714
|
+
return { kind: "git_unavailable", detail: "git rev-parse returned an unexpected response" };
|
|
715
|
+
}
|
|
716
|
+
const root = resolve(rootLine);
|
|
717
|
+
const commonDir = resolve(root, commonLine);
|
|
718
|
+
const isLinkedWorktree = commonDir !== join3(root, ".git");
|
|
719
|
+
const nested = await boundariesBetween(absoluteCwd, root);
|
|
720
|
+
if (!isLinkedWorktree && await containingRepository(root)) {
|
|
721
|
+
const boundary = await boundaryAt(root);
|
|
722
|
+
if (boundary)
|
|
723
|
+
nested.push(boundary);
|
|
724
|
+
}
|
|
725
|
+
return {
|
|
726
|
+
kind: "git",
|
|
727
|
+
root,
|
|
728
|
+
commonDir,
|
|
729
|
+
isLinkedWorktree,
|
|
730
|
+
nested
|
|
731
|
+
};
|
|
732
|
+
} catch (error) {
|
|
733
|
+
const failure = error;
|
|
734
|
+
if (failure.code === 128 && /not a git repository/i.test(failure.stderr ?? failure.message)) {
|
|
735
|
+
return { kind: "plain", root: absoluteCwd };
|
|
736
|
+
}
|
|
737
|
+
return { kind: "git_unavailable", detail: failure.message };
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
async function readPlainIdentity(start2) {
|
|
741
|
+
const home = resolve(homedir());
|
|
742
|
+
let directory = start2;
|
|
743
|
+
while (true) {
|
|
744
|
+
const result = await readIdentityFile(directory);
|
|
745
|
+
if (result.kind !== "absent")
|
|
746
|
+
return { root: directory, result };
|
|
747
|
+
if (directory === home)
|
|
748
|
+
break;
|
|
749
|
+
const parent = dirname2(directory);
|
|
750
|
+
if (parent === directory)
|
|
751
|
+
break;
|
|
752
|
+
directory = parent;
|
|
753
|
+
}
|
|
754
|
+
return { root: start2, result: { kind: "absent" } };
|
|
755
|
+
}
|
|
756
|
+
function withBase(repository, root, nested) {
|
|
757
|
+
return { root, repository, nested };
|
|
758
|
+
}
|
|
759
|
+
async function resolveProjectIdentity(cwd, options = {}) {
|
|
760
|
+
const resolved = await resolveRepositoryRoot(cwd);
|
|
761
|
+
const repository = resolved.kind === "git_unavailable" ? { kind: "plain", root: resolve(cwd) } : resolved;
|
|
762
|
+
if (repository.kind === "plain") {
|
|
763
|
+
const { root, result } = options.selectedRoot ? { root: repository.root, result: await readIdentityFile(repository.root, options) } : await readPlainIdentity(repository.root);
|
|
764
|
+
const base2 = withBase(repository, root, []);
|
|
765
|
+
if (result.kind === "ok")
|
|
766
|
+
return { ...base2, ...result };
|
|
767
|
+
if (result.kind === "unknown_version")
|
|
768
|
+
return { ...base2, ...result, path: root };
|
|
769
|
+
if (result.kind === "malformed")
|
|
770
|
+
return { ...base2, ...result, path: root };
|
|
771
|
+
return { ...base2, kind: "absent" };
|
|
772
|
+
}
|
|
773
|
+
const ownRoot = repository.isLinkedWorktree ? dirname2(repository.commonDir) : repository.root;
|
|
774
|
+
const outer = repository.isLinkedWorktree ? void 0 : await containingRepository(repository.root);
|
|
775
|
+
const own = await readIdentityFile(ownRoot, options);
|
|
776
|
+
if (!outer || options.selectedRoot || own.kind === "ok") {
|
|
777
|
+
const base2 = withBase(repository, ownRoot, repository.nested);
|
|
778
|
+
if (own.kind === "ok")
|
|
779
|
+
return { ...base2, ...own };
|
|
780
|
+
if (own.kind === "unknown_version")
|
|
781
|
+
return { ...base2, ...own, path: ownRoot };
|
|
782
|
+
if (own.kind === "malformed")
|
|
783
|
+
return { ...base2, ...own, path: ownRoot };
|
|
784
|
+
return { ...base2, kind: "absent" };
|
|
785
|
+
}
|
|
786
|
+
const nested = repository.nested;
|
|
787
|
+
const parentRoot = await canonicalBoundaryRoot(outer);
|
|
788
|
+
const parent = await readIdentityFile(parentRoot);
|
|
789
|
+
const base = withBase(repository, parentRoot, nested);
|
|
790
|
+
if (own.kind === "unknown_version")
|
|
791
|
+
return { ...base, ...own, path: ownRoot };
|
|
792
|
+
if (own.kind === "malformed")
|
|
793
|
+
return { ...base, ...own, path: ownRoot };
|
|
794
|
+
if (parent.kind === "unknown_version")
|
|
795
|
+
return { ...base, ...parent, path: parentRoot };
|
|
796
|
+
if (parent.kind === "malformed")
|
|
797
|
+
return { ...base, ...parent, path: parentRoot };
|
|
798
|
+
if (!options.allowNestedInherit) {
|
|
799
|
+
return {
|
|
800
|
+
...base,
|
|
801
|
+
kind: "nested",
|
|
802
|
+
...parent.kind === "ok" ? { parentIdentity: parent.identity } : {}
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
if (parent.kind === "ok")
|
|
806
|
+
return { ...base, kind: "ok", identity: parent.identity };
|
|
807
|
+
return { ...base, kind: "absent" };
|
|
808
|
+
}
|
|
809
|
+
var GIT_TIMEOUT_MS, GIT_ENV_KEYS;
|
|
527
810
|
var init_repositoryRoot = __esm({
|
|
528
811
|
"packages/shared/dist/repositoryRoot.js"() {
|
|
529
812
|
"use strict";
|
|
530
813
|
init_projectIdentityFile();
|
|
814
|
+
GIT_TIMEOUT_MS = 2e3;
|
|
815
|
+
GIT_ENV_KEYS = [
|
|
816
|
+
"PATH",
|
|
817
|
+
"HOME",
|
|
818
|
+
"LANG",
|
|
819
|
+
"LC_ALL",
|
|
820
|
+
"SYSTEMROOT",
|
|
821
|
+
"TEMP",
|
|
822
|
+
"TMP",
|
|
823
|
+
"USERPROFILE"
|
|
824
|
+
];
|
|
531
825
|
}
|
|
532
826
|
});
|
|
533
827
|
|
|
@@ -2183,13 +2477,13 @@ async function Module2(moduleArg = {}) {
|
|
|
2183
2477
|
}
|
|
2184
2478
|
readAsync = /* @__PURE__ */ __name(async (url) => {
|
|
2185
2479
|
if (isFileURI(url)) {
|
|
2186
|
-
return new Promise((
|
|
2480
|
+
return new Promise((resolve2, reject) => {
|
|
2187
2481
|
var xhr = new XMLHttpRequest();
|
|
2188
2482
|
xhr.open("GET", url, true);
|
|
2189
2483
|
xhr.responseType = "arraybuffer";
|
|
2190
2484
|
xhr.onload = () => {
|
|
2191
2485
|
if (xhr.status == 200 || xhr.status == 0 && xhr.response) {
|
|
2192
|
-
|
|
2486
|
+
resolve2(xhr.response);
|
|
2193
2487
|
return;
|
|
2194
2488
|
}
|
|
2195
2489
|
reject(xhr.status);
|
|
@@ -2385,9 +2679,9 @@ async function Module2(moduleArg = {}) {
|
|
|
2385
2679
|
__name(receiveInstantiationResult, "receiveInstantiationResult");
|
|
2386
2680
|
var info22 = getWasmImports();
|
|
2387
2681
|
if (Module["instantiateWasm"]) {
|
|
2388
|
-
return new Promise((
|
|
2682
|
+
return new Promise((resolve2, reject) => {
|
|
2389
2683
|
Module["instantiateWasm"](info22, (mod, inst) => {
|
|
2390
|
-
|
|
2684
|
+
resolve2(receiveInstance(mod, inst));
|
|
2391
2685
|
});
|
|
2392
2686
|
});
|
|
2393
2687
|
}
|
|
@@ -3718,8 +4012,8 @@ async function Module2(moduleArg = {}) {
|
|
|
3718
4012
|
if (runtimeInitialized) {
|
|
3719
4013
|
moduleRtn = Module;
|
|
3720
4014
|
} else {
|
|
3721
|
-
moduleRtn = new Promise((
|
|
3722
|
-
readyPromiseResolve =
|
|
4015
|
+
moduleRtn = new Promise((resolve2, reject) => {
|
|
4016
|
+
readyPromiseResolve = resolve2;
|
|
3723
4017
|
readyPromiseReject = reject;
|
|
3724
4018
|
});
|
|
3725
4019
|
}
|
|
@@ -4866,10 +5160,10 @@ function apiOrigin(env = process.env) {
|
|
|
4866
5160
|
|
|
4867
5161
|
// packages/local-setup/dist/storage.js
|
|
4868
5162
|
init_hookRuntime();
|
|
4869
|
-
import { homedir } from "node:os";
|
|
4870
|
-
import { dirname as
|
|
5163
|
+
import { homedir as homedir2 } from "node:os";
|
|
5164
|
+
import { dirname as dirname3, join as join4, win32, posix } from "node:path";
|
|
4871
5165
|
init_hookRuntime();
|
|
4872
|
-
function stateDirectory(platform = process.platform, env = process.env, home =
|
|
5166
|
+
function stateDirectory(platform = process.platform, env = process.env, home = homedir2()) {
|
|
4873
5167
|
if (env.MNEMONIK_STATE_DIR)
|
|
4874
5168
|
return env.MNEMONIK_STATE_DIR;
|
|
4875
5169
|
if (platform === "win32")
|
|
@@ -4956,12 +5250,12 @@ import {
|
|
|
4956
5250
|
import { hostOrder, launchHostLabels } from "./install/adapters.js";
|
|
4957
5251
|
import { readInstallVersions } from "./install/ownership.js";
|
|
4958
5252
|
import { ensureLauncher, removeLauncher, LauncherError } from "./launcher.js";
|
|
4959
|
-
import { readFile, realpath } from "node:fs/promises";
|
|
5253
|
+
import { readFile as readFile3, realpath } from "node:fs/promises";
|
|
4960
5254
|
import { createInterface } from "node:readline";
|
|
4961
5255
|
import { RuntimeStore, updateRuntime } from "./runtime/store.js";
|
|
4962
5256
|
import { updateCli, cliUpdateHint } from "./runtime/selfUpdate.js";
|
|
4963
|
-
import { homedir as
|
|
4964
|
-
import { join as
|
|
5257
|
+
import { homedir as homedir3 } from "node:os";
|
|
5258
|
+
import { join as join5 } from "node:path";
|
|
4965
5259
|
import { Output } from "./output.js";
|
|
4966
5260
|
import { SCANNER_RESTART_MESSAGE } from "./scanner/service.js";
|
|
4967
5261
|
import { SCANNER_FAILURE_MESSAGE, SCANNER_RETRY_MESSAGE } from "./screens/journey.js";
|
|
@@ -4978,6 +5272,7 @@ import {
|
|
|
4978
5272
|
import { evaluateRoot } from "./project/eligibility.js";
|
|
4979
5273
|
import { grantTransport, grantHost } from "./auth/status.js";
|
|
4980
5274
|
import { createCliAuth } from "./auth/index.js";
|
|
5275
|
+
import { runEditorLogin } from "./auth/pkce.js";
|
|
4981
5276
|
import { currentInstallSession, ensureInstallSession } from "./auth/installSession.js";
|
|
4982
5277
|
import { runIdentityMigration } from "./identity/migrate.js";
|
|
4983
5278
|
import { renderScannerStatus } from "./scanner/picker.js";
|
|
@@ -5005,7 +5300,14 @@ import {
|
|
|
5005
5300
|
var connectFolderPrompt = (name2) => `Connect ${name2} to Mnemonik? [Y/n]`;
|
|
5006
5301
|
var removeFolderPrompt = (name2) => `Stop indexing ${name2}? Its memories stay in your account. [y/N]`;
|
|
5007
5302
|
var connectedFolderLine = (name2) => ` \u2713 Connected ${name2}.`;
|
|
5303
|
+
var alreadyConnectedFolderLine = (name2) => ` \u2713 ${name2} is already connected and watched.`;
|
|
5008
5304
|
var removedFolderLine = (name2) => ` \u2713 ${name2} is no longer connected.`;
|
|
5305
|
+
var projectDeletionWarning = (name2) => `Deleting ${name2} removes its memories, code index and summaries for everyone. This cannot be undone.`;
|
|
5306
|
+
var projectDeletedLine = (name2) => `Deleted ${name2}.`;
|
|
5307
|
+
var stillWatchedLine = (root) => `The folder is still being indexed. Run mnemonik remove ${root} to stop that.`;
|
|
5308
|
+
var identityFileKeptLine = "This folder's .mnemonik.json still points at the deleted project. Connecting the folder again creates a new project.";
|
|
5309
|
+
var CODEX_SIGNED_IN_MESSAGE = "Codex is signed in to Mnemonik.";
|
|
5310
|
+
var CONNECT_NOT_APPROVED_MESSAGE = "Sign-in timed out. Run mnemonik connect codex to try again.";
|
|
5009
5311
|
function maintenanceExitCode(results) {
|
|
5010
5312
|
if (results.some((result) => result.status === "FAILED")) return 1;
|
|
5011
5313
|
return results.every((result) => result.status === "READY") ? 0 : 3;
|
|
@@ -5064,7 +5366,7 @@ Commands:
|
|
|
5064
5366
|
install
|
|
5065
5367
|
status
|
|
5066
5368
|
connect <${hostOrder.join("|")}>
|
|
5067
|
-
project <init|setup|status|link|ensure>
|
|
5369
|
+
project <init|setup|status|link|ensure|delete>
|
|
5068
5370
|
add <folder>
|
|
5069
5371
|
remove <folder>
|
|
5070
5372
|
data delete --project <id>
|
|
@@ -5083,6 +5385,7 @@ Install consent: --accept-indexing --accept-limited --apply`;
|
|
|
5083
5385
|
function parse(args2) {
|
|
5084
5386
|
const positionals = [];
|
|
5085
5387
|
const flags2 = /* @__PURE__ */ new Map();
|
|
5388
|
+
const namedConfirm = args2[0] === "project" && args2[1] === "delete";
|
|
5086
5389
|
for (let index = 0; index < args2.length; index++) {
|
|
5087
5390
|
const argument = args2[index] ?? "";
|
|
5088
5391
|
if (!argument.startsWith("--")) {
|
|
@@ -5096,8 +5399,17 @@ function parse(args2) {
|
|
|
5096
5399
|
continue;
|
|
5097
5400
|
}
|
|
5098
5401
|
if (booleans.has(name2)) {
|
|
5099
|
-
|
|
5100
|
-
|
|
5402
|
+
const takesName = name2 === "confirm" && namedConfirm;
|
|
5403
|
+
if (inline !== void 0 && !takesName)
|
|
5404
|
+
return { positionals, flags: flags2, error: `Unknown flag: ${argument}` };
|
|
5405
|
+
const next = args2[index + 1];
|
|
5406
|
+
let value = true;
|
|
5407
|
+
if (takesName && inline !== void 0) value = inline;
|
|
5408
|
+
else if (takesName && next !== void 0 && !next.startsWith("--")) {
|
|
5409
|
+
value = next;
|
|
5410
|
+
index++;
|
|
5411
|
+
}
|
|
5412
|
+
flags2.set(name2 === "accept-scanner" ? "accept-indexing" : name2, value);
|
|
5101
5413
|
continue;
|
|
5102
5414
|
}
|
|
5103
5415
|
if (values.has(name2)) {
|
|
@@ -5179,7 +5491,7 @@ async function hostDependencies(deps, output, state) {
|
|
|
5179
5491
|
if (!cliAuth.accountEmail) throw new Error("account_identity_failed");
|
|
5180
5492
|
const email = await cliAuth.accountEmail(bearer);
|
|
5181
5493
|
const installation = JSON.parse(
|
|
5182
|
-
await
|
|
5494
|
+
await readFile3(join5(state, "installation.json"), "utf8").catch(() => "{}")
|
|
5183
5495
|
);
|
|
5184
5496
|
return {
|
|
5185
5497
|
stateDir: state,
|
|
@@ -5196,7 +5508,7 @@ async function hostDependencies(deps, output, state) {
|
|
|
5196
5508
|
async function updateHostDependencies(deps, state) {
|
|
5197
5509
|
if (deps.hostManagement) return { ...deps.hostManagement, stateDir: state };
|
|
5198
5510
|
const installation = JSON.parse(
|
|
5199
|
-
await
|
|
5511
|
+
await readFile3(join5(state, "installation.json"), "utf8").catch(() => "{}")
|
|
5200
5512
|
);
|
|
5201
5513
|
return {
|
|
5202
5514
|
stateDir: state,
|
|
@@ -5204,7 +5516,7 @@ async function updateHostDependencies(deps, state) {
|
|
|
5204
5516
|
};
|
|
5205
5517
|
}
|
|
5206
5518
|
async function packageVersion() {
|
|
5207
|
-
const contents = await
|
|
5519
|
+
const contents = await readFile3(new URL("../package.json", import.meta.url), "utf8");
|
|
5208
5520
|
return JSON.parse(contents).version;
|
|
5209
5521
|
}
|
|
5210
5522
|
async function runHostCommand(command, parsed, deps, output, scannerSelected = false) {
|
|
@@ -5236,7 +5548,7 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5236
5548
|
component: component2,
|
|
5237
5549
|
host: name2,
|
|
5238
5550
|
scope: "user",
|
|
5239
|
-
home: deps.home ??
|
|
5551
|
+
home: deps.home ?? homedir3(),
|
|
5240
5552
|
projectRoot: deps.cwd ?? process.cwd()
|
|
5241
5553
|
}))
|
|
5242
5554
|
);
|
|
@@ -5305,7 +5617,7 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5305
5617
|
noBrowser: parsed.flags.has("no-browser"),
|
|
5306
5618
|
source: dependencies.source ?? (updatedCli ? (host2) => hostSource(
|
|
5307
5619
|
host2,
|
|
5308
|
-
|
|
5620
|
+
join5(updatedCli.directory, "node_modules/@mnemonik/cli/package.json")
|
|
5309
5621
|
) : void 0),
|
|
5310
5622
|
instruction: json ? void 0 : (text) => output.line(text),
|
|
5311
5623
|
apply: parsed.flags.has("apply")
|
|
@@ -5316,7 +5628,7 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5316
5628
|
let scanner;
|
|
5317
5629
|
let launcher;
|
|
5318
5630
|
let scannerRecovery;
|
|
5319
|
-
if (all && await
|
|
5631
|
+
if (all && await readFile3(`${state}/scanner/state.json`).then(
|
|
5320
5632
|
() => true,
|
|
5321
5633
|
() => false
|
|
5322
5634
|
)) {
|
|
@@ -5358,7 +5670,7 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5358
5670
|
if (fullUninstall && hostExit === 0) {
|
|
5359
5671
|
const installed = await Promise.all(
|
|
5360
5672
|
[new RuntimeStore(state).pointerPath("scanner"), `${state}/scanner/state.json`].map(
|
|
5361
|
-
(path) =>
|
|
5673
|
+
(path) => readFile3(path).then(
|
|
5362
5674
|
() => true,
|
|
5363
5675
|
() => false
|
|
5364
5676
|
)
|
|
@@ -5402,18 +5714,29 @@ async function runHostCommand(command, parsed, deps, output, scannerSelected = f
|
|
|
5402
5714
|
...remaining ? { remaining } : {}
|
|
5403
5715
|
});
|
|
5404
5716
|
else if (command === "update") {
|
|
5405
|
-
if (failed || hostsFailed)
|
|
5406
|
-
|
|
5717
|
+
if (failed || hostsFailed) {
|
|
5718
|
+
if (cli?.status === "UPDATED") output.line("The mnemonik command updated.");
|
|
5719
|
+
if (result.reports.length > 0 && !hostsFailed) output.line("Your editors updated.");
|
|
5720
|
+
if (scanner?.status === "UPDATED") output.line("The scanner updated.");
|
|
5721
|
+
if (cli?.status === "FAILED") {
|
|
5722
|
+
output.error("The mnemonik command could not update.");
|
|
5723
|
+
output.error("Run npx -y @mnemonik/cli@latest install to update it.");
|
|
5724
|
+
}
|
|
5725
|
+
if (hostsFailed) {
|
|
5726
|
+
output.error("Your editors could not update.");
|
|
5727
|
+
output.error("Run mnemonik repair, then start a new session in each editor.");
|
|
5728
|
+
}
|
|
5729
|
+
if (scanner?.status === "FAILED") {
|
|
5730
|
+
output.error(scannerRecovery?.message ?? "The scanner could not update.");
|
|
5731
|
+
output.error(scannerRecovery?.action ?? SCANNER_RETRY_MESSAGE);
|
|
5732
|
+
}
|
|
5733
|
+
} else if (codexTrustPending) {
|
|
5407
5734
|
output.line("Mnemonik updated.");
|
|
5408
5735
|
output.line(CODEX_TRUST_MESSAGE.sentence);
|
|
5409
5736
|
output.line(CODEX_TRUST_MESSAGE.nextStep);
|
|
5410
5737
|
} else if (cli?.status === "UPDATED" || result.reports.length > 0 || scanner?.status === "UPDATED")
|
|
5411
5738
|
output.line("Mnemonik updated.");
|
|
5412
5739
|
else output.line("Mnemonik is up to date.");
|
|
5413
|
-
if (scannerRecovery) {
|
|
5414
|
-
output.error(scannerRecovery.message);
|
|
5415
|
-
if (scannerRecovery.action) output.error(scannerRecovery.action);
|
|
5416
|
-
}
|
|
5417
5740
|
} else {
|
|
5418
5741
|
for (const target of result.results)
|
|
5419
5742
|
output.line(target.status === "READY" ? "Done." : humanReason(target.reason));
|
|
@@ -5591,7 +5914,7 @@ async function doctorCommand(parsed, deps, output) {
|
|
|
5591
5914
|
const invalid = allowed(parsed, []);
|
|
5592
5915
|
if (invalid) return output.error(invalid), 2;
|
|
5593
5916
|
const result = await runPreflight({ cwd: deps.cwd, home: deps.home, ...deps.preflight });
|
|
5594
|
-
output.setContext({ home: deps.home ??
|
|
5917
|
+
output.setContext({ home: deps.home ?? homedir3(), projectRoot: result.project.root });
|
|
5595
5918
|
const document = await collectStatusDocument({
|
|
5596
5919
|
preflight: result,
|
|
5597
5920
|
cwd: deps.cwd ?? process.cwd(),
|
|
@@ -5628,10 +5951,10 @@ async function collectCurrentInstallation(deps, output) {
|
|
|
5628
5951
|
...deps.preflight,
|
|
5629
5952
|
fetch: async () => new Response(null, { status: 204 })
|
|
5630
5953
|
});
|
|
5631
|
-
output.setContext({ home: deps.home ??
|
|
5954
|
+
output.setContext({ home: deps.home ?? homedir3(), projectRoot: result.project.root });
|
|
5632
5955
|
const hostStateDir = deps.hostManagement?.stateDir ?? deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
5633
5956
|
const localConditions = deps.projectHookConditions ? [] : [
|
|
5634
|
-
...await localInstallationConditions(deps.home ??
|
|
5957
|
+
...await localInstallationConditions(deps.home ?? homedir3(), hostStateDir, deps.launcher),
|
|
5635
5958
|
// Installed Codex hooks that Codex has not trusted cannot run.
|
|
5636
5959
|
...await (deps.codexTrustConditions ?? (() => codexTrustConditions({
|
|
5637
5960
|
stateDir: hostStateDir,
|
|
@@ -5675,6 +5998,96 @@ async function reportCurrentInstallation(deps, output, document) {
|
|
|
5675
5998
|
).catch(() => {
|
|
5676
5999
|
});
|
|
5677
6000
|
}
|
|
6001
|
+
async function deleteProjectCommand(parsed, rest, deps, output) {
|
|
6002
|
+
const json = parsed.flags.has("json");
|
|
6003
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
6004
|
+
const resolve2 = deps.projectResolver?.resolveProjectIdentity ?? resolveProjectIdentity;
|
|
6005
|
+
const here = await resolve2(cwd, { allowNestedInherit: false });
|
|
6006
|
+
const hereId = here.kind === "ok" ? here.identity.projectId : void 0;
|
|
6007
|
+
const root = "root" in here ? here.root : cwd;
|
|
6008
|
+
const target = rest[0] ?? hereId;
|
|
6009
|
+
if (!target) {
|
|
6010
|
+
output.error(
|
|
6011
|
+
"This folder is not connected to a project. Run mnemonik project delete <name> instead."
|
|
6012
|
+
);
|
|
6013
|
+
return 3;
|
|
6014
|
+
}
|
|
6015
|
+
const bearer = await ensureCliAuth(deps, output, parsed.flags.has("no-browser"), false);
|
|
6016
|
+
const send = deps.grantFetch ?? fetch;
|
|
6017
|
+
const listed = await send(`${apiOrigin()}/api/v1/users/me/projects?days=0&limit=200`, {
|
|
6018
|
+
headers: { Authorization: `Bearer ${bearer}` }
|
|
6019
|
+
});
|
|
6020
|
+
if (!listed.ok) {
|
|
6021
|
+
output.error("Mnemonik could not be reached from this machine.");
|
|
6022
|
+
return 3;
|
|
6023
|
+
}
|
|
6024
|
+
const listing = await listed.json().catch(() => []);
|
|
6025
|
+
const projects = Array.isArray(listing) ? listing : [];
|
|
6026
|
+
const project = projects.find(
|
|
6027
|
+
(candidate) => candidate.id === target || candidate.name?.toLowerCase() === target.toLowerCase()
|
|
6028
|
+
);
|
|
6029
|
+
if (!project) {
|
|
6030
|
+
output.error(`There is no project called ${target} in your account.`);
|
|
6031
|
+
return 3;
|
|
6032
|
+
}
|
|
6033
|
+
const supplied = parsed.flags.get("confirm");
|
|
6034
|
+
let typed = typeof supplied === "string" ? supplied : "";
|
|
6035
|
+
if (typeof supplied !== "string") {
|
|
6036
|
+
if (parsed.flags.has("non-interactive") || json) {
|
|
6037
|
+
output.error(
|
|
6038
|
+
`To skip this check, run mnemonik project delete ${project.name} --confirm "${project.name}".`
|
|
6039
|
+
);
|
|
6040
|
+
return 3;
|
|
6041
|
+
}
|
|
6042
|
+
output.line(projectDeletionWarning(project.name));
|
|
6043
|
+
output.line("Type the project name to confirm.");
|
|
6044
|
+
const readline = createInterface({ input: deps.input ?? process.stdin, terminal: false });
|
|
6045
|
+
typed = String((await readline[Symbol.asyncIterator]().next()).value ?? "").trim();
|
|
6046
|
+
readline.close();
|
|
6047
|
+
if (typed.toLowerCase() !== project.name.toLowerCase()) {
|
|
6048
|
+
output.line("Nothing was deleted.");
|
|
6049
|
+
return 130;
|
|
6050
|
+
}
|
|
6051
|
+
}
|
|
6052
|
+
if (typed.toLowerCase() !== project.name.toLowerCase()) {
|
|
6053
|
+
output.error("That is not the project name. Nothing was deleted.");
|
|
6054
|
+
return 3;
|
|
6055
|
+
}
|
|
6056
|
+
const response = await send(`${apiOrigin()}/api/v1/projects/${encodeURIComponent(project.id)}`, {
|
|
6057
|
+
method: "DELETE",
|
|
6058
|
+
headers: { Authorization: `Bearer ${bearer}`, "content-type": "application/json" },
|
|
6059
|
+
body: JSON.stringify({ confirmProjectName: typed })
|
|
6060
|
+
});
|
|
6061
|
+
if (!response.ok) {
|
|
6062
|
+
output.error(
|
|
6063
|
+
response.status === 403 ? `Only the owner of ${project.name} can delete it.` : response.status === 404 ? `There is no project called ${target} in your account.` : `${project.name} could not be deleted. Try again in a moment.`
|
|
6064
|
+
);
|
|
6065
|
+
return 3;
|
|
6066
|
+
}
|
|
6067
|
+
const result = await response.json().catch(() => ({ success: true }));
|
|
6068
|
+
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
6069
|
+
const saved = JSON.parse(
|
|
6070
|
+
await readFile3(`${stateDir}/scanner/state.json`, "utf8").catch(() => "null")
|
|
6071
|
+
);
|
|
6072
|
+
let stillWatched = false;
|
|
6073
|
+
if (hereId === project.id && saved?.config.roots.includes(root)) {
|
|
6074
|
+
const update = await updateScannerRoots({
|
|
6075
|
+
stateDir,
|
|
6076
|
+
bearer,
|
|
6077
|
+
add: [],
|
|
6078
|
+
remove: [root],
|
|
6079
|
+
fetch: deps.grantFetch
|
|
6080
|
+
}).catch(() => void 0);
|
|
6081
|
+
stillWatched = update?.status !== "updated";
|
|
6082
|
+
}
|
|
6083
|
+
if (json) output.json(result);
|
|
6084
|
+
else {
|
|
6085
|
+
output.line(projectDeletedLine(project.name));
|
|
6086
|
+
if (stillWatched) output.line(stillWatchedLine(root));
|
|
6087
|
+
if (hereId === project.id) output.line(identityFileKeptLine);
|
|
6088
|
+
}
|
|
6089
|
+
return 0;
|
|
6090
|
+
}
|
|
5678
6091
|
async function runCli(args2, deps = {}) {
|
|
5679
6092
|
const parsed = parse(args2);
|
|
5680
6093
|
const silent = parsed.flags.has("automatic");
|
|
@@ -5683,7 +6096,7 @@ async function runCli(args2, deps = {}) {
|
|
|
5683
6096
|
const stdout = silent ? discard : deps.stdout ?? process.stdout;
|
|
5684
6097
|
const stderr = silent ? discard : deps.stderr ?? process.stderr;
|
|
5685
6098
|
const output = new Output(stdout, stderr, {
|
|
5686
|
-
home: deps.home ??
|
|
6099
|
+
home: deps.home ?? homedir3()
|
|
5687
6100
|
});
|
|
5688
6101
|
if (process.env.MNEMONIK_DEV_RELEASE_DIR && !silent)
|
|
5689
6102
|
stderr.write(
|
|
@@ -5715,7 +6128,7 @@ async function runCli(args2, deps = {}) {
|
|
|
5715
6128
|
return output.error(invalid ?? "Usage: mnemonik add <folder> or mnemonik remove <folder>"), 2;
|
|
5716
6129
|
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
5717
6130
|
const saved = JSON.parse(
|
|
5718
|
-
await
|
|
6131
|
+
await readFile3(`${stateDir}/scanner/state.json`, "utf8").catch(() => "null")
|
|
5719
6132
|
);
|
|
5720
6133
|
if (!saved) return actionRequired2(output, parsed.flags.has("json"), "mnemonik install");
|
|
5721
6134
|
if (action === "list") {
|
|
@@ -5728,6 +6141,11 @@ async function runCli(args2, deps = {}) {
|
|
|
5728
6141
|
const pathArgument = actionArguments[0] ?? "";
|
|
5729
6142
|
const requested = action === "add" ? await realpath(pathArgument) : saved.config.roots.find((root) => root === pathArgument) ?? pathArgument;
|
|
5730
6143
|
const name2 = requested.split(/[\\/]/u).filter(Boolean).at(-1) ?? requested;
|
|
6144
|
+
if (action === "add" && saved.config.roots.includes(requested)) {
|
|
6145
|
+
if (parsed.flags.has("json")) output.json(saved.config.roots);
|
|
6146
|
+
else output.line(alreadyConnectedFolderLine(name2));
|
|
6147
|
+
return 0;
|
|
6148
|
+
}
|
|
5731
6149
|
if (!parsed.flags.has("non-interactive") && !parsed.flags.has("json")) {
|
|
5732
6150
|
output.line(action === "add" ? connectFolderPrompt(name2) : removeFolderPrompt(name2));
|
|
5733
6151
|
const readline = createInterface({ input: deps.input ?? process.stdin, terminal: false });
|
|
@@ -5793,7 +6211,7 @@ async function runCli(args2, deps = {}) {
|
|
|
5793
6211
|
if (invalid || rest.length) return output.error(invalid ?? "Unexpected argument"), 2;
|
|
5794
6212
|
try {
|
|
5795
6213
|
const stateDir = deps.installStateDir ?? stateDirectory(process.platform, process.env, deps.home);
|
|
5796
|
-
const saved = JSON.parse(await
|
|
6214
|
+
const saved = JSON.parse(await readFile3(`${stateDir}/scanner/state.json`, "utf8"));
|
|
5797
6215
|
const bearer = await ensureCliAuth(deps, output, false);
|
|
5798
6216
|
const response = await (deps.grantFetch ?? fetch)(
|
|
5799
6217
|
`${apiOrigin()}/api/v1/component-credentials/${encodeURIComponent(saved.config.credentialFamilyId)}/revoke`,
|
|
@@ -6030,9 +6448,25 @@ Preview: ${preview.path}
|
|
|
6030
6448
|
if (!subcommand || rest.length || !hostOrder.includes(subcommand))
|
|
6031
6449
|
return output.error(`Usage: mnemonik connect <${hostOrder.join("|")}>`), 2;
|
|
6032
6450
|
const host = subcommand;
|
|
6033
|
-
const editor = (await localEditorStatus(deps.home ??
|
|
6451
|
+
const editor = (await localEditorStatus(deps.home ?? homedir3())).find(
|
|
6034
6452
|
(candidate) => candidate.host === host
|
|
6035
6453
|
);
|
|
6454
|
+
if (host === "codex" && editor?.mcp === "ready" && !parsed.flags.has("json")) {
|
|
6455
|
+
const bearer = await auth(deps, output, false).getCliBearer().catch(() => void 0);
|
|
6456
|
+
if (typeof bearer === "string") {
|
|
6457
|
+
const outcome = await runEditorLogin({
|
|
6458
|
+
command: ["codex", "mcp", "login", "mnemonik"],
|
|
6459
|
+
apiOrigin: apiOrigin(),
|
|
6460
|
+
issuer: process.env.MNEMONIK_OAUTH_ISSUER ?? "https://auth.mnemonik.ai",
|
|
6461
|
+
bearer: () => Promise.resolve(bearer),
|
|
6462
|
+
print: (line) => void output.line(line),
|
|
6463
|
+
fetch: deps.grantFetch,
|
|
6464
|
+
...deps.editorLogin
|
|
6465
|
+
});
|
|
6466
|
+
if (outcome === "signed_in") return output.line(CODEX_SIGNED_IN_MESSAGE), 0;
|
|
6467
|
+
if (outcome === "not_approved") return output.line(CONNECT_NOT_APPROVED_MESSAGE), 1;
|
|
6468
|
+
}
|
|
6469
|
+
}
|
|
6036
6470
|
const reason = editor?.mcp === "disabled" ? `${editor.name} connection is turned off.` : editor?.mcp === "ready" ? "Finish signing in to Mnemonik in the editor." : `${launchHostLabels[host]} connection is missing.`;
|
|
6037
6471
|
const actions = editor?.mcp === "ready" ? editorAuthorizationRows([host]) : [
|
|
6038
6472
|
editor?.mcp === "disabled" ? mcpTurnOnAction[host] : "Run mnemonik install to set it up again."
|
|
@@ -6045,8 +6479,14 @@ Preview: ${preview.path}
|
|
|
6045
6479
|
return 3;
|
|
6046
6480
|
}
|
|
6047
6481
|
if (command === "project") {
|
|
6048
|
-
if (!subcommand || !["init", "setup", "status", "link", "ensure"].includes(subcommand))
|
|
6049
|
-
return output.error("Usage: mnemonik project <init|setup|status|link|ensure>"), 2;
|
|
6482
|
+
if (!subcommand || !["init", "setup", "status", "link", "ensure", "delete"].includes(subcommand))
|
|
6483
|
+
return output.error("Usage: mnemonik project <init|setup|status|link|ensure|delete>"), 2;
|
|
6484
|
+
if (subcommand === "delete") {
|
|
6485
|
+
const unknown = allowed(parsed, ["confirm"]);
|
|
6486
|
+
if (unknown || rest.length > 1)
|
|
6487
|
+
return output.error(unknown ?? "Usage: mnemonik project delete [<project id or name>]"), 2;
|
|
6488
|
+
return deleteProjectCommand(parsed, rest, deps, output);
|
|
6489
|
+
}
|
|
6050
6490
|
const invalid = allowed(
|
|
6051
6491
|
parsed,
|
|
6052
6492
|
subcommand === "ensure" ? ["agent"] : subcommand === "status" ? [] : subcommand === "link" ? ["apply", "non-git", "confirm-mismatch", "replace", "owner"] : ["apply", "non-git", "owner"]
|
|
@@ -6393,11 +6833,18 @@ Preview: ${preview.path}
|
|
|
6393
6833
|
}
|
|
6394
6834
|
var serializeReadiness2 = (input) => devReadiness(serializeReadiness(input));
|
|
6395
6835
|
export {
|
|
6836
|
+
CODEX_SIGNED_IN_MESSAGE,
|
|
6837
|
+
CONNECT_NOT_APPROVED_MESSAGE,
|
|
6838
|
+
alreadyConnectedFolderLine,
|
|
6396
6839
|
connectFolderPrompt,
|
|
6397
6840
|
connectedFolderLine,
|
|
6398
6841
|
help,
|
|
6842
|
+
identityFileKeptLine,
|
|
6399
6843
|
maintenanceExitCode,
|
|
6844
|
+
projectDeletedLine,
|
|
6845
|
+
projectDeletionWarning,
|
|
6400
6846
|
removeFolderPrompt,
|
|
6401
6847
|
removedFolderLine,
|
|
6402
|
-
runCli
|
|
6848
|
+
runCli,
|
|
6849
|
+
stillWatchedLine
|
|
6403
6850
|
};
|