@getmikie/cli 1.1.86 → 1.1.88
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/README.md +15 -0
- package/bin/mikie.mjs +157 -0
- package/lib/launcher.mjs +88 -0
- package/lib/update.mjs +2944 -0
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -16,3 +16,18 @@ mikie mcp
|
|
|
16
16
|
The launcher contains no relay, pricing, receipt, or model logic. npm installs
|
|
17
17
|
the matching `@getmikie/*` optional platform package and the launcher executes that
|
|
18
18
|
binary with inherited stdio.
|
|
19
|
+
|
|
20
|
+
## Mikie Control
|
|
21
|
+
|
|
22
|
+
Run one immutable, repository-scoped request through the verified Codex App
|
|
23
|
+
Server runtime:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
mikie control run --request C:\absolute\path\control-request.json --json
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The request must be an existing absolute JSON file. Mikie validates the frozen
|
|
30
|
+
repository, allowed paths, deterministic verifier, exact model and reasoning
|
|
31
|
+
effort, bounded model-turn timeout, and private temporary root before execution. The JSON result is
|
|
32
|
+
content-free: it reports terminal status and hashes, never prompts, context,
|
|
33
|
+
patch bodies, verifier output, or credentials.
|
package/bin/mikie.mjs
CHANGED
|
@@ -1,12 +1,28 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
|
+
import { homedir } from "node:os";
|
|
5
|
+
import { access } from "node:fs/promises";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
4
8
|
|
|
5
9
|
import {
|
|
10
|
+
launchNativeCaptured,
|
|
6
11
|
launchNative,
|
|
7
12
|
resolveNativeBinary,
|
|
13
|
+
selectPlatformPackage,
|
|
8
14
|
translateArguments,
|
|
9
15
|
} from "../lib/launcher.mjs";
|
|
16
|
+
import {
|
|
17
|
+
UpdateTopology,
|
|
18
|
+
createCommandAdapter,
|
|
19
|
+
createFilesystemAdapter,
|
|
20
|
+
createRegistryAdapter,
|
|
21
|
+
detectUpdateTopology,
|
|
22
|
+
externalRecoveryInvocation,
|
|
23
|
+
parseUpdateHandoff,
|
|
24
|
+
runUpdateTransaction,
|
|
25
|
+
} from "../lib/update.mjs";
|
|
10
26
|
|
|
11
27
|
const require = createRequire(import.meta.url);
|
|
12
28
|
const packageMetadata = require("../package.json");
|
|
@@ -22,9 +38,150 @@ Usage:
|
|
|
22
38
|
mikie mcp [--adapter codex|claude_code]
|
|
23
39
|
mikie login
|
|
24
40
|
mikie connect .
|
|
41
|
+
mikie control run --request <absolute-json> --json
|
|
25
42
|
mikie doctor
|
|
43
|
+
mikie update
|
|
26
44
|
|
|
27
45
|
All commands execute the compiled Mikie native engine.`);
|
|
46
|
+
} else if (arguments_.length === 1 && arguments_[0].toLowerCase() === "update") {
|
|
47
|
+
try {
|
|
48
|
+
const commands = createCommandAdapter();
|
|
49
|
+
const npmRoot = await commands.run("npm", ["root", "--global"], {
|
|
50
|
+
shell: false,
|
|
51
|
+
capture: true,
|
|
52
|
+
});
|
|
53
|
+
const npmPrefix = await commands.run("npm", ["prefix", "--global"], {
|
|
54
|
+
shell: false,
|
|
55
|
+
capture: true,
|
|
56
|
+
});
|
|
57
|
+
if (
|
|
58
|
+
npmRoot.code !== 0 ||
|
|
59
|
+
npmRoot.stdout.trim().split(/\r?\n/).length !== 1 ||
|
|
60
|
+
!path.isAbsolute(npmRoot.stdout.trim()) ||
|
|
61
|
+
npmPrefix.code !== 0 ||
|
|
62
|
+
npmPrefix.stdout.trim().split(/\r?\n/).length !== 1 ||
|
|
63
|
+
!path.isAbsolute(npmPrefix.stdout.trim())
|
|
64
|
+
) {
|
|
65
|
+
throw new Error("global npm installation authority is unavailable");
|
|
66
|
+
}
|
|
67
|
+
const topology = detectUpdateTopology({ globalNodeModules: npmRoot.stdout.trim() });
|
|
68
|
+
const customerHome = homedir();
|
|
69
|
+
const transactionRoot = path.join(customerHome, ".mikie", "npm-update-v1");
|
|
70
|
+
const recoveryJournal = path.join(transactionRoot, "journal.json");
|
|
71
|
+
if (topology === UpdateTopology.NpmGlobal) {
|
|
72
|
+
try {
|
|
73
|
+
await access(recoveryJournal);
|
|
74
|
+
const invocation = await externalRecoveryInvocation(transactionRoot);
|
|
75
|
+
const recovered = await commands.run(invocation.executable, invocation.args, {
|
|
76
|
+
shell: false,
|
|
77
|
+
capture: true,
|
|
78
|
+
});
|
|
79
|
+
if (recovered.code !== 0) {
|
|
80
|
+
throw new Error("pending Mikie update recovery failed");
|
|
81
|
+
}
|
|
82
|
+
} catch (error) {
|
|
83
|
+
if (error?.code !== "ENOENT") throw error;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const selected = selectPlatformPackage();
|
|
87
|
+
const platformPackageJson = require.resolve(`${selected.packageName}/package.json`);
|
|
88
|
+
const wrapperPackageJson = fileURLToPath(new URL("../package.json", import.meta.url));
|
|
89
|
+
const binary = await resolveNativeBinary();
|
|
90
|
+
const globalPrefix = npmPrefix.stdout.trim();
|
|
91
|
+
const globalShims =
|
|
92
|
+
process.platform === "win32"
|
|
93
|
+
? ["mikie", "mikie.cmd", "mikie.ps1"].map((name) => path.join(globalPrefix, name))
|
|
94
|
+
: [path.join(globalPrefix, "bin", "mikie")];
|
|
95
|
+
const handoffResult = await launchNativeCaptured(binary, ["update"], { topology });
|
|
96
|
+
if (handoffResult.code !== 0) {
|
|
97
|
+
if (handoffResult.stderr) process.stderr.write(handoffResult.stderr);
|
|
98
|
+
throw new Error(`native update handoff exited with status ${handoffResult.code}`);
|
|
99
|
+
}
|
|
100
|
+
const handoff = parseUpdateHandoff(handoffResult.stdout, topology);
|
|
101
|
+
const registry = createRegistryAdapter({ commands });
|
|
102
|
+
const files = createFilesystemAdapter({
|
|
103
|
+
currentLayout: { wrapperPackageJson, platformPackageJson, binary, shims: globalShims },
|
|
104
|
+
locateCandidate: async ({ stagingPrefix } = {}) => {
|
|
105
|
+
if (stagingPrefix) {
|
|
106
|
+
const nodeModules =
|
|
107
|
+
process.platform === "win32"
|
|
108
|
+
? path.join(stagingPrefix, "node_modules")
|
|
109
|
+
: path.join(stagingPrefix, "lib", "node_modules");
|
|
110
|
+
const stagedWrapper = path.join(nodeModules, "@getmikie", "cli", "package.json");
|
|
111
|
+
const stagedPlatform = path.join(
|
|
112
|
+
nodeModules,
|
|
113
|
+
...selected.packageName.split("/"),
|
|
114
|
+
"package.json",
|
|
115
|
+
);
|
|
116
|
+
return {
|
|
117
|
+
wrapperPackageJson: stagedWrapper,
|
|
118
|
+
platformPackageJson: stagedPlatform,
|
|
119
|
+
binary: path.join(
|
|
120
|
+
path.dirname(stagedPlatform),
|
|
121
|
+
...selected.binaryPath.split("/"),
|
|
122
|
+
),
|
|
123
|
+
shims:
|
|
124
|
+
process.platform === "win32"
|
|
125
|
+
? ["mikie", "mikie.cmd", "mikie.ps1"].map((name) =>
|
|
126
|
+
path.join(stagingPrefix, name),
|
|
127
|
+
)
|
|
128
|
+
: [path.join(stagingPrefix, "bin", "mikie")],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
wrapperPackageJson,
|
|
133
|
+
platformPackageJson: require.resolve(`${selected.packageName}/package.json`),
|
|
134
|
+
binary: await resolveNativeBinary(),
|
|
135
|
+
shims: globalShims,
|
|
136
|
+
};
|
|
137
|
+
},
|
|
138
|
+
providerPaths: {
|
|
139
|
+
registration: path.join(customerHome, ".claude.json"),
|
|
140
|
+
settings: path.join(customerHome, ".claude", "settings.json"),
|
|
141
|
+
ownership: path.join(customerHome, ".claude", "mikie-evidence-hook-ownership.json"),
|
|
142
|
+
},
|
|
143
|
+
transactionRoot,
|
|
144
|
+
settleProviderRepair: async (phase, snapshot) => {
|
|
145
|
+
const settlementBinary = snapshot?.preparedCandidate?.binary;
|
|
146
|
+
const finalLauncher = snapshot?.preparedCandidate?.finalLauncher;
|
|
147
|
+
if (!settlementBinary || !finalLauncher) {
|
|
148
|
+
throw new Error("prepared candidate recovery authority is unavailable");
|
|
149
|
+
}
|
|
150
|
+
const settlement = await commands.run(settlementBinary, handoff.repair_command, {
|
|
151
|
+
shell: false,
|
|
152
|
+
capture: true,
|
|
153
|
+
environment: {
|
|
154
|
+
MIKIE_DISTRIBUTION_MODE: "npm",
|
|
155
|
+
MIKIE_NPM_UPDATE_TOPOLOGY: UpdateTopology.NpmGlobal,
|
|
156
|
+
MIKIE_NPM_UPDATE_REPAIR_PHASE: phase,
|
|
157
|
+
MIKIE_UPDATE_REPAIR_CANDIDATE: settlementBinary,
|
|
158
|
+
MIKIE_UPDATE_REPAIR_LAUNCHER: finalLauncher,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
if (settlement.code !== 0) {
|
|
162
|
+
throw new Error("candidate owned-adapter settlement failed");
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
const result = await runUpdateTransaction({
|
|
167
|
+
handoff,
|
|
168
|
+
currentVersion: packageMetadata.version,
|
|
169
|
+
platformPackage: selected.packageName,
|
|
170
|
+
registry,
|
|
171
|
+
commands,
|
|
172
|
+
files,
|
|
173
|
+
});
|
|
174
|
+
if (result.status === "updated") {
|
|
175
|
+
console.log(`Updated Mikie to ${result.version}.`);
|
|
176
|
+
for (const setting of result.foreignSettings) {
|
|
177
|
+
console.log(`Preserved foreign setting: ${setting}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} catch (error) {
|
|
181
|
+
const message = error instanceof Error ? error.message : "Mikie update failed";
|
|
182
|
+
console.error(`mikie: ${message}`);
|
|
183
|
+
process.exitCode = 1;
|
|
184
|
+
}
|
|
28
185
|
} else {
|
|
29
186
|
try {
|
|
30
187
|
const binary = await resolveNativeBinary();
|
package/lib/launcher.mjs
CHANGED
|
@@ -17,6 +17,8 @@ const SIGNAL_EXIT_CODES = new Map([
|
|
|
17
17
|
["SIGTERM", 143],
|
|
18
18
|
]);
|
|
19
19
|
|
|
20
|
+
const MAX_CAPTURED_OUTPUT_BYTES = 1024 * 1024;
|
|
21
|
+
|
|
20
22
|
function currentRuntimeUsesGlibc() {
|
|
21
23
|
try {
|
|
22
24
|
const report = process.report?.getReport();
|
|
@@ -122,3 +124,89 @@ export function launchNative(
|
|
|
122
124
|
});
|
|
123
125
|
});
|
|
124
126
|
}
|
|
127
|
+
|
|
128
|
+
export function launchNativeCaptured(
|
|
129
|
+
binary,
|
|
130
|
+
arguments_,
|
|
131
|
+
{
|
|
132
|
+
topology,
|
|
133
|
+
spawnProcess = spawn,
|
|
134
|
+
environment = process.env,
|
|
135
|
+
timeoutMs = 30_000,
|
|
136
|
+
scheduleTimeout = setTimeout,
|
|
137
|
+
cancelTimeout = clearTimeout,
|
|
138
|
+
} = {},
|
|
139
|
+
) {
|
|
140
|
+
if (!["npm_global", "npm_ephemeral"].includes(topology)) {
|
|
141
|
+
throw new Error("Mikie npm update topology is invalid");
|
|
142
|
+
}
|
|
143
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
|
|
144
|
+
throw new Error("Mikie native update timeout is invalid");
|
|
145
|
+
}
|
|
146
|
+
return new Promise((resolve, reject) => {
|
|
147
|
+
let settled = false;
|
|
148
|
+
const stdout = [];
|
|
149
|
+
const stderr = [];
|
|
150
|
+
let capturedBytes = 0;
|
|
151
|
+
const child = spawnProcess(binary, arguments_, {
|
|
152
|
+
shell: false,
|
|
153
|
+
stdio: ["inherit", "pipe", "pipe"],
|
|
154
|
+
windowsHide: true,
|
|
155
|
+
env: {
|
|
156
|
+
...environment,
|
|
157
|
+
MIKIE_DISTRIBUTION_MODE: "npm",
|
|
158
|
+
MIKIE_NPM_UPDATE_TOPOLOGY: topology,
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
const deadline = scheduleTimeout(() => {
|
|
162
|
+
if (settled) return;
|
|
163
|
+
settled = true;
|
|
164
|
+
try {
|
|
165
|
+
child.kill?.("SIGKILL");
|
|
166
|
+
} catch {
|
|
167
|
+
// The child may already have exited.
|
|
168
|
+
}
|
|
169
|
+
reject(new Error("Mikie native update command timed out"));
|
|
170
|
+
}, timeoutMs);
|
|
171
|
+
const finish = (callback) => {
|
|
172
|
+
if (settled) return false;
|
|
173
|
+
settled = true;
|
|
174
|
+
cancelTimeout(deadline);
|
|
175
|
+
callback();
|
|
176
|
+
return true;
|
|
177
|
+
};
|
|
178
|
+
const capture = (target) => (chunk) => {
|
|
179
|
+
if (settled) return;
|
|
180
|
+
const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
181
|
+
capturedBytes += bytes.length;
|
|
182
|
+
if (capturedBytes > MAX_CAPTURED_OUTPUT_BYTES) {
|
|
183
|
+
finish(() => {
|
|
184
|
+
try {
|
|
185
|
+
child.kill?.("SIGKILL");
|
|
186
|
+
} catch {
|
|
187
|
+
// The child may already have exited.
|
|
188
|
+
}
|
|
189
|
+
reject(new Error("Mikie native update response exceeded the capture limit"));
|
|
190
|
+
});
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
target.push(bytes);
|
|
194
|
+
};
|
|
195
|
+
child.stdout.on("data", capture(stdout));
|
|
196
|
+
child.stderr.on("data", capture(stderr));
|
|
197
|
+
child.once("error", (error) => {
|
|
198
|
+
finish(() =>
|
|
199
|
+
reject(new Error("Mikie native update command could not be started", { cause: error })),
|
|
200
|
+
);
|
|
201
|
+
});
|
|
202
|
+
child.once("close", (code, signal) => {
|
|
203
|
+
finish(() =>
|
|
204
|
+
resolve({
|
|
205
|
+
code: Number.isInteger(code) ? code : (SIGNAL_EXIT_CODES.get(signal) ?? 1),
|
|
206
|
+
stdout: Buffer.concat(stdout).toString("utf8"),
|
|
207
|
+
stderr: Buffer.concat(stderr).toString("utf8"),
|
|
208
|
+
}),
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
}
|