moshcode 0.24.3 → 0.25.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/bin/moshcode.mjs +9 -1
- package/package.json +3 -3
- package/src/auth.mjs +73 -7
- package/src/cli-schema.mjs +3 -1
- package/src/completion.mjs +4 -4
- package/src/engines.mjs +13 -10
- package/src/tui.mjs +8 -1
package/README.md
CHANGED
|
@@ -76,8 +76,8 @@ use this only in an isolated container, VM, or workspace you trust:
|
|
|
76
76
|
|
|
77
77
|
```sh
|
|
78
78
|
moshcode agents claude # claude agents --dangerously-skip-permissions (agent view)
|
|
79
|
-
moshcode agents opencode # opencode
|
|
80
|
-
moshcode agents privacycode # privacycode
|
|
79
|
+
moshcode agents opencode # opencode --auto (autonomous)
|
|
80
|
+
moshcode agents privacycode # privacycode --auto (autonomous)
|
|
81
81
|
moshcode agents codex # codex --dangerously-bypass-approvals-and-sandbox (autonomous)
|
|
82
82
|
moshcode agents gemini # gemini --approval-mode=yolo (autonomous)
|
|
83
83
|
moshcode agents kimi # kimi --yolo (autonomous)
|
package/bin/moshcode.mjs
CHANGED
|
@@ -546,7 +546,15 @@ async function main() {
|
|
|
546
546
|
} catch (e) { console.error(String(e.message || e)); process.exitCode = 1; }
|
|
547
547
|
return;
|
|
548
548
|
}
|
|
549
|
-
if (cmd === "whoami") {
|
|
549
|
+
if (cmd === "whoami") {
|
|
550
|
+
if (rest.length > 1 || (rest.length === 1 && rest[0] !== "--json")) {
|
|
551
|
+
console.error("usage: moshcode whoami [--json]");
|
|
552
|
+
process.exitCode = 1;
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
await whoami({ json: rest[0] === "--json" });
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
550
558
|
if (cmd === "logout") { logout(); return; }
|
|
551
559
|
if (cmd === "run") {
|
|
552
560
|
let max = 3, dryRun = false;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "moshcode",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "moshcode — a metal wrapper for coding engines and native UGig/CoinPay workflow CLIs, with OpenPRD and moshscript",
|
|
6
6
|
"repository": {
|
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
"url": "https://github.com/moshcoder/moshcode/issues"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"moshcode": "
|
|
16
|
-
"moshscript": "
|
|
15
|
+
"moshcode": "bin/moshcode.mjs",
|
|
16
|
+
"moshscript": "bin/moshscript.mjs"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"start": "node bin/moshcode.mjs",
|
package/src/auth.mjs
CHANGED
|
@@ -167,22 +167,88 @@ export async function loginAuto({ device = false, browser = false } = {}) {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/** Print who is logged in (verified against the app). */
|
|
170
|
-
export async function whoami() {
|
|
170
|
+
export async function whoami({ json = false } = {}) {
|
|
171
171
|
const creds = loadCreds();
|
|
172
|
-
if (!creds?.token) {
|
|
172
|
+
if (!creds?.token) {
|
|
173
|
+
if (json) {
|
|
174
|
+
console.log(JSON.stringify({
|
|
175
|
+
status: "not_logged_in",
|
|
176
|
+
verified: false,
|
|
177
|
+
api: API(),
|
|
178
|
+
user: null,
|
|
179
|
+
}, null, 2));
|
|
180
|
+
} else {
|
|
181
|
+
console.log("not logged in — run: moshcode login");
|
|
182
|
+
}
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
const api = creds.api || API();
|
|
186
|
+
const localUser = {
|
|
187
|
+
id: creds.id ?? null,
|
|
188
|
+
email: creds.email ?? null,
|
|
189
|
+
name: null,
|
|
190
|
+
credits: null,
|
|
191
|
+
};
|
|
192
|
+
const printJson = (value) => console.log(JSON.stringify(value, null, 2));
|
|
173
193
|
try {
|
|
174
|
-
const res = await fetch(`${
|
|
175
|
-
if (res.status === 401) {
|
|
194
|
+
const res = await fetch(`${api}/api/me`, { headers: { authorization: `Bearer ${creds.token}` } });
|
|
195
|
+
if (res.status === 401) {
|
|
196
|
+
if (json) {
|
|
197
|
+
printJson({
|
|
198
|
+
status: "expired",
|
|
199
|
+
verified: false,
|
|
200
|
+
api,
|
|
201
|
+
user: localUser,
|
|
202
|
+
error: { type: "auth", status: 401 },
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
else console.log("session expired — run: moshcode login");
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
176
208
|
// Any other error status still has a body, and it isn't an account — reading
|
|
177
209
|
// it as one prints a made-up identity for a session the app just refused.
|
|
178
210
|
if (!res.ok) {
|
|
179
|
-
|
|
211
|
+
if (json) {
|
|
212
|
+
printJson({
|
|
213
|
+
status: "unverified",
|
|
214
|
+
verified: false,
|
|
215
|
+
api,
|
|
216
|
+
user: localUser,
|
|
217
|
+
error: { type: "http", status: res.status },
|
|
218
|
+
});
|
|
219
|
+
} else {
|
|
220
|
+
console.log(`${creds.email || "logged in"} @ ${api} (couldn't verify — the app returned ${res.status})`);
|
|
221
|
+
}
|
|
180
222
|
return;
|
|
181
223
|
}
|
|
182
224
|
const me = await res.json();
|
|
183
|
-
|
|
225
|
+
if (json) {
|
|
226
|
+
printJson({
|
|
227
|
+
status: "authenticated",
|
|
228
|
+
verified: true,
|
|
229
|
+
api,
|
|
230
|
+
user: {
|
|
231
|
+
id: me.id ?? creds.id ?? null,
|
|
232
|
+
email: me.email ?? creds.email ?? null,
|
|
233
|
+
name: me.name ?? null,
|
|
234
|
+
credits: me.credits ?? null,
|
|
235
|
+
},
|
|
236
|
+
});
|
|
237
|
+
} else {
|
|
238
|
+
console.log(`${me.email || me.name || "moshcoder"} 🤘 (${me.credits ?? "?"} credits) @ ${api}`);
|
|
239
|
+
}
|
|
184
240
|
} catch {
|
|
185
|
-
|
|
241
|
+
if (json) {
|
|
242
|
+
printJson({
|
|
243
|
+
status: "unreachable",
|
|
244
|
+
verified: false,
|
|
245
|
+
api,
|
|
246
|
+
user: localUser,
|
|
247
|
+
error: { type: "network" },
|
|
248
|
+
});
|
|
249
|
+
} else {
|
|
250
|
+
console.log(`${creds.email || "logged in"} @ ${api} (couldn't reach the app to verify)`);
|
|
251
|
+
}
|
|
186
252
|
}
|
|
187
253
|
}
|
|
188
254
|
|
package/src/cli-schema.mjs
CHANGED
|
@@ -161,7 +161,9 @@ export const CORE_CLI_COMMANDS = [
|
|
|
161
161
|
name: "whoami",
|
|
162
162
|
group: "account",
|
|
163
163
|
description: "show the logged-in account",
|
|
164
|
-
synopsis: [["moshcode whoami", ""]],
|
|
164
|
+
synopsis: [["moshcode whoami [--json]", ""]],
|
|
165
|
+
flags: [["--json", "print account status as machine-readable JSON", ""]],
|
|
166
|
+
examples: [["moshcode whoami --json", "inspect the current session from a script"]],
|
|
165
167
|
seeAlso: ["login", "logout"],
|
|
166
168
|
},
|
|
167
169
|
{
|
package/src/completion.mjs
CHANGED
|
@@ -215,7 +215,7 @@ Register-ArgumentCompleter -Native -CommandName moshcode -ScriptBlock {
|
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
'login' { if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionLogin } }
|
|
218
|
-
{ $_ -in @('engines', 'tools', 'commands') } {
|
|
218
|
+
{ $_ -in @('whoami', 'engines', 'tools', 'commands') } {
|
|
219
219
|
if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionJson }
|
|
220
220
|
}
|
|
221
221
|
'run' { if ($wordToComplete.StartsWith('-')) { $choices = $script:MoshcodeCompletionRun } }
|
|
@@ -321,7 +321,7 @@ _moshcode_completion() {
|
|
|
321
321
|
login)
|
|
322
322
|
[[ "$cur" == -* ]] && choices="--browser -b --device -d"
|
|
323
323
|
;;
|
|
324
|
-
engines|tools|commands)
|
|
324
|
+
whoami|engines|tools|commands)
|
|
325
325
|
[[ "$cur" == -* ]] && choices="--json"
|
|
326
326
|
;;
|
|
327
327
|
run)
|
|
@@ -464,7 +464,7 @@ _moshcode() {
|
|
|
464
464
|
login)
|
|
465
465
|
_values "login option" --browser -b --device -d
|
|
466
466
|
;;
|
|
467
|
-
engines|tools|commands)
|
|
467
|
+
whoami|engines|tools|commands)
|
|
468
468
|
_values "option" --json
|
|
469
469
|
;;
|
|
470
470
|
run)
|
|
@@ -556,7 +556,7 @@ complete -c moshcode -n '__moshcode_nested_is mcp list' -l json -d 'print JSON'
|
|
|
556
556
|
complete -c moshcode -n '__moshcode_nested_is skill list; or __moshcode_nested_is skills list' -l json -d 'print JSON'
|
|
557
557
|
complete -c moshcode -n '__moshcode_command_is login' -l browser -s b -d 'use browser authentication'
|
|
558
558
|
complete -c moshcode -n '__moshcode_command_is login' -l device -s d -d 'use device-code authentication'
|
|
559
|
-
complete -c moshcode -n '${atSecondToken("agents engines tools commands")}' -l json -d 'print JSON'
|
|
559
|
+
complete -c moshcode -n '${atSecondToken("agents whoami engines tools commands")}' -l json -d 'print JSON'
|
|
560
560
|
complete -c moshcode -n '__moshcode_command_is run' -l dry-run -d 'show actions without executing'
|
|
561
561
|
complete -c moshcode -n '__moshcode_command_is run' -l max -s n -r -d 'maximum loop count'
|
|
562
562
|
complete -c moshcode -n '__moshcode_command_is uninstall remove' -l yes -s y -d 'confirm deleting a binary'
|
package/src/engines.mjs
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
//
|
|
6
6
|
// `agentsView` (optional) is the exact argv that opens the engine's native
|
|
7
7
|
// agent list/view — used by `/agents <name>` when the engine actually has one
|
|
8
|
-
// (claude
|
|
9
|
-
// subcommand accepts)
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
8
|
+
// (currently claude). It's the FULL leading args (subcommand + any flags that
|
|
9
|
+
// subcommand accepts). Engines without an `agentsView` fall back to
|
|
10
|
+
// `agentArgs` — an autonomous session with native approvals
|
|
11
|
+
// bypassed/auto-approved. Do not use a machine-readable, one-shot list command
|
|
12
|
+
// as an agents view: `/agents` promises to hand the terminal to a live session.
|
|
13
13
|
import { spawn } from "node:child_process";
|
|
14
14
|
import { existsSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
15
15
|
import { homedir, tmpdir } from "node:os";
|
|
@@ -22,17 +22,19 @@ export const ENGINES = {
|
|
|
22
22
|
desc: "opencode — the open-source coding agent (SST/anomalyco)",
|
|
23
23
|
bin: "opencode",
|
|
24
24
|
agentArgs: ["--auto"],
|
|
25
|
-
agentsView: ["agent", "list"], // `opencode agent list` — lists agents; the `agent` subcommand takes no bypass flag
|
|
26
25
|
install: { cmd: "bash", args: ["-c", "curl -fsSL https://opencode.ai/install | bash"] },
|
|
27
26
|
upgrade: { cmd: "opencode", args: ["upgrade"] },
|
|
27
|
+
// The installer appends this directory to a shell profile. The moshcode
|
|
28
|
+
// process that ran it cannot see that PATH change, so search it directly.
|
|
29
|
+
binDirs: [path.join(homedir(), ".opencode", "bin")],
|
|
28
30
|
},
|
|
29
31
|
privacycode: {
|
|
30
32
|
desc: "privacycode — privacy-first coding agent (profullstack)",
|
|
31
33
|
bin: "privacycode",
|
|
32
34
|
// An opencode derivative, so it speaks the same flags/subcommands.
|
|
33
35
|
agentArgs: ["--auto"],
|
|
34
|
-
agentsView: ["agent", "list"],
|
|
35
36
|
install: { cmd: "sh", args: ["-c", "curl -fsSL https://getprivacycode.com/install | sh"] },
|
|
37
|
+
binDirs: [path.join(homedir(), ".privacycode", "bin")],
|
|
36
38
|
// Deliberately no native updater. `privacycode upgrade` is opencode's, and
|
|
37
39
|
// it works out how to update itself by recognising where it was installed —
|
|
38
40
|
// it knows opencode's own locations, not this fork's ~/.privacycode/bin. It
|
|
@@ -263,9 +265,10 @@ export function pickAiEngine(preferred) {
|
|
|
263
265
|
|
|
264
266
|
/** Engine entries annotated with install status. */
|
|
265
267
|
export function engineStatus() {
|
|
266
|
-
// Search each engine's own install dir as well as PATH —
|
|
267
|
-
//
|
|
268
|
-
// the very session that installed
|
|
268
|
+
// Search each engine's own install dir as well as PATH — several curl-based
|
|
269
|
+
// installers only add their bin directory to a shell rc, so PATH alone
|
|
270
|
+
// reports them missing in the very session that installed them. (Inert for
|
|
271
|
+
// engines without binDirs.)
|
|
269
272
|
return Object.entries(ENGINES).map(([key, e]) => ({ key, ...e, installed: isInstalled(e.bin, e.binDirs) }));
|
|
270
273
|
}
|
|
271
274
|
|
package/src/tui.mjs
CHANGED
|
@@ -539,7 +539,14 @@ export async function tui() {
|
|
|
539
539
|
catch (e) { console.log(err(String(e.message || e))); }
|
|
540
540
|
continue;
|
|
541
541
|
}
|
|
542
|
-
if (cmd === "whoami") {
|
|
542
|
+
if (cmd === "whoami") {
|
|
543
|
+
if (rest.length > 1 || (rest.length === 1 && rest[0] !== "--json")) {
|
|
544
|
+
console.log(err("usage: /whoami [--json]"));
|
|
545
|
+
continue;
|
|
546
|
+
}
|
|
547
|
+
await whoami({ json: rest[0] === "--json" });
|
|
548
|
+
continue;
|
|
549
|
+
}
|
|
543
550
|
if (cmd === "logout") { logout(); continue; }
|
|
544
551
|
if (cmd === "run") {
|
|
545
552
|
await runFile(rest);
|