@rizzmyrobot/mochi-cli 0.0.3 → 0.0.4
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 +36 -28
- package/dist/index.js +533 -28
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -174,12 +174,12 @@ explicit-config live Telegram delivery and Bot API polling primitives, tests,
|
|
|
174
174
|
and planning docs. The local V0 owner proof lives in
|
|
175
175
|
[`docs/runtime/v0-manual-proof.md`](docs/runtime/v0-manual-proof.md).
|
|
176
176
|
|
|
177
|
-
Mochi still does not publish player packages, host
|
|
178
|
-
ingress by default, expose public dashboard
|
|
179
|
-
control panels, run production Prom13us/Rizz
|
|
180
|
-
contracts and server-validated proofs, support
|
|
181
|
-
arbitrary live MCP tools, provide hosted accounts, or
|
|
182
|
-
trusted game-owned validation.
|
|
177
|
+
Mochi still does not publish preferred `@mochi/*` player packages, host
|
|
178
|
+
certification, open live HTTP ingress by default, expose public dashboard
|
|
179
|
+
ingress, provide dashboard game control panels, run production Prom13us/Rizz
|
|
180
|
+
play outside compatible-game contracts and server-validated proofs, support
|
|
181
|
+
unsupported games, execute arbitrary live MCP tools, provide hosted accounts, or
|
|
182
|
+
mutate game canon outside trusted game-owned validation.
|
|
183
183
|
|
|
184
184
|
Mochi uses the Apache-2.0 license. See `CONTRIBUTING.md`, `SECURITY.md`, and
|
|
185
185
|
`PRIVACY.md` before opening public contributions, reporting vulnerabilities, or
|
|
@@ -192,28 +192,34 @@ as a default.
|
|
|
192
192
|
|
|
193
193
|
## Player Install
|
|
194
194
|
|
|
195
|
-
Mochi is pre-alpha, and
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
195
|
+
Mochi is pre-alpha, and the fallback CLI package is registry-proven at
|
|
196
|
+
`@rizzmyrobot/mochi-cli@0.0.3` by trusted publishing plus
|
|
197
|
+
`npm view @rizzmyrobot/mochi-cli@0.0.3` proof. The public player install path is npm/npx,
|
|
198
|
+
not cloning the repository and running Bun.
|
|
199
199
|
|
|
200
200
|
Because `@mochi/*` npm ownership is not proven, the fallback package scope is
|
|
201
|
-
the current public install target. The
|
|
201
|
+
the current public install target. The one-line player install is:
|
|
202
202
|
|
|
203
203
|
```bash
|
|
204
204
|
npm install -g @rizzmyrobot/mochi-cli
|
|
205
205
|
mochi onboard
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
`mochi onboard` is the player first-run command.
|
|
209
|
-
|
|
210
|
-
Telegram
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
208
|
+
`mochi onboard` is the player first-run command. In an interactive terminal it
|
|
209
|
+
runs a real guided setup: choose MiniMax OAuth, OpenAI API key, or Codex OAuth;
|
|
210
|
+
choose Telegram, Discord, or no channel; seed the proof workspace; write local
|
|
211
|
+
runtime config refs; store local secrets; validate Telegram bot tokens with the
|
|
212
|
+
Bot API `getMe` check; and print the exact `mochi talk` / `mochi telegram
|
|
213
|
+
listen` proof commands to run next. Non-interactive `mochi onboard --guide`
|
|
214
|
+
remains a no-write preview for CI, docs, and scripts.
|
|
215
|
+
|
|
216
|
+
MiniMax OAuth, OpenAI API-key refs, Telegram config, workspace seed files,
|
|
217
|
+
local provider credential refs, and local Telegram token refs reuse the existing
|
|
218
|
+
provider auth, configure, proof workspace seed, Telegram, Gateway, and
|
|
219
|
+
secret-store packages. Codex OAuth runs the external `codex login` path, but it
|
|
220
|
+
is not yet a Mochi provider runtime for `mochi talk`. Discord is exposed as a
|
|
221
|
+
product choice, but it does not accept or store Discord bot tokens until a
|
|
222
|
+
Discord runtime package exists.
|
|
217
223
|
|
|
218
224
|
npx follows the same fallback scope:
|
|
219
225
|
|
|
@@ -235,14 +241,16 @@ mochi onboard
|
|
|
235
241
|
```
|
|
236
242
|
|
|
237
243
|
Current public install `gateway start/status/doctor` commands remain dry-run
|
|
238
|
-
planning proofs. `mochi onboard` may write local workspace seed
|
|
239
|
-
config refs, and local secrets
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
244
|
+
planning proofs. Interactive `mochi onboard` may write local workspace seed
|
|
245
|
+
files, runtime config refs, and local secrets; MiniMax OAuth may open a browser,
|
|
246
|
+
start a loopback callback server, and call the provider token endpoint; Telegram
|
|
247
|
+
setup may call only the Bot API `getMe` validation endpoint. It does not call
|
|
248
|
+
model providers, poll Telegram, send Telegram messages, connect Discord,
|
|
249
|
+
connect games, submit production intents, or change game canon. The separate
|
|
250
|
+
credentialed `talk` command can call a selected model provider for a local
|
|
251
|
+
Mochi reply; contributor/runtime docs describe the local owner proof for
|
|
252
|
+
credentialed provider and Telegram conversation, and the mock-game proof
|
|
253
|
+
exercises a fixture provider response
|
|
246
254
|
plus a trusted local adapter receipt.
|
|
247
255
|
|
|
248
256
|
The local laptop Gateway install flow lives in
|
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import { lstatSync } from "fs";
|
|
|
21
21
|
import { access, mkdir as mkdir6, readFile as readFile10, rename, rm as rm2, stat as stat3, writeFile as writeFile6 } from "fs/promises";
|
|
22
22
|
import { createServer } from "http";
|
|
23
23
|
import { dirname as dirname7, isAbsolute as isAbsolute4, join as join5, resolve as resolve4 } from "path";
|
|
24
|
+
import { createInterface } from "readline";
|
|
24
25
|
import { Database as Database13 } from "bun:sqlite";
|
|
25
26
|
|
|
26
27
|
// node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
@@ -51044,7 +51045,7 @@ function renderCliHelp() {
|
|
|
51044
51045
|
"",
|
|
51045
51046
|
"Commands:",
|
|
51046
51047
|
" init --dry-run [--profile local] [--workspace-root <path>] [--storage-path <path>] [--host 127.0.0.1] [--port 7332]",
|
|
51047
|
-
" onboard [--workspace-root <path>] [--provider minimax-oauth|codex-oauth|openai-api-key] [--model <model>] [--channel telegram|discord|none] [--owner <owner-id>] [--telegram-user-id <id>] [--credential-stdin] [--telegram-token-stdin] [--confirm] [--format text|json]",
|
|
51048
|
+
" onboard [--interactive|--guide] [--workspace-root <path>] [--provider minimax-oauth|codex-oauth|openai-api-key] [--model <model>] [--channel telegram|discord|none] [--owner <owner-id>] [--telegram-user-id <id>] [--credential-stdin] [--telegram-token-stdin] [--confirm] [--format text|json]",
|
|
51048
51049
|
" onboard bootstrap --dry-run [--fixture complete] [--decision-fixture approve-edit-reject]",
|
|
51049
51050
|
" onboard bootstrap --apply --confirm --workspace-root <path> --checkpoint-ref <ref> --fixture complete --decision-fixture approve-edit-reject",
|
|
51050
51051
|
" onboard play-contract --dry-run --fixture complete [--decision approve|reject|reset]",
|
|
@@ -58558,6 +58559,7 @@ function parseCliOnboardRootArgs(args = [], env = process.env) {
|
|
|
58558
58559
|
let channel = "telegram";
|
|
58559
58560
|
let ownerId;
|
|
58560
58561
|
let telegramUserId;
|
|
58562
|
+
let interactionMode = "auto";
|
|
58561
58563
|
let confirm = false;
|
|
58562
58564
|
let credentialStdin = false;
|
|
58563
58565
|
let telegramTokenStdin = false;
|
|
@@ -58656,6 +58658,14 @@ function parseCliOnboardRootArgs(args = [], env = process.env) {
|
|
|
58656
58658
|
confirm = true;
|
|
58657
58659
|
continue;
|
|
58658
58660
|
}
|
|
58661
|
+
if (arg === "--interactive") {
|
|
58662
|
+
interactionMode = "interactive";
|
|
58663
|
+
continue;
|
|
58664
|
+
}
|
|
58665
|
+
if (arg === "--guide" || arg === "--dry-run" || arg === "--non-interactive") {
|
|
58666
|
+
interactionMode = "guide";
|
|
58667
|
+
continue;
|
|
58668
|
+
}
|
|
58659
58669
|
if (arg === "--credential-stdin") {
|
|
58660
58670
|
credentialStdin = true;
|
|
58661
58671
|
continue;
|
|
@@ -58710,6 +58720,7 @@ function parseCliOnboardRootArgs(args = [], env = process.env) {
|
|
|
58710
58720
|
channel,
|
|
58711
58721
|
...ownerId?.trim() ? { ownerId: ownerId.trim() } : {},
|
|
58712
58722
|
...telegramUserId?.trim() ? { telegramUserId: telegramUserId.trim() } : {},
|
|
58723
|
+
interactionMode,
|
|
58713
58724
|
confirm,
|
|
58714
58725
|
credentialStdin,
|
|
58715
58726
|
telegramTokenStdin,
|
|
@@ -58822,7 +58833,504 @@ function cliOnboardStoresSecrets(payload) {
|
|
|
58822
58833
|
function cliOnboardProviderCredentialRef(provider) {
|
|
58823
58834
|
return provider === "minimax-oauth" ? "oauth:providers/minimax/default" : "secret:providers/openai/default";
|
|
58824
58835
|
}
|
|
58836
|
+
function cliOnboardProviderId(provider) {
|
|
58837
|
+
return provider === "minimax-oauth" ? "minimax" : "openai";
|
|
58838
|
+
}
|
|
58839
|
+
function cliOnboardProviderRefreshTokenRef(provider) {
|
|
58840
|
+
return provider === "minimax-oauth" ? "secret:providers/minimax/oauth/refresh-token" : undefined;
|
|
58841
|
+
}
|
|
58842
|
+
function cliOnboardProviderDefaultModel(provider, env) {
|
|
58843
|
+
if (env.MOCHI_MODEL?.trim()) {
|
|
58844
|
+
return env.MOCHI_MODEL.trim();
|
|
58845
|
+
}
|
|
58846
|
+
if (provider === "minimax-oauth") {
|
|
58847
|
+
return env.MOCHI_MINIMAX_MODEL?.trim() || "abab6.5s-chat";
|
|
58848
|
+
}
|
|
58849
|
+
if (provider === "openai-api-key") {
|
|
58850
|
+
return env.MOCHI_OPENAI_MODEL?.trim() || "gpt-4.1-mini";
|
|
58851
|
+
}
|
|
58852
|
+
return;
|
|
58853
|
+
}
|
|
58854
|
+
function cliOnboardIsTty() {
|
|
58855
|
+
return Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
58856
|
+
}
|
|
58857
|
+
function cliOnboardShouldRunInteractive(options) {
|
|
58858
|
+
if (options.confirm || options.interactionMode === "guide") {
|
|
58859
|
+
return false;
|
|
58860
|
+
}
|
|
58861
|
+
return options.interactionMode === "interactive" || cliOnboardIsTty();
|
|
58862
|
+
}
|
|
58863
|
+
function defaultCliOnboardReadLine(question) {
|
|
58864
|
+
const readline = createInterface({
|
|
58865
|
+
input: process.stdin,
|
|
58866
|
+
output: process.stdout
|
|
58867
|
+
});
|
|
58868
|
+
return new Promise((resolveAnswer) => {
|
|
58869
|
+
readline.question(question, (answer) => {
|
|
58870
|
+
readline.close();
|
|
58871
|
+
resolveAnswer(answer);
|
|
58872
|
+
});
|
|
58873
|
+
});
|
|
58874
|
+
}
|
|
58875
|
+
function defaultCliOnboardReadSecret(question) {
|
|
58876
|
+
if (!process.stdin.isTTY) {
|
|
58877
|
+
return defaultCliOnboardReadLine(question);
|
|
58878
|
+
}
|
|
58879
|
+
return new Promise((resolveSecret, rejectSecret) => {
|
|
58880
|
+
const input = process.stdin;
|
|
58881
|
+
const output = process.stdout;
|
|
58882
|
+
const rawInput = input;
|
|
58883
|
+
const wasRaw = rawInput.isRaw === true;
|
|
58884
|
+
let secret = "";
|
|
58885
|
+
const cleanup = () => {
|
|
58886
|
+
input.off("data", onData);
|
|
58887
|
+
if (rawInput.setRawMode) {
|
|
58888
|
+
rawInput.setRawMode(wasRaw);
|
|
58889
|
+
}
|
|
58890
|
+
input.pause();
|
|
58891
|
+
output.write(`
|
|
58892
|
+
`);
|
|
58893
|
+
};
|
|
58894
|
+
const onData = (chunk) => {
|
|
58895
|
+
const value = chunk.toString("utf8");
|
|
58896
|
+
for (const char of value) {
|
|
58897
|
+
if (char === "\x03") {
|
|
58898
|
+
cleanup();
|
|
58899
|
+
rejectSecret(new Error("Secret prompt interrupted."));
|
|
58900
|
+
return;
|
|
58901
|
+
}
|
|
58902
|
+
if (char === "\r" || char === `
|
|
58903
|
+
`) {
|
|
58904
|
+
cleanup();
|
|
58905
|
+
resolveSecret(secret);
|
|
58906
|
+
return;
|
|
58907
|
+
}
|
|
58908
|
+
if (char === "\b" || char === "\x7F") {
|
|
58909
|
+
secret = secret.slice(0, -1);
|
|
58910
|
+
continue;
|
|
58911
|
+
}
|
|
58912
|
+
secret += char;
|
|
58913
|
+
}
|
|
58914
|
+
};
|
|
58915
|
+
output.write(question);
|
|
58916
|
+
if (rawInput.setRawMode) {
|
|
58917
|
+
rawInput.setRawMode(true);
|
|
58918
|
+
}
|
|
58919
|
+
input.resume();
|
|
58920
|
+
input.on("data", onData);
|
|
58921
|
+
});
|
|
58922
|
+
}
|
|
58923
|
+
function defaultCliOnboardPrompt() {
|
|
58924
|
+
if (!cliOnboardIsTty()) {
|
|
58925
|
+
return;
|
|
58926
|
+
}
|
|
58927
|
+
return {
|
|
58928
|
+
readLine: defaultCliOnboardReadLine,
|
|
58929
|
+
readSecret: defaultCliOnboardReadSecret
|
|
58930
|
+
};
|
|
58931
|
+
}
|
|
58932
|
+
function parseCliOnboardInteractiveProvider(raw, fallback) {
|
|
58933
|
+
const value = raw.trim().toLowerCase();
|
|
58934
|
+
if (!value)
|
|
58935
|
+
return fallback;
|
|
58936
|
+
if (value === "1" || value === "minimax" || value === "minimax-oauth") {
|
|
58937
|
+
return "minimax-oauth";
|
|
58938
|
+
}
|
|
58939
|
+
if (value === "2" || value === "openai" || value === "openai-api-key" || value === "openai api key") {
|
|
58940
|
+
return "openai-api-key";
|
|
58941
|
+
}
|
|
58942
|
+
if (value === "3" || value === "codex" || value === "codex-oauth") {
|
|
58943
|
+
return "codex-oauth";
|
|
58944
|
+
}
|
|
58945
|
+
return parseCliOnboardRootProvider(value);
|
|
58946
|
+
}
|
|
58947
|
+
function parseCliOnboardInteractiveChannel(raw, fallback) {
|
|
58948
|
+
const value = raw.trim().toLowerCase();
|
|
58949
|
+
if (!value)
|
|
58950
|
+
return fallback;
|
|
58951
|
+
if (value === "1" || value === "telegram") {
|
|
58952
|
+
return "telegram";
|
|
58953
|
+
}
|
|
58954
|
+
if (value === "2" || value === "discord") {
|
|
58955
|
+
return "discord";
|
|
58956
|
+
}
|
|
58957
|
+
if (value === "3" || value === "none" || value === "skip") {
|
|
58958
|
+
return "none";
|
|
58959
|
+
}
|
|
58960
|
+
return parseCliOnboardRootChannel(value);
|
|
58961
|
+
}
|
|
58962
|
+
async function cliOnboardPromptValue(input) {
|
|
58963
|
+
const suffix = input.defaultValue ? ` [${input.defaultValue}]` : "";
|
|
58964
|
+
const question = `${input.question}${suffix}: `;
|
|
58965
|
+
const raw = input.secret ? await input.prompt.readSecret(question) : await input.prompt.readLine(question);
|
|
58966
|
+
return raw.trim() || input.defaultValue?.trim() || "";
|
|
58967
|
+
}
|
|
58968
|
+
function defaultCliOnboardExternalCommand() {
|
|
58969
|
+
return (command, args) => new Promise((resolveCommand) => {
|
|
58970
|
+
const child = spawn(command, [...args], { stdio: "inherit" });
|
|
58971
|
+
child.on("error", () => resolveCommand({ exitCode: 127 }));
|
|
58972
|
+
child.on("exit", (code) => resolveCommand({ exitCode: code ?? 1 }));
|
|
58973
|
+
});
|
|
58974
|
+
}
|
|
58975
|
+
function cliOnboardSharedSecretStore(dependencies) {
|
|
58976
|
+
return dependencies.secretStore ?? dependencies.providerAuth?.secretStore ?? dependencies.telegram?.secretStore;
|
|
58977
|
+
}
|
|
58978
|
+
function cliOnboardConfigureDependencies(dependencies, readSecret) {
|
|
58979
|
+
const secretStore = cliOnboardSharedSecretStore(dependencies);
|
|
58980
|
+
return {
|
|
58981
|
+
...secretStore ? { secretStore } : {},
|
|
58982
|
+
readSecret
|
|
58983
|
+
};
|
|
58984
|
+
}
|
|
58985
|
+
function cliOnboardProviderAuthDependencies(dependencies) {
|
|
58986
|
+
const secretStore = cliOnboardSharedSecretStore(dependencies);
|
|
58987
|
+
return {
|
|
58988
|
+
...dependencies.providerAuth,
|
|
58989
|
+
...secretStore ? { secretStore } : {}
|
|
58990
|
+
};
|
|
58991
|
+
}
|
|
58992
|
+
function cliOnboardTelegramDependencies(dependencies) {
|
|
58993
|
+
const secretStore = cliOnboardSharedSecretStore(dependencies);
|
|
58994
|
+
return {
|
|
58995
|
+
...dependencies.telegram,
|
|
58996
|
+
...secretStore ? { secretStore } : {}
|
|
58997
|
+
};
|
|
58998
|
+
}
|
|
58999
|
+
function cliOnboardSelectedRuntimeCommands(input) {
|
|
59000
|
+
if (input.provider === "codex-oauth") {
|
|
59001
|
+
return [
|
|
59002
|
+
"No Mochi talk proof command exists for Codex OAuth yet; choose minimax-oauth or openai-api-key for the current Mochi runtime."
|
|
59003
|
+
];
|
|
59004
|
+
}
|
|
59005
|
+
const providerId = cliOnboardProviderId(input.provider);
|
|
59006
|
+
const credentialRef = cliOnboardProviderCredentialRef(input.provider);
|
|
59007
|
+
const refreshTokenRef = cliOnboardProviderRefreshTokenRef(input.provider);
|
|
59008
|
+
return [
|
|
59009
|
+
[
|
|
59010
|
+
"mochi proof readiness",
|
|
59011
|
+
`--workspace-root ${input.workspaceRoot}`,
|
|
59012
|
+
`--provider ${providerId}`,
|
|
59013
|
+
`--credential-ref ${credentialRef}`,
|
|
59014
|
+
...refreshTokenRef ? [`--refresh-token-ref ${refreshTokenRef}`] : [],
|
|
59015
|
+
...input.channel === "telegram" ? [
|
|
59016
|
+
"--telegram-token-ref os:mochi/telegram/bot-token",
|
|
59017
|
+
`--owner ${input.ownerId ?? "<owner-id>"}`,
|
|
59018
|
+
`--telegram-user-id ${input.telegramUserId ?? "<telegram-user-id>"}`
|
|
59019
|
+
] : []
|
|
59020
|
+
].join(" "),
|
|
59021
|
+
[
|
|
59022
|
+
"mochi talk",
|
|
59023
|
+
`--workspace-root ${input.workspaceRoot}`,
|
|
59024
|
+
"--game mock-game",
|
|
59025
|
+
`--provider ${providerId}`,
|
|
59026
|
+
`--model ${input.model}`,
|
|
59027
|
+
`--credential-ref ${credentialRef}`,
|
|
59028
|
+
...refreshTokenRef ? [`--refresh-token-ref ${refreshTokenRef}`] : [],
|
|
59029
|
+
'--message "Hello Mochi. Answer in one short sentence."'
|
|
59030
|
+
].join(" "),
|
|
59031
|
+
...input.channel === "telegram" ? [
|
|
59032
|
+
[
|
|
59033
|
+
"mochi telegram listen",
|
|
59034
|
+
`--workspace-root ${input.workspaceRoot}`,
|
|
59035
|
+
"--game mock-game",
|
|
59036
|
+
`--owner ${input.ownerId ?? "<owner-id>"}`,
|
|
59037
|
+
`--telegram-user-id ${input.telegramUserId ?? "<telegram-user-id>"}`,
|
|
59038
|
+
`--provider ${providerId}`,
|
|
59039
|
+
`--model ${input.model}`,
|
|
59040
|
+
`--credential-ref ${credentialRef}`,
|
|
59041
|
+
...refreshTokenRef ? [`--refresh-token-ref ${refreshTokenRef}`] : [],
|
|
59042
|
+
"--telegram-token-ref os:mochi/telegram/bot-token",
|
|
59043
|
+
"--poll-once"
|
|
59044
|
+
].join(" ")
|
|
59045
|
+
] : []
|
|
59046
|
+
];
|
|
59047
|
+
}
|
|
59048
|
+
async function createCliOnboardInteractivePayload(options, env = process.env, dependencies = {}) {
|
|
59049
|
+
const prompt = dependencies.prompt ?? defaultCliOnboardPrompt();
|
|
59050
|
+
const warnings = [
|
|
59051
|
+
"Mochi onboard reuses provider auth, configure, proof workspace seed, Telegram, and Gateway runtime surfaces; it does not create parallel setup abstractions.",
|
|
59052
|
+
"Raw provider keys, OAuth tokens, refresh tokens, Telegram bot tokens, and auth headers are never printed or written to workspace files.",
|
|
59053
|
+
"Game connections and game actions remain server-authoritative; onboarding does not connect games, submit intents, or mutate game canon."
|
|
59054
|
+
];
|
|
59055
|
+
const blockers = [];
|
|
59056
|
+
if (!prompt) {
|
|
59057
|
+
const providerChoices2 = cliOnboardProviderChoices(options);
|
|
59058
|
+
const channelChoices2 = cliOnboardChannelChoices(options);
|
|
59059
|
+
return {
|
|
59060
|
+
type: "mochi.cli.onboard_first_run",
|
|
59061
|
+
ok: false,
|
|
59062
|
+
confirmed: true,
|
|
59063
|
+
workspaceRoot: options.workspaceRoot,
|
|
59064
|
+
selected: {
|
|
59065
|
+
provider: options.provider,
|
|
59066
|
+
channel: options.channel,
|
|
59067
|
+
model: options.model ?? null
|
|
59068
|
+
},
|
|
59069
|
+
providerChoices: providerChoices2,
|
|
59070
|
+
channelChoices: channelChoices2,
|
|
59071
|
+
setup: {},
|
|
59072
|
+
sideEffects: {
|
|
59073
|
+
writesWorkspaceFiles: false,
|
|
59074
|
+
writesRuntimeConfig: false,
|
|
59075
|
+
storesLocalSecrets: false,
|
|
59076
|
+
opensBrowser: false,
|
|
59077
|
+
startsLocalCallbackServer: false,
|
|
59078
|
+
runsExternalCodexLogin: false,
|
|
59079
|
+
callsProviderTokenEndpoint: false,
|
|
59080
|
+
callsTelegramGetMeEndpoint: false,
|
|
59081
|
+
callsModelProvider: false,
|
|
59082
|
+
pollsTelegram: false,
|
|
59083
|
+
sendsTelegram: false,
|
|
59084
|
+
connectsDiscord: false,
|
|
59085
|
+
connectsGames: false,
|
|
59086
|
+
submitsActions: false,
|
|
59087
|
+
mutatesGameCanon: false,
|
|
59088
|
+
secretsDisplayed: false
|
|
59089
|
+
},
|
|
59090
|
+
blockers: [
|
|
59091
|
+
"Interactive onboard requires a TTY. Use `mochi onboard --guide` for a no-write preview or pass `--confirm` with stdin flags for scripted setup."
|
|
59092
|
+
],
|
|
59093
|
+
nextCommands: ["mochi onboard --guide", "mochi onboard --confirm --help"],
|
|
59094
|
+
warnings
|
|
59095
|
+
};
|
|
59096
|
+
}
|
|
59097
|
+
const workspaceRoot = await cliOnboardPromptValue({
|
|
59098
|
+
prompt,
|
|
59099
|
+
question: "Workspace root",
|
|
59100
|
+
defaultValue: options.workspaceRoot
|
|
59101
|
+
});
|
|
59102
|
+
const providerAnswer = await prompt.readLine("Choose AI provider: 1) MiniMax OAuth 2) OpenAI API key 3) Codex OAuth [1]: ");
|
|
59103
|
+
const provider = parseCliOnboardInteractiveProvider(providerAnswer, options.provider);
|
|
59104
|
+
if (!provider) {
|
|
59105
|
+
blockers.push("Unsupported provider choice. Choose MiniMax OAuth, OpenAI API key, or Codex OAuth.");
|
|
59106
|
+
}
|
|
59107
|
+
const selectedProvider = provider ?? options.provider;
|
|
59108
|
+
const model = selectedProvider === "codex-oauth" ? options.model ?? null : await cliOnboardPromptValue({
|
|
59109
|
+
prompt,
|
|
59110
|
+
question: "Model",
|
|
59111
|
+
defaultValue: options.model ?? cliOnboardProviderDefaultModel(selectedProvider, env)
|
|
59112
|
+
});
|
|
59113
|
+
if (selectedProvider !== "codex-oauth" && !model) {
|
|
59114
|
+
blockers.push("Model is required for Mochi talk.");
|
|
59115
|
+
}
|
|
59116
|
+
const workspaceSeed = await createCliProofWorkspaceSeedPayload({
|
|
59117
|
+
workspaceRoot,
|
|
59118
|
+
game: cliProofWorkspaceSeedDefaultGame(),
|
|
59119
|
+
dryRun: false,
|
|
59120
|
+
confirm: true,
|
|
59121
|
+
journalDate: options.now.slice(0, 10),
|
|
59122
|
+
format: "json"
|
|
59123
|
+
});
|
|
59124
|
+
let providerConfig;
|
|
59125
|
+
let providerAuth;
|
|
59126
|
+
let codexLogin;
|
|
59127
|
+
if (selectedProvider === "minimax-oauth") {
|
|
59128
|
+
const defaults = cliProviderOauthAuthChoices["minimax-global-oauth"];
|
|
59129
|
+
const clientId = await cliOnboardPromptValue({
|
|
59130
|
+
prompt,
|
|
59131
|
+
question: "MiniMax OAuth client ID",
|
|
59132
|
+
defaultValue: env.MOCHI_MINIMAX_OAUTH_CLIENT_ID?.trim()
|
|
59133
|
+
});
|
|
59134
|
+
if (!clientId) {
|
|
59135
|
+
blockers.push("MiniMax OAuth client ID is required.");
|
|
59136
|
+
} else if (model) {
|
|
59137
|
+
providerAuth = await createCliProviderAuthPayload({
|
|
59138
|
+
command: "oauth_login",
|
|
59139
|
+
providerId: defaults.providerId,
|
|
59140
|
+
authChoice: defaults.authChoice,
|
|
59141
|
+
authorizationEndpoint: defaults.authorizationEndpoint,
|
|
59142
|
+
tokenEndpoint: defaults.tokenEndpoint,
|
|
59143
|
+
clientId,
|
|
59144
|
+
redirectUri: defaults.redirectUri,
|
|
59145
|
+
scopes: defaults.scopes,
|
|
59146
|
+
accessTokenRef: defaults.accessTokenRef,
|
|
59147
|
+
refreshTokenRef: defaults.refreshTokenRef,
|
|
59148
|
+
workspaceRoot,
|
|
59149
|
+
model,
|
|
59150
|
+
baseUrl: defaults.baseUrl,
|
|
59151
|
+
openBrowser: true,
|
|
59152
|
+
timeoutMs: 120000,
|
|
59153
|
+
state: `mochi-${randomUUID()}`,
|
|
59154
|
+
format: "json",
|
|
59155
|
+
now: options.now
|
|
59156
|
+
}, env, cliOnboardProviderAuthDependencies(dependencies));
|
|
59157
|
+
if (!providerAuth.ok) {
|
|
59158
|
+
blockers.push(`MiniMax OAuth login failed: ${providerAuth.exchange?.publicSummary ?? "provider auth did not complete"}`);
|
|
59159
|
+
}
|
|
59160
|
+
}
|
|
59161
|
+
}
|
|
59162
|
+
if (selectedProvider === "openai-api-key") {
|
|
59163
|
+
const apiKey = await cliOnboardPromptValue({
|
|
59164
|
+
prompt,
|
|
59165
|
+
question: "OpenAI API key",
|
|
59166
|
+
secret: true
|
|
59167
|
+
});
|
|
59168
|
+
if (!apiKey) {
|
|
59169
|
+
blockers.push("OpenAI API key is required.");
|
|
59170
|
+
} else if (model) {
|
|
59171
|
+
providerConfig = await createCliConfigurePayload({
|
|
59172
|
+
command: "provider",
|
|
59173
|
+
workspaceRoot,
|
|
59174
|
+
providerId: "openai",
|
|
59175
|
+
model,
|
|
59176
|
+
credentialRef: "secret:providers/openai/default",
|
|
59177
|
+
credentialStdin: true,
|
|
59178
|
+
now: options.now,
|
|
59179
|
+
format: "json"
|
|
59180
|
+
}, env, cliOnboardConfigureDependencies(dependencies, () => apiKey));
|
|
59181
|
+
if (!providerConfig.ok) {
|
|
59182
|
+
blockers.push("OpenAI provider configure failed; inspect stored secret status and retry.");
|
|
59183
|
+
}
|
|
59184
|
+
}
|
|
59185
|
+
}
|
|
59186
|
+
if (selectedProvider === "codex-oauth") {
|
|
59187
|
+
const runExternalCommand = dependencies.runExternalCommand ?? defaultCliOnboardExternalCommand();
|
|
59188
|
+
codexLogin = {
|
|
59189
|
+
attempted: true,
|
|
59190
|
+
...await runExternalCommand("codex", ["login"])
|
|
59191
|
+
};
|
|
59192
|
+
if (codexLogin.exitCode !== 0) {
|
|
59193
|
+
blockers.push("Codex OAuth login failed or the codex CLI is not installed.");
|
|
59194
|
+
}
|
|
59195
|
+
blockers.push("Codex OAuth can log in through `codex login`, but Mochi has no Codex OAuth provider runtime yet; choose MiniMax OAuth or OpenAI API key for `mochi talk` today.");
|
|
59196
|
+
}
|
|
59197
|
+
const channelAnswer = await prompt.readLine("Choose chat channel: 1) Telegram bot token 2) Discord bot token 3) None [1]: ");
|
|
59198
|
+
const channel = parseCliOnboardInteractiveChannel(channelAnswer, options.channel);
|
|
59199
|
+
if (!channel) {
|
|
59200
|
+
blockers.push("Unsupported chat channel choice. Choose Telegram, Discord, or none.");
|
|
59201
|
+
}
|
|
59202
|
+
const selectedChannel = channel ?? options.channel;
|
|
59203
|
+
let ownerId = options.ownerId;
|
|
59204
|
+
let telegramUserId = options.telegramUserId;
|
|
59205
|
+
let telegramConfig;
|
|
59206
|
+
let telegramValidation;
|
|
59207
|
+
if (selectedChannel === "telegram") {
|
|
59208
|
+
ownerId = await cliOnboardPromptValue({
|
|
59209
|
+
prompt,
|
|
59210
|
+
question: "Owner ID",
|
|
59211
|
+
defaultValue: ownerId ?? "owner-main"
|
|
59212
|
+
});
|
|
59213
|
+
telegramUserId = await cliOnboardPromptValue({
|
|
59214
|
+
prompt,
|
|
59215
|
+
question: "Telegram numeric user ID",
|
|
59216
|
+
defaultValue: telegramUserId
|
|
59217
|
+
});
|
|
59218
|
+
const botToken = await cliOnboardPromptValue({
|
|
59219
|
+
prompt,
|
|
59220
|
+
question: "Telegram bot token from BotFather",
|
|
59221
|
+
secret: true
|
|
59222
|
+
});
|
|
59223
|
+
if (!ownerId) {
|
|
59224
|
+
blockers.push("Owner ID is required for Telegram.");
|
|
59225
|
+
}
|
|
59226
|
+
if (!telegramUserId) {
|
|
59227
|
+
blockers.push("Telegram numeric user ID is required for Telegram.");
|
|
59228
|
+
}
|
|
59229
|
+
if (!botToken) {
|
|
59230
|
+
blockers.push("Telegram bot token is required.");
|
|
59231
|
+
}
|
|
59232
|
+
if (ownerId && telegramUserId && botToken) {
|
|
59233
|
+
telegramConfig = await createCliConfigurePayload({
|
|
59234
|
+
command: "telegram",
|
|
59235
|
+
workspaceRoot,
|
|
59236
|
+
ownerId,
|
|
59237
|
+
telegramUserId,
|
|
59238
|
+
botTokenRef: "os:mochi/telegram/bot-token",
|
|
59239
|
+
botTokenStdin: true,
|
|
59240
|
+
liveDeliveryEnabled: true,
|
|
59241
|
+
allowedTelegramUserIds: [telegramUserId],
|
|
59242
|
+
now: options.now,
|
|
59243
|
+
format: "json"
|
|
59244
|
+
}, env, cliOnboardConfigureDependencies(dependencies, () => botToken));
|
|
59245
|
+
if (!telegramConfig.ok) {
|
|
59246
|
+
blockers.push("Telegram configure failed; inspect stored secret status and retry.");
|
|
59247
|
+
} else {
|
|
59248
|
+
telegramValidation = await createCliTelegramValidatePayload({
|
|
59249
|
+
workspaceRoot,
|
|
59250
|
+
telegramTokenRef: "os:mochi/telegram/bot-token",
|
|
59251
|
+
now: options.now,
|
|
59252
|
+
format: "json"
|
|
59253
|
+
}, env, cliOnboardTelegramDependencies(dependencies));
|
|
59254
|
+
if (!telegramValidation.ok) {
|
|
59255
|
+
blockers.push(`Telegram validation failed: ${telegramValidation.blockers[0] ?? "Bot API getMe did not validate the token."}`);
|
|
59256
|
+
}
|
|
59257
|
+
}
|
|
59258
|
+
}
|
|
59259
|
+
}
|
|
59260
|
+
if (selectedChannel === "discord") {
|
|
59261
|
+
blockers.push("Discord is a visible onboarding channel choice, but Mochi has no Discord runtime package yet, so no Discord token was accepted or stored.");
|
|
59262
|
+
}
|
|
59263
|
+
const providerChoices = cliOnboardProviderChoices({
|
|
59264
|
+
...options,
|
|
59265
|
+
workspaceRoot,
|
|
59266
|
+
provider: selectedProvider,
|
|
59267
|
+
...typeof model === "string" && model ? { model } : {}
|
|
59268
|
+
});
|
|
59269
|
+
const channelChoices = cliOnboardChannelChoices({
|
|
59270
|
+
...options,
|
|
59271
|
+
workspaceRoot,
|
|
59272
|
+
channel: selectedChannel,
|
|
59273
|
+
...ownerId ? { ownerId } : {},
|
|
59274
|
+
...telegramUserId ? { telegramUserId } : {}
|
|
59275
|
+
});
|
|
59276
|
+
const nextCommands = [
|
|
59277
|
+
...cliOnboardInstallCommands(),
|
|
59278
|
+
...cliOnboardSelectedRuntimeCommands({
|
|
59279
|
+
workspaceRoot,
|
|
59280
|
+
provider: selectedProvider,
|
|
59281
|
+
model: typeof model === "string" && model ? model : "<model>",
|
|
59282
|
+
channel: selectedChannel,
|
|
59283
|
+
...ownerId ? { ownerId } : {},
|
|
59284
|
+
...telegramUserId ? { telegramUserId } : {}
|
|
59285
|
+
})
|
|
59286
|
+
];
|
|
59287
|
+
return {
|
|
59288
|
+
type: "mochi.cli.onboard_first_run",
|
|
59289
|
+
ok: blockers.length === 0,
|
|
59290
|
+
confirmed: true,
|
|
59291
|
+
workspaceRoot,
|
|
59292
|
+
selected: {
|
|
59293
|
+
provider: selectedProvider,
|
|
59294
|
+
channel: selectedChannel,
|
|
59295
|
+
model: typeof model === "string" && model ? model : null
|
|
59296
|
+
},
|
|
59297
|
+
providerChoices,
|
|
59298
|
+
channelChoices,
|
|
59299
|
+
setup: {
|
|
59300
|
+
workspaceSeed,
|
|
59301
|
+
...providerConfig ? { providerConfig } : {},
|
|
59302
|
+
...providerAuth ? { providerAuth } : {},
|
|
59303
|
+
...telegramConfig ? { telegramConfig } : {},
|
|
59304
|
+
...telegramValidation ? { telegramValidation } : {},
|
|
59305
|
+
...codexLogin ? { codexLogin } : {}
|
|
59306
|
+
},
|
|
59307
|
+
sideEffects: {
|
|
59308
|
+
writesWorkspaceFiles: workspaceSeed.sideEffects.writesFiles,
|
|
59309
|
+
writesRuntimeConfig: cliOnboardConfigWrites(providerConfig) || providerAuth?.sideEffects.writesRuntimeConfig === true || cliOnboardConfigWrites(telegramConfig),
|
|
59310
|
+
storesLocalSecrets: cliOnboardStoresSecrets(providerConfig) || providerAuth?.sideEffects.storesLocalSecrets === true || cliOnboardStoresSecrets(telegramConfig),
|
|
59311
|
+
opensBrowser: providerAuth?.sideEffects.opensBrowser === true,
|
|
59312
|
+
startsLocalCallbackServer: providerAuth?.sideEffects.startsLocalCallbackServer === true,
|
|
59313
|
+
runsExternalCodexLogin: codexLogin?.attempted === true,
|
|
59314
|
+
callsProviderTokenEndpoint: providerAuth?.sideEffects.callsProviderTokenEndpoint === true,
|
|
59315
|
+
callsTelegramGetMeEndpoint: telegramValidation?.sideEffects.callsTelegramGetMeEndpoint === true,
|
|
59316
|
+
callsModelProvider: false,
|
|
59317
|
+
pollsTelegram: false,
|
|
59318
|
+
sendsTelegram: false,
|
|
59319
|
+
connectsDiscord: false,
|
|
59320
|
+
connectsGames: false,
|
|
59321
|
+
submitsActions: false,
|
|
59322
|
+
mutatesGameCanon: false,
|
|
59323
|
+
secretsDisplayed: false
|
|
59324
|
+
},
|
|
59325
|
+
blockers,
|
|
59326
|
+
nextCommands: [...new Set(nextCommands)],
|
|
59327
|
+
warnings
|
|
59328
|
+
};
|
|
59329
|
+
}
|
|
58825
59330
|
async function createCliOnboardRootPayload(options, env = process.env, dependencies = {}) {
|
|
59331
|
+
if (cliOnboardShouldRunInteractive(options)) {
|
|
59332
|
+
return createCliOnboardInteractivePayload(options, env, dependencies);
|
|
59333
|
+
}
|
|
58826
59334
|
const blockers = [];
|
|
58827
59335
|
const warnings = [
|
|
58828
59336
|
"Mochi onboard reuses provider auth, configure, proof workspace seed, Telegram, and Gateway runtime surfaces; it does not create parallel setup abstractions.",
|
|
@@ -58920,36 +59428,18 @@ async function createCliOnboardRootPayload(options, env = process.env, dependenc
|
|
|
58920
59428
|
const providerChoice = providerChoices.find((choice) => choice.id === options.provider);
|
|
58921
59429
|
const channelChoice = channelChoices.find((choice) => choice.id === options.channel);
|
|
58922
59430
|
const providerRuntimeImplemented = options.provider !== "codex-oauth";
|
|
58923
|
-
const selectedCredentialRef = providerRuntimeImplemented ? cliOnboardProviderCredentialRef(options.provider) : undefined;
|
|
58924
|
-
const model = cliOnboardModel(options);
|
|
58925
59431
|
const nextCommands = [
|
|
58926
59432
|
...cliOnboardInstallCommands(),
|
|
58927
59433
|
...providerChoice?.nextCommands ?? [],
|
|
58928
59434
|
...channelChoice?.nextCommands ?? [],
|
|
58929
|
-
...
|
|
58930
|
-
|
|
58931
|
-
|
|
58932
|
-
|
|
58933
|
-
|
|
58934
|
-
|
|
58935
|
-
|
|
58936
|
-
|
|
58937
|
-
"--owner <owner-id>",
|
|
58938
|
-
"--telegram-user-id <telegram-user-id>"
|
|
58939
|
-
] : []
|
|
58940
|
-
].join(" "),
|
|
58941
|
-
[
|
|
58942
|
-
"mochi talk",
|
|
58943
|
-
`--workspace-root ${options.workspaceRoot}`,
|
|
58944
|
-
"--game mock-game",
|
|
58945
|
-
`--provider ${options.provider === "minimax-oauth" ? "minimax" : "openai"}`,
|
|
58946
|
-
`--model ${model}`,
|
|
58947
|
-
`--credential-ref ${selectedCredentialRef}`,
|
|
58948
|
-
'--message "Hello Mochi. Answer in one short sentence."'
|
|
58949
|
-
].join(" ")
|
|
58950
|
-
] : [
|
|
58951
|
-
"No Mochi talk proof command exists for Codex OAuth yet; choose minimax-oauth or openai-api-key for the current Mochi runtime."
|
|
58952
|
-
]
|
|
59435
|
+
...cliOnboardSelectedRuntimeCommands({
|
|
59436
|
+
workspaceRoot: options.workspaceRoot,
|
|
59437
|
+
provider: providerRuntimeImplemented ? options.provider : "codex-oauth",
|
|
59438
|
+
model: cliOnboardModel(options),
|
|
59439
|
+
channel: options.channel,
|
|
59440
|
+
...options.ownerId ? { ownerId: options.ownerId } : {},
|
|
59441
|
+
...options.telegramUserId ? { telegramUserId: options.telegramUserId } : {}
|
|
59442
|
+
})
|
|
58953
59443
|
];
|
|
58954
59444
|
const fatalBlockers = blockers.filter((blocker) => blocker.startsWith("Missing ") || blocker.startsWith("Provider configure failed") || blocker.startsWith("Telegram configure failed"));
|
|
58955
59445
|
return {
|
|
@@ -58973,7 +59463,11 @@ async function createCliOnboardRootPayload(options, env = process.env, dependenc
|
|
|
58973
59463
|
writesWorkspaceFiles: workspaceSeed?.sideEffects.writesFiles ?? false,
|
|
58974
59464
|
writesRuntimeConfig: cliOnboardConfigWrites(providerConfig) || cliOnboardConfigWrites(telegramConfig),
|
|
58975
59465
|
storesLocalSecrets: cliOnboardStoresSecrets(providerConfig) || cliOnboardStoresSecrets(telegramConfig),
|
|
59466
|
+
opensBrowser: false,
|
|
59467
|
+
startsLocalCallbackServer: false,
|
|
59468
|
+
runsExternalCodexLogin: false,
|
|
58976
59469
|
callsProviderTokenEndpoint: false,
|
|
59470
|
+
callsTelegramGetMeEndpoint: false,
|
|
58977
59471
|
callsModelProvider: false,
|
|
58978
59472
|
pollsTelegram: false,
|
|
58979
59473
|
sendsTelegram: false,
|
|
@@ -59009,13 +59503,20 @@ function renderCliOnboardRootText(payload) {
|
|
|
59009
59503
|
"configured artifacts:",
|
|
59010
59504
|
`- workspace seed applied: ${payload.setup.workspaceSeed?.mode === "applied"}`,
|
|
59011
59505
|
`- provider config written: ${cliOnboardConfigWrites(payload.setup.providerConfig)}`,
|
|
59506
|
+
`- provider oauth login: ${payload.setup.providerAuth?.ok === true}`,
|
|
59012
59507
|
`- telegram config written: ${cliOnboardConfigWrites(payload.setup.telegramConfig)}`,
|
|
59508
|
+
`- telegram validation: ${payload.setup.telegramValidation ? payload.setup.telegramValidation.ok ? "valid" : "blocked" : "not-run"}`,
|
|
59509
|
+
`- codex login ran: ${payload.setup.codexLogin?.attempted === true}`,
|
|
59013
59510
|
"",
|
|
59014
59511
|
"bounds:",
|
|
59015
59512
|
`- workspace files written: ${payload.sideEffects.writesWorkspaceFiles}`,
|
|
59016
59513
|
`- runtime config written: ${payload.sideEffects.writesRuntimeConfig}`,
|
|
59017
59514
|
`- local secrets stored: ${payload.sideEffects.storesLocalSecrets}`,
|
|
59515
|
+
`- browser opened: ${payload.sideEffects.opensBrowser}`,
|
|
59516
|
+
`- local callback server started: ${payload.sideEffects.startsLocalCallbackServer}`,
|
|
59517
|
+
`- external codex login ran: ${payload.sideEffects.runsExternalCodexLogin}`,
|
|
59018
59518
|
`- provider token endpoint called: ${payload.sideEffects.callsProviderTokenEndpoint}`,
|
|
59519
|
+
`- telegram getMe called: ${payload.sideEffects.callsTelegramGetMeEndpoint}`,
|
|
59019
59520
|
`- model provider called: ${payload.sideEffects.callsModelProvider}`,
|
|
59020
59521
|
`- telegram polled: ${payload.sideEffects.pollsTelegram}`,
|
|
59021
59522
|
`- telegram sent: ${payload.sideEffects.sendsTelegram}`,
|
|
@@ -60060,7 +60561,11 @@ async function runCli(args = Bun.argv.slice(2), writeLine = console.log, env = p
|
|
|
60060
60561
|
}
|
|
60061
60562
|
if (command === "onboard") {
|
|
60062
60563
|
if (!args[1] || args[1].startsWith("--")) {
|
|
60063
|
-
const result = await renderCliOnboardRoot(args.slice(1), env,
|
|
60564
|
+
const result = await renderCliOnboardRoot(args.slice(1), env, {
|
|
60565
|
+
...dependencies.onboard,
|
|
60566
|
+
...dependencies.providerAuth ? { providerAuth: dependencies.providerAuth } : {},
|
|
60567
|
+
...dependencies.telegram ? { telegram: dependencies.telegram } : {}
|
|
60568
|
+
});
|
|
60064
60569
|
writeLine(result.text);
|
|
60065
60570
|
if (result.exitCode !== 0) {
|
|
60066
60571
|
writeLine(renderCliHelp());
|