@mnemonik/cli 7.109.3 → 7.111.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/credentials.js +297 -36
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1914 -19
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/machineName.d.ts +8 -0
- package/dist/auth/machineName.d.ts.map +1 -0
- package/dist/auth/machineName.js +23 -0
- package/dist/auth/machineName.js.map +1 -0
- package/dist/consent.d.ts +29 -0
- package/dist/consent.d.ts.map +1 -0
- package/dist/consent.js +87 -0
- package/dist/consent.js.map +1 -0
- package/dist/diagnostics.js +301 -40
- package/dist/digests.json +102 -90
- package/dist/help.d.ts.map +1 -1
- package/dist/help.js +59 -44
- package/dist/help.js.map +1 -1
- package/dist/humanReason.d.ts +8 -0
- package/dist/humanReason.d.ts.map +1 -1
- package/dist/humanReason.js +44 -16
- package/dist/humanReason.js.map +1 -1
- package/dist/identity/migrate.js +1835 -44
- package/dist/install/hosts.d.ts +2 -0
- package/dist/install/hosts.d.ts.map +1 -1
- package/dist/install/hosts.js +23 -14
- package/dist/install/hosts.js.map +1 -1
- package/dist/install/journal.js +124 -11
- package/dist/install/journey.d.ts +20 -0
- package/dist/install/journey.d.ts.map +1 -1
- package/dist/install/journey.js +1913 -82
- package/dist/install/journey.js.map +1 -1
- package/dist/install/ownership.d.ts.map +1 -1
- package/dist/install/ownership.js +1818 -10
- package/dist/install/ownership.js.map +1 -1
- package/dist/install/transaction.js +1913 -19
- package/dist/install/ui.js +1910 -15
- package/dist/installation.js +133 -10
- package/dist/launcher.js +108 -4
- package/dist/output.d.ts +3 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +11 -1
- package/dist/output.js.map +1 -1
- package/dist/preflight.d.ts +5 -0
- package/dist/preflight.d.ts.map +1 -1
- package/dist/preflight.js +14 -12
- package/dist/preflight.js.map +1 -1
- package/dist/project/eligibility.js +1917 -22
- package/dist/project/records.js +121 -8
- package/dist/project.d.ts +15 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +229 -15
- package/dist/project.js.map +1 -1
- package/dist/router.d.ts +2 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +2164 -122
- package/dist/router.js.map +1 -1
- package/dist/runtime/releaseSource.d.ts +6 -0
- package/dist/runtime/releaseSource.d.ts.map +1 -1
- package/dist/runtime/releaseSource.js +1933 -32
- package/dist/runtime/releaseSource.js.map +1 -1
- package/dist/runtime/selfUpdate.js +1809 -8
- package/dist/runtime/signers.js +28 -9
- package/dist/runtime/store.js +18 -6
- package/dist/runtime/updateCheck.d.ts +4 -0
- package/dist/runtime/updateCheck.d.ts.map +1 -0
- package/dist/runtime/updateCheck.js +6695 -0
- package/dist/runtime/updateCheck.js.map +1 -0
- package/dist/sbom.json +21 -21
- package/dist/scanner/control.d.ts +27 -1
- package/dist/scanner/control.d.ts.map +1 -1
- package/dist/scanner/control.js +207 -36
- package/dist/scanner/control.js.map +1 -1
- package/dist/scanner/discover.d.ts +5 -0
- package/dist/scanner/discover.d.ts.map +1 -1
- package/dist/scanner/discover.js +16 -6
- package/dist/scanner/discover.js.map +1 -1
- package/dist/scanner/enable.d.ts +2 -0
- package/dist/scanner/enable.d.ts.map +1 -1
- package/dist/scanner/enable.js +152 -14
- package/dist/scanner/enable.js.map +1 -1
- package/dist/scanner/picker.d.ts.map +1 -1
- package/dist/scanner/picker.js +5 -6
- package/dist/scanner/picker.js.map +1 -1
- package/dist/scanner/service.d.ts +2 -0
- package/dist/scanner/service.d.ts.map +1 -1
- package/dist/scanner/service.js +279 -54
- package/dist/scanner/service.js.map +1 -1
- package/dist/scanner/update.d.ts +8 -0
- package/dist/scanner/update.d.ts.map +1 -1
- package/dist/scanner/update.js +254 -20
- package/dist/scanner/update.js.map +1 -1
- package/dist/scanner-release.json +35 -30
- package/dist/screens/journey.d.ts +6 -1
- package/dist/screens/journey.d.ts.map +1 -1
- package/dist/screens/journey.js +29 -8
- package/dist/screens/journey.js.map +1 -1
- package/dist/status.d.ts +21 -0
- package/dist/status.d.ts.map +1 -1
- package/dist/status.js +1993 -39
- package/dist/status.js.map +1 -1
- package/dist/vendor/local-setup.js +256 -29
- package/dist/vendor/shared/runtimeSigners.js +38 -11
- package/package.json +31 -31
package/dist/project/records.js
CHANGED
|
@@ -516,8 +516,25 @@ function readIdentity(stdout) {
|
|
|
516
516
|
throw new Error("acl_identity_unavailable");
|
|
517
517
|
return { name: match[1], sid: match[2] };
|
|
518
518
|
}
|
|
519
|
+
function* readWindowsIdentity() {
|
|
520
|
+
const user = readIdentity(yield [windowsCommand("whoami.exe"), identityArgs]);
|
|
521
|
+
if (!ADMINISTRATOR_RID.test(user.sid))
|
|
522
|
+
return user;
|
|
523
|
+
const groups = yield [windowsCommand("whoami.exe"), groupArgs];
|
|
524
|
+
const local = /^"[^"\r\n]*","[^"\r\n]*","S-1-5-113",/m.test(groups);
|
|
525
|
+
return {
|
|
526
|
+
...user,
|
|
527
|
+
localAdministratorSid: local ? `${user.sid.slice(0, user.sid.lastIndexOf("-"))}-500` : null
|
|
528
|
+
};
|
|
529
|
+
}
|
|
519
530
|
function windowsCurrentAccountSync() {
|
|
520
|
-
|
|
531
|
+
if (currentIdentity)
|
|
532
|
+
return currentIdentity;
|
|
533
|
+
const commands = readWindowsIdentity();
|
|
534
|
+
let step = commands.next();
|
|
535
|
+
while (!step.done)
|
|
536
|
+
step = commands.next(hookExecuteSync(...step.value));
|
|
537
|
+
return currentIdentity = step.value;
|
|
521
538
|
}
|
|
522
539
|
function hookInvocation(file, args2) {
|
|
523
540
|
if (win32.basename(file) === "whoami.exe") {
|
|
@@ -537,11 +554,13 @@ function hookExecuteSync(file, args2, input) {
|
|
|
537
554
|
[file, args2] = hookInvocation(file, args2);
|
|
538
555
|
return execFileSync(file, args2, { ...hookOptions(file, args2), input });
|
|
539
556
|
}
|
|
540
|
-
var identityArgs, currentIdentity, ttl, hookOptions;
|
|
557
|
+
var identityArgs, groupArgs, ADMINISTRATOR_RID, currentIdentity, ttl, hookOptions;
|
|
541
558
|
var init_runtimeSigners = __esm({
|
|
542
559
|
"packages/shared/dist/runtimeSigners.js"() {
|
|
543
560
|
"use strict";
|
|
544
561
|
identityArgs = ["/user", "/fo", "csv", "/nh"];
|
|
562
|
+
groupArgs = ["/groups", "/fo", "csv", "/nh"];
|
|
563
|
+
ADMINISTRATOR_RID = /^S-1-5-21-\d+-\d+-\d+-500$/;
|
|
545
564
|
ttl = 10 * 6e4;
|
|
546
565
|
hookOptions = (file, args2) => ({
|
|
547
566
|
encoding: args2.includes("/u") ? "utf16le" : "utf8",
|
|
@@ -2199,7 +2218,7 @@ var require_proper_lockfile = __commonJS({
|
|
|
2199
2218
|
// packages/cli/src/project/records.ts
|
|
2200
2219
|
import { createHash as createHash2, randomUUID as randomUUID2 } from "node:crypto";
|
|
2201
2220
|
import { readFile as readFile2, readdir, unlink as unlink2 } from "node:fs/promises";
|
|
2202
|
-
import { join as
|
|
2221
|
+
import { join as join5 } from "node:path";
|
|
2203
2222
|
|
|
2204
2223
|
// packages/shared/dist/instructions.js
|
|
2205
2224
|
var INSTRUCTIONS_CONTENT = `Mnemonik provides persistent project memory: decisions, rationale, tasks, and policies across sessions. If no block begins "PROJECT_CONTEXT schemaVersion=", session_bootstrap({ cwd }) loads project context when cwd is the real absolute path of the project root; a placeholder or relative path fails. With that block, context is loaded and no session_bootstrap call is needed. Code and docs show current artifacts, git shows changes, and memory carries the why; memory_search recalls rationale or intent, then Grep or Read verifies current source.
|
|
@@ -6555,6 +6574,100 @@ async function withLock(path, waitMs, work) {
|
|
|
6555
6574
|
}
|
|
6556
6575
|
}
|
|
6557
6576
|
|
|
6577
|
+
// packages/local-setup/dist/automaticUpdate.js
|
|
6578
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
6579
|
+
import { realpathSync } from "node:fs";
|
|
6580
|
+
import { stat as nodeStat, utimes } from "node:fs/promises";
|
|
6581
|
+
import { homedir as homedir2 } from "node:os";
|
|
6582
|
+
import { join as join4 } from "node:path";
|
|
6583
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
6584
|
+
var DAY_MS = 864e5;
|
|
6585
|
+
var statePath = (stateDir) => join4(stateDir, "automatic-update.json");
|
|
6586
|
+
function cliLauncherPath(options = {}) {
|
|
6587
|
+
const platform = options.platform ?? process.platform;
|
|
6588
|
+
const home = options.home ?? homedir2();
|
|
6589
|
+
return platform === "win32" ? join4(options.env?.LOCALAPPDATA || join4(home, "AppData", "Local"), "Mnemonik", "bin", "mnemonik.cmd") : join4(home, ".local", "bin", "mnemonik");
|
|
6590
|
+
}
|
|
6591
|
+
async function readState(path) {
|
|
6592
|
+
const bytes = await readBytes(path);
|
|
6593
|
+
if (!bytes)
|
|
6594
|
+
return {};
|
|
6595
|
+
const value = JSON.parse(bytes.toString());
|
|
6596
|
+
if (!value || typeof value !== "object" || value.lastAttempt !== void 0 && (!Number.isFinite(value.lastAttempt) || value.lastAttempt < 0))
|
|
6597
|
+
throw new Error("automatic_update_state_invalid");
|
|
6598
|
+
return value.lastAttempt === void 0 ? {} : { lastAttempt: value.lastAttempt };
|
|
6599
|
+
}
|
|
6600
|
+
async function maybeStartAutomaticUpdate(options = {}) {
|
|
6601
|
+
const stateDir = options.stateDir ?? stateDirectory(options.platform, options.env, options.home);
|
|
6602
|
+
const path = statePath(stateDir);
|
|
6603
|
+
try {
|
|
6604
|
+
const now = (options.now ?? Date.now)();
|
|
6605
|
+
const stat = options.stat ?? nodeStat;
|
|
6606
|
+
try {
|
|
6607
|
+
if (now - (await stat(path)).mtimeMs < DAY_MS)
|
|
6608
|
+
return false;
|
|
6609
|
+
} catch (error) {
|
|
6610
|
+
if (error.code !== "ENOENT")
|
|
6611
|
+
throw error;
|
|
6612
|
+
}
|
|
6613
|
+
if (!options.spawn && !(await stat(cliLauncherPath(options))).isFile())
|
|
6614
|
+
return false;
|
|
6615
|
+
return await withLock(path, 0, async (assertOwned) => {
|
|
6616
|
+
const state = await readState(path);
|
|
6617
|
+
if (state.lastAttempt !== void 0 && now - state.lastAttempt < DAY_MS)
|
|
6618
|
+
return false;
|
|
6619
|
+
await atomicWrite(path, Buffer.from(`${JSON.stringify({ lastAttempt: now })}
|
|
6620
|
+
`), void 0, assertOwned);
|
|
6621
|
+
await utimes(path, now / 1e3, now / 1e3);
|
|
6622
|
+
const platform = options.platform ?? process.platform;
|
|
6623
|
+
const launcher = cliLauncherPath(options);
|
|
6624
|
+
const command = platform === "win32" ? {
|
|
6625
|
+
file: options.env?.ComSpec || "cmd.exe",
|
|
6626
|
+
args: ["/d", "/s", "/c", `""${launcher}" update --automatic"`],
|
|
6627
|
+
windowsVerbatimArguments: true
|
|
6628
|
+
} : platform === "linux" && (options.env ?? process.env).INVOCATION_ID ? {
|
|
6629
|
+
// detached creates a process group, not a new systemd cgroup. An
|
|
6630
|
+
// updater spawned by the scanner must survive stopping that service.
|
|
6631
|
+
file: "systemd-run",
|
|
6632
|
+
args: [
|
|
6633
|
+
"--user",
|
|
6634
|
+
"--collect",
|
|
6635
|
+
"--quiet",
|
|
6636
|
+
`--setenv=MNEMONIK_STATE_DIR=${stateDir}`,
|
|
6637
|
+
"--",
|
|
6638
|
+
launcher,
|
|
6639
|
+
"update",
|
|
6640
|
+
"--automatic"
|
|
6641
|
+
]
|
|
6642
|
+
} : { file: launcher, args: ["update", "--automatic"] };
|
|
6643
|
+
const child = (options.spawn ?? nodeSpawn)(command.file, command.args, {
|
|
6644
|
+
detached: true,
|
|
6645
|
+
stdio: "ignore",
|
|
6646
|
+
windowsHide: true,
|
|
6647
|
+
..."windowsVerbatimArguments" in command ? { windowsVerbatimArguments: command.windowsVerbatimArguments } : {}
|
|
6648
|
+
});
|
|
6649
|
+
child.once("error", () => {
|
|
6650
|
+
});
|
|
6651
|
+
child.unref();
|
|
6652
|
+
return true;
|
|
6653
|
+
});
|
|
6654
|
+
} catch {
|
|
6655
|
+
return false;
|
|
6656
|
+
}
|
|
6657
|
+
}
|
|
6658
|
+
var HELPER_FLAG = "--mnemonik-automatic-update";
|
|
6659
|
+
function isHelperInvocation() {
|
|
6660
|
+
if (process.argv[2] !== HELPER_FLAG || !process.argv[3] || !process.argv[1])
|
|
6661
|
+
return false;
|
|
6662
|
+
try {
|
|
6663
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath2(import.meta.url));
|
|
6664
|
+
} catch {
|
|
6665
|
+
return false;
|
|
6666
|
+
}
|
|
6667
|
+
}
|
|
6668
|
+
if (isHelperInvocation())
|
|
6669
|
+
void maybeStartAutomaticUpdate({ stateDir: process.argv[3] });
|
|
6670
|
+
|
|
6558
6671
|
// packages/local-setup/dist/index.js
|
|
6559
6672
|
var MAX_ORIGINAL_BYTES = 64 * 1024;
|
|
6560
6673
|
|
|
@@ -6562,7 +6675,7 @@ var MAX_ORIGINAL_BYTES = 64 * 1024;
|
|
|
6562
6675
|
var digest = (bytes) => `sha256:${createHash2("sha256").update(bytes).digest("hex")}`;
|
|
6563
6676
|
async function identityHash(root) {
|
|
6564
6677
|
try {
|
|
6565
|
-
return digest(await readFile2(
|
|
6678
|
+
return digest(await readFile2(join5(root, ".mnemonik.json")));
|
|
6566
6679
|
} catch (error) {
|
|
6567
6680
|
if (error.code === "ENOENT") return null;
|
|
6568
6681
|
throw error;
|
|
@@ -6570,14 +6683,14 @@ async function identityHash(root) {
|
|
|
6570
6683
|
}
|
|
6571
6684
|
var ownerLabel = (owner) => !owner || owner === "personal" ? "personal" : `team:${owner.teamId}`;
|
|
6572
6685
|
async function saveCommandRecord(record, stateDir = stateDirectory()) {
|
|
6573
|
-
const directory =
|
|
6686
|
+
const directory = join5(
|
|
6574
6687
|
stateDir,
|
|
6575
6688
|
"project-commands",
|
|
6576
6689
|
createHash2("sha256").update(record.resolvedRoot).digest("hex")
|
|
6577
6690
|
);
|
|
6578
|
-
const lock =
|
|
6691
|
+
const lock = join5(directory, ".records");
|
|
6579
6692
|
await withLock(lock, 6e4, async (assertOwned) => {
|
|
6580
|
-
const file =
|
|
6693
|
+
const file = join5(directory, `${Date.now().toString().padStart(16, "0")}-${randomUUID2()}.json`);
|
|
6581
6694
|
await atomicWrite(
|
|
6582
6695
|
file,
|
|
6583
6696
|
Buffer.from(`${JSON.stringify(record, null, 2)}
|
|
@@ -6588,7 +6701,7 @@ async function saveCommandRecord(record, stateDir = stateDirectory()) {
|
|
|
6588
6701
|
const files = (await readdir(directory)).filter((name2) => name2.endsWith(".json")).sort();
|
|
6589
6702
|
for (const stale of files.slice(0, -20)) {
|
|
6590
6703
|
await assertOwned();
|
|
6591
|
-
await unlink2(
|
|
6704
|
+
await unlink2(join5(directory, stale));
|
|
6592
6705
|
}
|
|
6593
6706
|
});
|
|
6594
6707
|
}
|
package/dist/project.d.ts
CHANGED
|
@@ -10,6 +10,19 @@ export interface ProjectExecutor {
|
|
|
10
10
|
apply(options: EnsureOptions): Promise<SetupResult>;
|
|
11
11
|
rollback(options: EnsureOptions): Promise<SetupResult>;
|
|
12
12
|
}
|
|
13
|
+
/**
|
|
14
|
+
* The command that gives each offered answer, for an agent that reads JSON.
|
|
15
|
+
* An action no command can give is left out.
|
|
16
|
+
*/
|
|
17
|
+
export declare function answerCommands(actions: readonly string[], root: string, details?: {
|
|
18
|
+
candidates?: Array<{
|
|
19
|
+
projectId: string;
|
|
20
|
+
}>;
|
|
21
|
+
projectId?: string;
|
|
22
|
+
}): Array<{
|
|
23
|
+
action: string;
|
|
24
|
+
command: string;
|
|
25
|
+
}>;
|
|
13
26
|
export declare function ensureProjectRoot(root: string, executor: ProjectExecutor): Promise<SetupResult>;
|
|
14
27
|
/** Does Mnemonik have plain words for this state? */
|
|
15
28
|
export declare const hasRefusalWords: (reason: string) => boolean;
|
|
@@ -118,6 +131,8 @@ export interface ProjectCommandInput {
|
|
|
118
131
|
apply: boolean;
|
|
119
132
|
confirmMismatch: boolean;
|
|
120
133
|
replace: boolean;
|
|
134
|
+
/** Answer a waiting setup with cancel: clear the folder's setup notes. */
|
|
135
|
+
cancel?: boolean;
|
|
121
136
|
owner?: string;
|
|
122
137
|
}
|
|
123
138
|
export declare function runProjectCommand(input: ProjectCommandInput, deps: ProjectCommandDependencies): Promise<number>;
|
package/dist/project.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACrE,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,aAAa,EAClB,KAAK,KAAK,EACV,KAAK,WAAW,EACjB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,sBAAsB,EAEtB,KAAK,yBAAyB,EAC9B,KAAK,qBAAqB,EAE3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAiB1C,MAAM,WAAW,eAAe;IAC9B,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAAC;IACxE,aAAa,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5D,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACpD,KAAK,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACpD,QAAQ,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CACxD;AAMD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE;IAAE,UAAU,CAAC,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAC9E,KAAK,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAoB5C;AAED,wBAAsB,iBAAiB,CACrC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,eAAe,GACxB,OAAO,CAAC,WAAW,CAAC,CAEtB;AAyED,qDAAqD;AACrD,eAAO,MAAM,eAAe,WAAY,MAAM,KAAG,OAAmC,CAAC;AAErF,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAM3E;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAChC,MAAM,EAAE,GAAG,SAAS,CActB;AAED,eAAO,MAAM,wBAAwB,UAAW,MAAM,EAAE,KAAG,MAGL,CAAC;AAEvD,eAAO,MAAM,eAAe,iBAAkB,oBAAoB,KAAG,eAOpE,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC5B,QAAQ,GAAG,UAAU,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;AAE7E,MAAM,WAAW,oBAAoB;IACnC,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC;IAC5D,gBAAgB,CACd,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,gBAAgB,CAAC,EAAE,qBAAqB,GAAG,IAAI,GAC9C,OAAO,CAAC;QAAE,KAAK,EAAE,kBAAkB,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,yBAAyB;IACxC,kEAAkE;IAClE,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC;IACzD,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,CAAC;CACvC;AAmBD,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CA8B/F;AAED,wBAAsB,wBAAwB,CAAC,OAAO,GAAE,yBAA8B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsErF;AAED,MAAM,WAAW,0BAA0B;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,QAAQ,CAAC,EAAE;QAAE,sBAAsB,EAAE,OAAO,sBAAsB,CAAA;KAAE,CAAC;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACjD,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC9C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,eAAe,EAAE,OAAO,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAseD,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,mBAAmB,EAC1B,IAAI,EAAE,0BAA0B,GAC/B,OAAO,CAAC,MAAM,CAAC,CAuCjB;AAoCD,wBAAsB,qBAAqB,CAAC,OAAO,EAAE;IACnD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,uEAAuE;IACvE,OAAO,CAAC,EAAE,IAAI,CAAC,yBAAyB,EAAE,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC,CAAC;IACjF,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,MAAM,CAAC,CA2ClB;AAED,wBAAsB,uBAAuB,CAAC,OAAO,EAAE;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B,GAAG,OAAO,CAAC,MAAM,CAAC,CASlB"}
|
package/dist/project.js
CHANGED
|
@@ -516,8 +516,25 @@ function readIdentity(stdout) {
|
|
|
516
516
|
throw new Error("acl_identity_unavailable");
|
|
517
517
|
return { name: match[1], sid: match[2] };
|
|
518
518
|
}
|
|
519
|
+
function* readWindowsIdentity() {
|
|
520
|
+
const user = readIdentity(yield [windowsCommand("whoami.exe"), identityArgs]);
|
|
521
|
+
if (!ADMINISTRATOR_RID.test(user.sid))
|
|
522
|
+
return user;
|
|
523
|
+
const groups = yield [windowsCommand("whoami.exe"), groupArgs];
|
|
524
|
+
const local = /^"[^"\r\n]*","[^"\r\n]*","S-1-5-113",/m.test(groups);
|
|
525
|
+
return {
|
|
526
|
+
...user,
|
|
527
|
+
localAdministratorSid: local ? `${user.sid.slice(0, user.sid.lastIndexOf("-"))}-500` : null
|
|
528
|
+
};
|
|
529
|
+
}
|
|
519
530
|
function windowsCurrentAccountSync() {
|
|
520
|
-
|
|
531
|
+
if (currentIdentity)
|
|
532
|
+
return currentIdentity;
|
|
533
|
+
const commands = readWindowsIdentity();
|
|
534
|
+
let step2 = commands.next();
|
|
535
|
+
while (!step2.done)
|
|
536
|
+
step2 = commands.next(hookExecuteSync(...step2.value));
|
|
537
|
+
return currentIdentity = step2.value;
|
|
521
538
|
}
|
|
522
539
|
function hookInvocation(file, args2) {
|
|
523
540
|
if (win32.basename(file) === "whoami.exe") {
|
|
@@ -537,11 +554,13 @@ function hookExecuteSync(file, args2, input) {
|
|
|
537
554
|
[file, args2] = hookInvocation(file, args2);
|
|
538
555
|
return execFileSync(file, args2, { ...hookOptions(file, args2), input });
|
|
539
556
|
}
|
|
540
|
-
var identityArgs, currentIdentity, ttl, hookOptions;
|
|
557
|
+
var identityArgs, groupArgs, ADMINISTRATOR_RID, currentIdentity, ttl, hookOptions;
|
|
541
558
|
var init_runtimeSigners = __esm({
|
|
542
559
|
"packages/shared/dist/runtimeSigners.js"() {
|
|
543
560
|
"use strict";
|
|
544
561
|
identityArgs = ["/user", "/fo", "csv", "/nh"];
|
|
562
|
+
groupArgs = ["/groups", "/fo", "csv", "/nh"];
|
|
563
|
+
ADMINISTRATOR_RID = /^S-1-5-21-\d+-\d+-\d+-500$/;
|
|
545
564
|
ttl = 10 * 6e4;
|
|
546
565
|
hookOptions = (file, args2) => ({
|
|
547
566
|
encoding: args2.includes("/u") ? "utf16le" : "utf8",
|
|
@@ -2636,7 +2655,7 @@ import { createCliCredentials } from "./auth/credentials.js";
|
|
|
2636
2655
|
import { createInterface } from "node:readline";
|
|
2637
2656
|
import { execFile as execFile3 } from "node:child_process";
|
|
2638
2657
|
import { lstat as lstat4 } from "node:fs/promises";
|
|
2639
|
-
import { basename as basename3, join as
|
|
2658
|
+
import { basename as basename3, join as join8 } from "node:path";
|
|
2640
2659
|
|
|
2641
2660
|
// packages/local-setup/dist/index.js
|
|
2642
2661
|
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
@@ -6833,7 +6852,7 @@ init_repositoryRoot();
|
|
|
6833
6852
|
|
|
6834
6853
|
// packages/local-setup/dist/index.js
|
|
6835
6854
|
import { realpath, unlink as unlink2 } from "node:fs/promises";
|
|
6836
|
-
import { basename as basename2, dirname as dirname5, join as
|
|
6855
|
+
import { basename as basename2, dirname as dirname5, join as join7 } from "node:path";
|
|
6837
6856
|
|
|
6838
6857
|
// packages/local-setup/dist/contracts.js
|
|
6839
6858
|
var actionRequired = (state) => ({
|
|
@@ -7006,6 +7025,100 @@ async function withLock(path, waitMs, work) {
|
|
|
7006
7025
|
}
|
|
7007
7026
|
}
|
|
7008
7027
|
|
|
7028
|
+
// packages/local-setup/dist/automaticUpdate.js
|
|
7029
|
+
import { spawn as nodeSpawn } from "node:child_process";
|
|
7030
|
+
import { realpathSync } from "node:fs";
|
|
7031
|
+
import { stat as nodeStat, utimes } from "node:fs/promises";
|
|
7032
|
+
import { homedir as homedir3 } from "node:os";
|
|
7033
|
+
import { join as join6 } from "node:path";
|
|
7034
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
7035
|
+
var DAY_MS = 864e5;
|
|
7036
|
+
var statePath = (stateDir) => join6(stateDir, "automatic-update.json");
|
|
7037
|
+
function cliLauncherPath(options = {}) {
|
|
7038
|
+
const platform = options.platform ?? process.platform;
|
|
7039
|
+
const home = options.home ?? homedir3();
|
|
7040
|
+
return platform === "win32" ? join6(options.env?.LOCALAPPDATA || join6(home, "AppData", "Local"), "Mnemonik", "bin", "mnemonik.cmd") : join6(home, ".local", "bin", "mnemonik");
|
|
7041
|
+
}
|
|
7042
|
+
async function readState(path) {
|
|
7043
|
+
const bytes = await readBytes(path);
|
|
7044
|
+
if (!bytes)
|
|
7045
|
+
return {};
|
|
7046
|
+
const value = JSON.parse(bytes.toString());
|
|
7047
|
+
if (!value || typeof value !== "object" || value.lastAttempt !== void 0 && (!Number.isFinite(value.lastAttempt) || value.lastAttempt < 0))
|
|
7048
|
+
throw new Error("automatic_update_state_invalid");
|
|
7049
|
+
return value.lastAttempt === void 0 ? {} : { lastAttempt: value.lastAttempt };
|
|
7050
|
+
}
|
|
7051
|
+
async function maybeStartAutomaticUpdate(options = {}) {
|
|
7052
|
+
const stateDir = options.stateDir ?? stateDirectory(options.platform, options.env, options.home);
|
|
7053
|
+
const path = statePath(stateDir);
|
|
7054
|
+
try {
|
|
7055
|
+
const now = (options.now ?? Date.now)();
|
|
7056
|
+
const stat = options.stat ?? nodeStat;
|
|
7057
|
+
try {
|
|
7058
|
+
if (now - (await stat(path)).mtimeMs < DAY_MS)
|
|
7059
|
+
return false;
|
|
7060
|
+
} catch (error) {
|
|
7061
|
+
if (error.code !== "ENOENT")
|
|
7062
|
+
throw error;
|
|
7063
|
+
}
|
|
7064
|
+
if (!options.spawn && !(await stat(cliLauncherPath(options))).isFile())
|
|
7065
|
+
return false;
|
|
7066
|
+
return await withLock(path, 0, async (assertOwned) => {
|
|
7067
|
+
const state = await readState(path);
|
|
7068
|
+
if (state.lastAttempt !== void 0 && now - state.lastAttempt < DAY_MS)
|
|
7069
|
+
return false;
|
|
7070
|
+
await atomicWrite(path, Buffer.from(`${JSON.stringify({ lastAttempt: now })}
|
|
7071
|
+
`), void 0, assertOwned);
|
|
7072
|
+
await utimes(path, now / 1e3, now / 1e3);
|
|
7073
|
+
const platform = options.platform ?? process.platform;
|
|
7074
|
+
const launcher = cliLauncherPath(options);
|
|
7075
|
+
const command = platform === "win32" ? {
|
|
7076
|
+
file: options.env?.ComSpec || "cmd.exe",
|
|
7077
|
+
args: ["/d", "/s", "/c", `""${launcher}" update --automatic"`],
|
|
7078
|
+
windowsVerbatimArguments: true
|
|
7079
|
+
} : platform === "linux" && (options.env ?? process.env).INVOCATION_ID ? {
|
|
7080
|
+
// detached creates a process group, not a new systemd cgroup. An
|
|
7081
|
+
// updater spawned by the scanner must survive stopping that service.
|
|
7082
|
+
file: "systemd-run",
|
|
7083
|
+
args: [
|
|
7084
|
+
"--user",
|
|
7085
|
+
"--collect",
|
|
7086
|
+
"--quiet",
|
|
7087
|
+
`--setenv=MNEMONIK_STATE_DIR=${stateDir}`,
|
|
7088
|
+
"--",
|
|
7089
|
+
launcher,
|
|
7090
|
+
"update",
|
|
7091
|
+
"--automatic"
|
|
7092
|
+
]
|
|
7093
|
+
} : { file: launcher, args: ["update", "--automatic"] };
|
|
7094
|
+
const child = (options.spawn ?? nodeSpawn)(command.file, command.args, {
|
|
7095
|
+
detached: true,
|
|
7096
|
+
stdio: "ignore",
|
|
7097
|
+
windowsHide: true,
|
|
7098
|
+
..."windowsVerbatimArguments" in command ? { windowsVerbatimArguments: command.windowsVerbatimArguments } : {}
|
|
7099
|
+
});
|
|
7100
|
+
child.once("error", () => {
|
|
7101
|
+
});
|
|
7102
|
+
child.unref();
|
|
7103
|
+
return true;
|
|
7104
|
+
});
|
|
7105
|
+
} catch {
|
|
7106
|
+
return false;
|
|
7107
|
+
}
|
|
7108
|
+
}
|
|
7109
|
+
var HELPER_FLAG = "--mnemonik-automatic-update";
|
|
7110
|
+
function isHelperInvocation() {
|
|
7111
|
+
if (process.argv[2] !== HELPER_FLAG || !process.argv[3] || !process.argv[1])
|
|
7112
|
+
return false;
|
|
7113
|
+
try {
|
|
7114
|
+
return realpathSync(process.argv[1]) === realpathSync(fileURLToPath2(import.meta.url));
|
|
7115
|
+
} catch {
|
|
7116
|
+
return false;
|
|
7117
|
+
}
|
|
7118
|
+
}
|
|
7119
|
+
if (isHelperInvocation())
|
|
7120
|
+
void maybeStartAutomaticUpdate({ stateDir: process.argv[3] });
|
|
7121
|
+
|
|
7009
7122
|
// packages/local-setup/dist/index.js
|
|
7010
7123
|
var MAX_ORIGINAL_BYTES = 64 * 1024;
|
|
7011
7124
|
var validDisplayName = (value) => typeof value === "string" && value.length <= 200 && !/[\p{C}\p{Zl}\p{Zp}@]/u.test(value);
|
|
@@ -7016,6 +7129,7 @@ var accessResponseHash = (response) => hash2(JSON.stringify({
|
|
|
7016
7129
|
allowedActions: [...response.allowedActions].sort(),
|
|
7017
7130
|
candidates: response.candidates
|
|
7018
7131
|
}));
|
|
7132
|
+
var pristine = (record, diskHash) => !record.remote && !record.staged && !record.steps.remote.started && !record.steps.identity.started && !record.steps.rollback.started && diskHash === record.before.hash;
|
|
7019
7133
|
var step = (beforeHash) => ({
|
|
7020
7134
|
complete: false,
|
|
7021
7135
|
beforeHash,
|
|
@@ -7046,7 +7160,7 @@ function createProjectSetupExecutor(deps) {
|
|
|
7046
7160
|
if (await realpath(fresh.root) !== root)
|
|
7047
7161
|
return actionRequired("identity_changed");
|
|
7048
7162
|
resolution = fresh;
|
|
7049
|
-
const file =
|
|
7163
|
+
const file = join7(root, ".mnemonik.json");
|
|
7050
7164
|
const bytes = await readBytes(file);
|
|
7051
7165
|
const diskHash = digest(bytes);
|
|
7052
7166
|
const saved = await readBytes(path);
|
|
@@ -7075,14 +7189,13 @@ function createProjectSetupExecutor(deps) {
|
|
|
7075
7189
|
return actionRequired("record_invalid");
|
|
7076
7190
|
if (record.before.base64 !== null && record.before.hash !== hash2(Buffer.from(record.before.base64, "base64")) || record.before.base64 !== null && Buffer.from(record.before.base64, "base64").length > MAX_ORIGINAL_BYTES || record.staged && hash2(record.staged.content) !== record.staged.hash || record.remote && hash2(JSON.stringify(record.remote)) !== record.steps.remote.afterHash)
|
|
7077
7191
|
return actionRequired("record_invalid");
|
|
7078
|
-
if (mode === "stage" &&
|
|
7192
|
+
if (mode === "stage" && (record.steps.identity.complete && !record.steps.rollback.started && resolution.kind === "ok" && resolution.identity.projectId === record.remote?.projectId && (!options.intent || options.intent.projectId === record.remote.projectId) || record.steps.rollback.complete && diskHash === record.before.hash)) {
|
|
7079
7193
|
record = freshRecord();
|
|
7080
7194
|
recordIsNew = true;
|
|
7081
7195
|
}
|
|
7082
7196
|
const settled = record.steps.identity.complete && !record.steps.rollback.started && resolution.kind === "ok" && resolution.identity.projectId === record.remote?.projectId && (!options.intent || options.intent.projectId === record.remote?.projectId);
|
|
7083
7197
|
if (record.scopeKey !== hash2(deps.scopeKey) || options.owner !== void 0 && JSON.stringify(record.owner) !== JSON.stringify(options.owner) || !settled && JSON.stringify(record.intent) !== JSON.stringify(options.intent)) {
|
|
7084
|
-
|
|
7085
|
-
if (replaceable) {
|
|
7198
|
+
if (pristine(record, diskHash)) {
|
|
7086
7199
|
record = freshRecord();
|
|
7087
7200
|
recordIsNew = true;
|
|
7088
7201
|
} else {
|
|
@@ -7179,10 +7292,15 @@ function createProjectSetupExecutor(deps) {
|
|
|
7179
7292
|
}
|
|
7180
7293
|
if (!resumingWithoutIdentity && record.steps.identity.complete && diskHash !== record.staged?.hash)
|
|
7181
7294
|
return actionRequired("identity_changed");
|
|
7295
|
+
if (record.evidence && JSON.stringify(record.evidence) !== JSON.stringify(evidence)) {
|
|
7296
|
+
if (!pristine(record, diskHash))
|
|
7297
|
+
return actionRequired("operation_context_changed");
|
|
7298
|
+
const ignored = record.ignored;
|
|
7299
|
+
record = { ...freshRecord(), ...ignored ? { ignored } : {} };
|
|
7300
|
+
recordIsNew = true;
|
|
7301
|
+
}
|
|
7182
7302
|
if (recordIsNew)
|
|
7183
7303
|
await save();
|
|
7184
|
-
if (record.evidence && JSON.stringify(record.evidence) !== JSON.stringify(evidence))
|
|
7185
|
-
return actionRequired("operation_context_changed");
|
|
7186
7304
|
if (record.steps.identity.complete && mode === "ensure" && record.remote) {
|
|
7187
7305
|
const validated = await deps.transport.issueSetupRequest({
|
|
7188
7306
|
...evidence,
|
|
@@ -7288,9 +7406,59 @@ function createProjectSetupExecutor(deps) {
|
|
|
7288
7406
|
ensureProject: (options) => execute(options, "ensure"),
|
|
7289
7407
|
stage: (options) => execute(options, "stage"),
|
|
7290
7408
|
apply: (options) => execute(options, "apply"),
|
|
7291
|
-
rollback: (options) => execute(options, "rollback")
|
|
7409
|
+
rollback: (options) => execute(options, "rollback"),
|
|
7410
|
+
cancel: async (options) => {
|
|
7411
|
+
const resolution = await deps.resolver.resolveProjectIdentity(options.cwd, options);
|
|
7412
|
+
return cancelProjectSetup("root" in resolution ? resolution.root : options.cwd, deps.stateDir, deps.waitMs);
|
|
7413
|
+
}
|
|
7292
7414
|
};
|
|
7293
7415
|
}
|
|
7416
|
+
async function cancelProjectSetup(folder, stateDir, waitMs = 6e4) {
|
|
7417
|
+
const root = await realpath(folder);
|
|
7418
|
+
const path = recordPath(root, stateDir);
|
|
7419
|
+
return withLock(path, waitMs, async (assertOwned) => {
|
|
7420
|
+
const saved = await readBytes(path);
|
|
7421
|
+
if (!saved)
|
|
7422
|
+
return { status: "cancelled", root, cleared: false, restored: false };
|
|
7423
|
+
let record = null;
|
|
7424
|
+
try {
|
|
7425
|
+
record = JSON.parse(saved.toString());
|
|
7426
|
+
} catch {
|
|
7427
|
+
}
|
|
7428
|
+
let restored = false;
|
|
7429
|
+
const staged = record?.staged;
|
|
7430
|
+
const before = record?.before;
|
|
7431
|
+
const settled = !!record?.steps?.identity?.complete && !record.steps.rollback?.started;
|
|
7432
|
+
if (!settled && staged && before && typeof staged.hash === "string" && staged.hash !== before.hash) {
|
|
7433
|
+
const file = join7(root, ".mnemonik.json");
|
|
7434
|
+
const earlier = typeof before.base64 === "string" ? Buffer.from(before.base64, "base64") : null;
|
|
7435
|
+
if (digest(await readBytes(file)) === staged.hash && (earlier ? hash2(earlier) === before.hash : before.hash === null)) {
|
|
7436
|
+
await assertOwned();
|
|
7437
|
+
if (earlier)
|
|
7438
|
+
await atomicWrite(file, earlier, void 0, assertOwned);
|
|
7439
|
+
else {
|
|
7440
|
+
await unlink2(file);
|
|
7441
|
+
await syncDirectory(root);
|
|
7442
|
+
}
|
|
7443
|
+
restored = true;
|
|
7444
|
+
}
|
|
7445
|
+
}
|
|
7446
|
+
await assertOwned();
|
|
7447
|
+
await unlink2(path).catch((error) => {
|
|
7448
|
+
if (error.code !== "ENOENT")
|
|
7449
|
+
throw error;
|
|
7450
|
+
});
|
|
7451
|
+
await syncDirectory(dirname5(path));
|
|
7452
|
+
const remote = record?.remote?.projectId;
|
|
7453
|
+
return {
|
|
7454
|
+
status: "cancelled",
|
|
7455
|
+
root,
|
|
7456
|
+
cleared: true,
|
|
7457
|
+
restored,
|
|
7458
|
+
...typeof remote === "string" ? { retainedRemoteUUID: remote } : {}
|
|
7459
|
+
};
|
|
7460
|
+
});
|
|
7461
|
+
}
|
|
7294
7462
|
|
|
7295
7463
|
// packages/cli/src/project.ts
|
|
7296
7464
|
import {
|
|
@@ -7306,6 +7474,27 @@ import {
|
|
|
7306
7474
|
readExecutorState,
|
|
7307
7475
|
saveCommandRecord
|
|
7308
7476
|
} from "./project/records.js";
|
|
7477
|
+
var shellWord = (value) => /^[\w@%+=:,./-]+$/u.test(value) ? value : `"${value.replace(/(["\\$`])/gu, "\\$1")}"`;
|
|
7478
|
+
function answerCommands(actions, root, details = {}) {
|
|
7479
|
+
const folder = shellWord(root);
|
|
7480
|
+
const linkFlags = (projectId, extra) => `mnemonik project link ${projectId} ${folder}${extra} --non-interactive --apply`;
|
|
7481
|
+
return actions.flatMap((action) => {
|
|
7482
|
+
if (action === "cancel")
|
|
7483
|
+
return [{ action, command: `mnemonik project setup ${folder} --cancel` }];
|
|
7484
|
+
if (action === "rerun_with_apply")
|
|
7485
|
+
return [{ action, command: `mnemonik project setup ${folder} --non-interactive --apply` }];
|
|
7486
|
+
if (action === "link")
|
|
7487
|
+
return (details.candidates ?? []).map((candidate) => ({
|
|
7488
|
+
action,
|
|
7489
|
+
command: linkFlags(candidate.projectId, "")
|
|
7490
|
+
}));
|
|
7491
|
+
if (action === "confirm_mismatch" && details.projectId)
|
|
7492
|
+
return [{ action, command: linkFlags(details.projectId, " --confirm-mismatch") }];
|
|
7493
|
+
if (action === "replace" && details.projectId)
|
|
7494
|
+
return [{ action, command: linkFlags(details.projectId, " --replace") }];
|
|
7495
|
+
return [];
|
|
7496
|
+
});
|
|
7497
|
+
}
|
|
7309
7498
|
async function ensureProjectRoot(root, executor) {
|
|
7310
7499
|
return executor.ensureProject({ cwd: root, allowCreate: true, allowNestedInherit: false });
|
|
7311
7500
|
}
|
|
@@ -7315,7 +7504,7 @@ var refusalReasons = {
|
|
|
7315
7504
|
temporary_directory: "Mnemonik does not index the temporary folder.",
|
|
7316
7505
|
mnemonik_state_directory: "That folder holds Mnemonik settings.",
|
|
7317
7506
|
user_data_directory: "That folder holds program settings.",
|
|
7318
|
-
host_config_directory: "That folder holds
|
|
7507
|
+
host_config_directory: "That folder holds coding tool settings.",
|
|
7319
7508
|
broad_workspace_parent: "It holds several projects, and Mnemonik would index all of them.",
|
|
7320
7509
|
not_found: "Its project file names a project this account cannot open.",
|
|
7321
7510
|
project_access_denied: "Its project file names a project this account cannot open.",
|
|
@@ -7366,7 +7555,7 @@ var refusalSteps = {
|
|
|
7366
7555
|
nested: "Run mnemonik project setup in that folder and choose which project it belongs to.",
|
|
7367
7556
|
conflict: "Run mnemonik project setup in that folder and choose which project it belongs to.",
|
|
7368
7557
|
identity_changed: AGAIN,
|
|
7369
|
-
operation_context_changed: "Run mnemonik project setup in that folder
|
|
7558
|
+
operation_context_changed: "Run mnemonik project setup --cancel in that folder, then run the command again.",
|
|
7370
7559
|
rollback_in_progress: "Wait for it to finish, then run the command again.",
|
|
7371
7560
|
operation_rolled_back: "Run mnemonik project setup in that folder to set it up again.",
|
|
7372
7561
|
not_staged: AGAIN,
|
|
@@ -7570,6 +7759,12 @@ function showResult(output, json, result, root, owner, record) {
|
|
|
7570
7759
|
..."candidates" in result && Array.isArray(result.candidates) ? { candidates: result.candidates } : {},
|
|
7571
7760
|
..."manualAction" in result ? { manualAction: result.manualAction } : {},
|
|
7572
7761
|
..."used" in result && "limit" in result ? { used: result.used, limit: result.limit } : {},
|
|
7762
|
+
..."allowedActions" in result ? {
|
|
7763
|
+
commands: answerCommands(result.allowedActions, root, {
|
|
7764
|
+
candidates: "candidates" in result && Array.isArray(result.candidates) ? result.candidates : void 0,
|
|
7765
|
+
projectId: record.projectId ?? void 0
|
|
7766
|
+
})
|
|
7767
|
+
} : {},
|
|
7573
7768
|
root,
|
|
7574
7769
|
owner: ownerLabel(owner)
|
|
7575
7770
|
});
|
|
@@ -7671,6 +7866,23 @@ async function statusCommand(input, deps) {
|
|
|
7671
7866
|
}
|
|
7672
7867
|
return 0;
|
|
7673
7868
|
}
|
|
7869
|
+
async function cancelCommand(input, deps) {
|
|
7870
|
+
const cwd = input.path ?? deps.cwd;
|
|
7871
|
+
const resolution = await (deps.executor ?? deps.resolver ?? { resolveProjectIdentity }).resolveProjectIdentity(cwd, { allowNestedInherit: false });
|
|
7872
|
+
const result = await cancelProjectSetup(
|
|
7873
|
+
"root" in resolution ? resolution.root : cwd,
|
|
7874
|
+
deps.stateDir
|
|
7875
|
+
);
|
|
7876
|
+
if (input.json) deps.output.json(result);
|
|
7877
|
+
else {
|
|
7878
|
+
const name2 = basename3(result.root);
|
|
7879
|
+
deps.output.line(
|
|
7880
|
+
result.cleared ? `Setup of ${name2} was cancelled.` : `Nothing was waiting for ${name2}.`
|
|
7881
|
+
);
|
|
7882
|
+
if (result.restored) deps.output.line("Its project file is back as it was.");
|
|
7883
|
+
}
|
|
7884
|
+
return 0;
|
|
7885
|
+
}
|
|
7674
7886
|
async function runProjectCommandInner(input, deps, prompts) {
|
|
7675
7887
|
if (input.command === "status") return statusCommand(input, deps);
|
|
7676
7888
|
if (!deps.executor)
|
|
@@ -7691,7 +7903,7 @@ async function runProjectCommandInner(input, deps, prompts) {
|
|
|
7691
7903
|
const cwd = input.path ?? deps.cwd;
|
|
7692
7904
|
const resolution = await executor.resolveProjectIdentity(cwd);
|
|
7693
7905
|
if (resolution.kind === "nested" || resolution.kind === "conflict") {
|
|
7694
|
-
const identityLocation =
|
|
7906
|
+
const identityLocation = join8(resolution.root, ".mnemonik.json");
|
|
7695
7907
|
if (!input.json) {
|
|
7696
7908
|
deps.output.line(`Root: ${resolution.root}`);
|
|
7697
7909
|
deps.output.line(`Identity: ${identityLocation}`);
|
|
@@ -7839,7 +8051,7 @@ async function runProjectCommandInner(input, deps, prompts) {
|
|
|
7839
8051
|
if (input.command === "init" && !input.nonInteractive && !input.json) {
|
|
7840
8052
|
if (result.status === "ignored") {
|
|
7841
8053
|
deps.output.line(`Root: ${decision.root}`);
|
|
7842
|
-
deps.output.line(`Identity: ${
|
|
8054
|
+
deps.output.line(`Identity: ${join8(decision.root, ".mnemonik.json")}`);
|
|
7843
8055
|
if (await prompts.confirm("Stop ignoring this folder and continue?"))
|
|
7844
8056
|
result = await executor.ensureProject({ ...base, clearIgnore: true });
|
|
7845
8057
|
} else if ("allowedActions" in result && result.allowedActions.includes("ignore") && await prompts.confirm("Ignore this folder on this machine?"))
|
|
@@ -7848,6 +8060,7 @@ async function runProjectCommandInner(input, deps, prompts) {
|
|
|
7848
8060
|
return finish(deps, input, result, decision.root, decision.reason, owner, beforeHash);
|
|
7849
8061
|
}
|
|
7850
8062
|
async function runProjectCommand(input, deps) {
|
|
8063
|
+
if (input.cancel) return cancelCommand(input, deps);
|
|
7851
8064
|
const prompts = new Prompter(deps.input, deps.output);
|
|
7852
8065
|
try {
|
|
7853
8066
|
let effective = deps;
|
|
@@ -7961,6 +8174,7 @@ async function rollbackProjectIdentity(options) {
|
|
|
7961
8174
|
return result.status === "rolled_back" ? 0 : 3;
|
|
7962
8175
|
}
|
|
7963
8176
|
export {
|
|
8177
|
+
answerCommands,
|
|
7964
8178
|
connectedProjectsMessage,
|
|
7965
8179
|
createRealProjectRuntime,
|
|
7966
8180
|
ensureProjectForAgent,
|