@wix/himalaya-cli 0.1118.0 → 0.1120.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/cli.mjs +73 -5
- package/guides/himi-mcp.md +3 -1
- package/package.json +2 -2
package/dist/cli.mjs
CHANGED
|
@@ -6762,7 +6762,6 @@ function walk(node, registry, path2, out2) {
|
|
|
6762
6762
|
var SYSTEM_FONT_FAMILY, TONAL_ELEVATION_ALPHA;
|
|
6763
6763
|
var init_tokens = __esm({
|
|
6764
6764
|
"../../core/ts/src/tokens.ts"() {
|
|
6765
|
-
"use strict";
|
|
6766
6765
|
SYSTEM_FONT_FAMILY = "$system";
|
|
6767
6766
|
TONAL_ELEVATION_ALPHA = [0, 0.05, 0.08, 0.11, 0.12, 0.14];
|
|
6768
6767
|
}
|
|
@@ -49227,6 +49226,7 @@ function readInitWatch(dir) {
|
|
|
49227
49226
|
const r = JSON.parse(readFileSync52(file, "utf8"));
|
|
49228
49227
|
if (r.v !== 1 || typeof r.pid !== "number" || !Number.isInteger(r.pid) || r.pid < 1) return null;
|
|
49229
49228
|
if (typeof r.url !== "string" || !/^http:\/\/127\.0\.0\.1:\d+\//.test(r.url) || typeof r.board !== "string" || typeof r.log !== "string" || typeof r.startedAt !== "string") return null;
|
|
49229
|
+
if (r.root !== runRootId(dir)) return null;
|
|
49230
49230
|
return r;
|
|
49231
49231
|
} catch {
|
|
49232
49232
|
return null;
|
|
@@ -49324,7 +49324,7 @@ async function startWatchAtInit(dir, opts) {
|
|
|
49324
49324
|
});
|
|
49325
49325
|
child.unref();
|
|
49326
49326
|
if (!child.pid) return { skipped: "the live preview did not start (no process) \u2014 start it yourself: `himi run --watch --content <dir> &`" };
|
|
49327
|
-
const record2 = { v: 1, pid: child.pid, url, board, log: WATCH_LOG, startedAt: now.toISOString() };
|
|
49327
|
+
const record2 = { v: 1, pid: child.pid, root: runRootId(dir), url, board, log: WATCH_LOG, startedAt: now.toISOString() };
|
|
49328
49328
|
if (realDirIn(dir, ".himi")) writeFileAtomic(join46(dir, INIT_WATCH_FILE), `${JSON.stringify(record2, null, 2)}
|
|
49329
49329
|
`);
|
|
49330
49330
|
return { started: true, pid: child.pid, url, board, log: WATCH_LOG };
|
|
@@ -49384,6 +49384,7 @@ var init_milestones = __esm({
|
|
|
49384
49384
|
"src/milestones.ts"() {
|
|
49385
49385
|
init_app_source();
|
|
49386
49386
|
init_preview();
|
|
49387
|
+
init_run_identity();
|
|
49387
49388
|
init_progress();
|
|
49388
49389
|
init_shell_quote();
|
|
49389
49390
|
init_studio_reel();
|
|
@@ -54035,6 +54036,15 @@ function symlinkComponent(base, abs) {
|
|
|
54035
54036
|
}
|
|
54036
54037
|
return void 0;
|
|
54037
54038
|
}
|
|
54039
|
+
function workspaceRefusal(root, target) {
|
|
54040
|
+
const r = resolve45(root);
|
|
54041
|
+
const t = resolve45(r, target);
|
|
54042
|
+
if (!existsSync54(r)) return `the workspace folder ${r} does not exist`;
|
|
54043
|
+
if (!within(r, t) || !within(realpathSync7(r), realish(t))) return `"${target}" is outside the workspace folder ${r}`;
|
|
54044
|
+
const link = symlinkComponent(r, t);
|
|
54045
|
+
if (link) return `"${link}" is a symlink \u2014 paths must stay in real folders inside the workspace`;
|
|
54046
|
+
return null;
|
|
54047
|
+
}
|
|
54038
54048
|
async function confinedAppDir(args, deps) {
|
|
54039
54049
|
const root = resolve45(await deps.defaultDir());
|
|
54040
54050
|
const dir = typeof args.dir === "string" && args.dir ? resolve45(root, args.dir) : root;
|
|
@@ -54305,6 +54315,15 @@ function guarded(h) {
|
|
|
54305
54315
|
return async (args, deps) => {
|
|
54306
54316
|
const bad2 = flagShapedInputs(args);
|
|
54307
54317
|
if (bad2.length) return text6(`refused: ${bad2.join(", ")} may not start with "-" (it would be read as a himi flag)`, true);
|
|
54318
|
+
if (deps.workspaceBoundary) {
|
|
54319
|
+
const base = await deps.defaultDir();
|
|
54320
|
+
for (const k of PATH_ARGS) {
|
|
54321
|
+
const v = args[k];
|
|
54322
|
+
if (typeof v !== "string" || !v) continue;
|
|
54323
|
+
const why = workspaceRefusal(deps.workspaceBoundary, resolve46(base, v));
|
|
54324
|
+
if (why) return text6(`refused: ${k} ${why}`, true);
|
|
54325
|
+
}
|
|
54326
|
+
}
|
|
54308
54327
|
return h(args, deps);
|
|
54309
54328
|
};
|
|
54310
54329
|
}
|
|
@@ -54557,7 +54576,7 @@ ${log}` : ""}`, true);
|
|
|
54557
54576
|
}
|
|
54558
54577
|
];
|
|
54559
54578
|
}
|
|
54560
|
-
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT;
|
|
54579
|
+
var MAX_TEXT2, clip, text6, json3, opt, sw, DIR2, LEARN, CHECK, LOCAL_WRITE, PUBLISH, PREVIEW_HINT, LOGIN_HINT, PATH_ARGS;
|
|
54561
54580
|
var init_tools = __esm({
|
|
54562
54581
|
"src/mcp/tools.ts"() {
|
|
54563
54582
|
init_file_tools();
|
|
@@ -54575,6 +54594,7 @@ var init_tools = __esm({
|
|
|
54575
54594
|
PUBLISH = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
54576
54595
|
PREVIEW_HINT = "The preview is already running: open `url` in your built-in browser \u2014 Claude Code desktop's browser pane, Cursor's Browser tool, the Browser in Codex inside the ChatGPT desktop app, VS Code's integrated browser. Do not also start the `himi-preview` launch configuration: it serves the same port, and is the way to start a preview only when none is running. A terminal-only agent should show the owner `himi_render` PNGs instead. `board` (when present) is the build board on the same origin.";
|
|
54577
54596
|
LOGIN_HINT = "Not signed in to the himi serve plane. Call himi_login: it opens a browser window where the user signs in to Wix (this server never sees the credential). A user with a terminal can run `himi login --browser` instead. Then retry.";
|
|
54597
|
+
PATH_ARGS = ["dir", "parentDir", "file"];
|
|
54578
54598
|
}
|
|
54579
54599
|
});
|
|
54580
54600
|
|
|
@@ -54715,7 +54735,8 @@ async function startMcpServer(opts) {
|
|
|
54715
54735
|
stop: (dir) => stopPreview(dir, previewDeps)
|
|
54716
54736
|
},
|
|
54717
54737
|
readFile: (p) => readFileSync60(p),
|
|
54718
|
-
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login })
|
|
54738
|
+
login: createLoginSession({ ...defaultLoginDeps, selfCommand: previewDeps.selfCommand, ...opts.login }),
|
|
54739
|
+
...opts.workspace ? { workspaceBoundary: opts.workspace } : {}
|
|
54719
54740
|
};
|
|
54720
54741
|
const closed = new Promise((resolve54) => {
|
|
54721
54742
|
stdin.once("end", resolve54);
|
|
@@ -57667,6 +57688,7 @@ __export(run_watch_exports, {
|
|
|
57667
57688
|
isEmptyDiff: () => isEmptyDiff,
|
|
57668
57689
|
rebuildBlocker: () => rebuildBlocker,
|
|
57669
57690
|
reloadEvents: () => reloadEvents,
|
|
57691
|
+
removeInitWatchRecord: () => removeInitWatchRecord,
|
|
57670
57692
|
removeRunRecord: () => removeRunRecord,
|
|
57671
57693
|
serialize: () => serialize,
|
|
57672
57694
|
watchContent: () => watchContent,
|
|
@@ -57836,6 +57858,24 @@ function removeRunRecord(dir, owner) {
|
|
|
57836
57858
|
}
|
|
57837
57859
|
rmSync15(join59(root, "run.json"), { force: true });
|
|
57838
57860
|
}
|
|
57861
|
+
function removeInitWatchRecord(dir, owner) {
|
|
57862
|
+
const root = join59(dir, ".himi");
|
|
57863
|
+
try {
|
|
57864
|
+
if (!lstatSync13(root).isDirectory()) return;
|
|
57865
|
+
} catch {
|
|
57866
|
+
return;
|
|
57867
|
+
}
|
|
57868
|
+
const bytes2 = readConfined(root, "watch.json");
|
|
57869
|
+
if (!bytes2) return;
|
|
57870
|
+
let pid;
|
|
57871
|
+
try {
|
|
57872
|
+
pid = JSON.parse(bytes2.toString("utf8")).pid;
|
|
57873
|
+
} catch {
|
|
57874
|
+
return;
|
|
57875
|
+
}
|
|
57876
|
+
if (pid !== owner) return;
|
|
57877
|
+
rmSync15(join59(root, "watch.json"), { force: true });
|
|
57878
|
+
}
|
|
57839
57879
|
function boardFile(dir, pathname) {
|
|
57840
57880
|
if (pathname === RUN_IDENTITY_PATH) {
|
|
57841
57881
|
return new Response(JSON.stringify(runIdentity(dir)), { status: 200, headers: { "content-type": "application/json", "cache-control": "no-store" } });
|
|
@@ -77537,9 +77577,30 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77537
77577
|
let browserCopy = null;
|
|
77538
77578
|
let servedMissing = [];
|
|
77539
77579
|
const fromContent = !source;
|
|
77580
|
+
let dropEarlySignals;
|
|
77581
|
+
let dropInitRecord;
|
|
77540
77582
|
try {
|
|
77541
77583
|
if (!source) {
|
|
77542
77584
|
const dir2 = contentDir(flags);
|
|
77585
|
+
if (watch2) {
|
|
77586
|
+
const { removeInitWatchRecord: removeInitWatchRecord2 } = await Promise.resolve().then(() => (init_run_watch(), run_watch_exports));
|
|
77587
|
+
dropInitRecord = () => removeInitWatchRecord2(dir2, process.pid);
|
|
77588
|
+
const onExit = () => dropInitRecord?.();
|
|
77589
|
+
process.once("exit", onExit);
|
|
77590
|
+
const early = [["SIGINT", 130], ["SIGTERM", 143], ["SIGHUP", 129]].map(([sig, code]) => {
|
|
77591
|
+
const onEarly = () => {
|
|
77592
|
+
dropInitRecord?.();
|
|
77593
|
+
process.exit(code);
|
|
77594
|
+
};
|
|
77595
|
+
process.once(sig, onEarly);
|
|
77596
|
+
return [sig, onEarly];
|
|
77597
|
+
});
|
|
77598
|
+
dropEarlySignals = () => {
|
|
77599
|
+
for (const [sig, onEarly] of early) process.removeListener(sig, onEarly);
|
|
77600
|
+
process.removeListener("exit", onExit);
|
|
77601
|
+
dropEarlySignals = void 0;
|
|
77602
|
+
};
|
|
77603
|
+
}
|
|
77543
77604
|
const app = await appId(dir2);
|
|
77544
77605
|
const { buildContentBundles: buildContentBundles2, buildReleaseFromContent: buildReleaseFromContent2, bundleOutDir: bundleOutDir2 } = await loadAuthoring();
|
|
77545
77606
|
const bres = await buildContentBundles2(dir2, { resolution: resolutionFlag(flags) });
|
|
@@ -77573,7 +77634,10 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77573
77634
|
let startedAt = "";
|
|
77574
77635
|
const record2 = (served2, build2) => {
|
|
77575
77636
|
try {
|
|
77576
|
-
if (recordKit?.writeRunRecord(dir, { url: served2.url, port: served2.port, ...served2.lanUrl ? { lanUrl: served2.lanUrl } : {}, pid: process.pid, startedAt, watching: watch2, build: build2 }))
|
|
77637
|
+
if (recordKit?.writeRunRecord(dir, { url: served2.url, port: served2.port, ...served2.lanUrl ? { lanUrl: served2.lanUrl } : {}, pid: process.pid, startedAt, watching: watch2, build: build2 })) {
|
|
77638
|
+
recorded = true;
|
|
77639
|
+
if (watch2) recordKit.removeInitWatchRecord(dir, process.pid);
|
|
77640
|
+
}
|
|
77577
77641
|
return null;
|
|
77578
77642
|
} catch (e) {
|
|
77579
77643
|
return e.message;
|
|
@@ -77610,6 +77674,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77610
77674
|
const stop = () => {
|
|
77611
77675
|
void retract().catch((e) => io.error(JSON.stringify({ run: "stop_cleanup_failed", message: e.message }))).finally(() => run2.close().finally(() => resolve54()));
|
|
77612
77676
|
};
|
|
77677
|
+
dropEarlySignals?.();
|
|
77613
77678
|
process.once("SIGINT", stop);
|
|
77614
77679
|
process.once("SIGTERM", stop);
|
|
77615
77680
|
});
|
|
@@ -77755,6 +77820,7 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77755
77820
|
}
|
|
77756
77821
|
};
|
|
77757
77822
|
const onSignal = () => void stop();
|
|
77823
|
+
dropEarlySignals?.();
|
|
77758
77824
|
for (const sig of ["SIGINT", "SIGTERM", "SIGHUP"]) process.once(sig, onSignal);
|
|
77759
77825
|
stopNow = (why) => void stop(why);
|
|
77760
77826
|
armIdle();
|
|
@@ -77764,6 +77830,8 @@ default (no --glyph): ${DEFAULT_GLYPH2} \u2014 a mark that claims nothing, so th
|
|
|
77764
77830
|
io.error(JSON.stringify({ error: e.message }));
|
|
77765
77831
|
return 1;
|
|
77766
77832
|
} finally {
|
|
77833
|
+
dropEarlySignals?.();
|
|
77834
|
+
dropInitRecord?.();
|
|
77767
77835
|
if (temp) rmSync16(temp, { recursive: true, force: true });
|
|
77768
77836
|
if (served) rmSync16(served, { recursive: true, force: true });
|
|
77769
77837
|
if (browserCopy) rmSync16(browserCopy, { recursive: true, force: true });
|
package/guides/himi-mcp.md
CHANGED
|
@@ -90,7 +90,9 @@ without following links. They judge the deny-list in every spelling, because mac
|
|
|
90
90
|
write or delete anything the source deny-list keeps off the machine: `.env` files, the `.himi/`
|
|
91
91
|
secret store, MCP host configs with their keys, key files, and `node_modules`, `dist` and `.git`
|
|
92
92
|
at any depth. When the host names
|
|
93
|
-
no workspace, `HIMI_WORKSPACE` sets the folder.
|
|
93
|
+
no workspace, `HIMI_WORKSPACE` sets the folder. It is then a hard boundary for EVERY tool: a
|
|
94
|
+
`dir`, `parentDir` or `file` argument outside it, or through a symlink, is refused. That covers the
|
|
95
|
+
publish and share tools, not only the file tools. Coding agents edit files themselves, so the flag is
|
|
94
96
|
off by default.
|
|
95
97
|
|
|
96
98
|
**What the tools will not do:** make a release live, build store binaries, touch secrets, write to a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1120.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"artifactId": "himalaya-cli"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"falconPackageHash": "
|
|
70
|
+
"falconPackageHash": "98cf64fc20ceea962129bd83a948d2491f2a9672af068c757d9ca1d3"
|
|
71
71
|
}
|