@imfusion/web-ui 0.10.1-dev.37.g9147f90f → 0.10.1-dev.41.g467e0e1a

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.
@@ -1,8 +1,12 @@
1
1
  import { Plugin, UserConfig } from 'vite';
2
- /** Returns `undefined` for an installed package; only a checkout outside `node_modules` needs the config. */
2
+ /**
3
+ * Returns `undefined` for an installed package that `web-ui link` has not claimed. A linked package is excluded from
4
+ * dependency pre-bundling so its rebuilt files are served directly. A checkout outside `node_modules` gets peer dedupe.
5
+ */
3
6
  export declare function localWebUILinkConfig(root: string): UserConfig | undefined;
4
7
  /**
5
- * Lets a consumer link a local checkout (`"@imfusion/web-ui": "file:../web-ui"`) without loading two copies of React in
6
- * client dev and build. SSR is not covered. Does nothing for an installed package, so it can stay registered.
8
+ * Lets a consumer keep `localWebUILink()` registered for good. With no link it does nothing for an installed package.
9
+ * After `npx web-ui link <checkout>` it serves the linked build and reloads the page on each rebuild. Server rendering
10
+ * is not covered.
7
11
  */
8
12
  export declare function localWebUILink(): Plugin;
package/dist/vite.js CHANGED
@@ -1,34 +1,34 @@
1
- import { n as e } from "./paths-B5Ht3ETc.js";
2
- import { readFileSync as t, readdirSync as n, realpathSync as r } from "node:fs";
3
- import { dirname as i, join as a, resolve as o, sep as s } from "node:path";
4
- import { fileURLToPath as c } from "node:url";
1
+ import { n as e, s as t } from "./paths-CZtwNknt.js";
2
+ import { existsSync as n, readFileSync as r, readdirSync as i, realpathSync as a, statSync as o, watch as s } from "node:fs";
3
+ import { dirname as c, join as l, resolve as u, sep as d } from "node:path";
4
+ import { fileURLToPath as f } from "node:url";
5
5
  //#region src/vite/brand-assets.ts
6
- var l = i(c(import.meta.resolve("@imfusion/web-ui/assets/favicon/favicon.svg"))), u = n(l).map((e) => ({
6
+ var p = c(f(import.meta.resolve("@imfusion/web-ui/assets/favicon/favicon.svg"))), m = i(p).map((e) => ({
7
7
  name: e,
8
- source: t(a(l, e))
9
- })), d = {
8
+ source: r(l(p, e))
9
+ })), h = {
10
10
  ".ico": "image/x-icon",
11
11
  ".png": "image/png",
12
12
  ".svg": "image/svg+xml"
13
13
  };
14
- function f(e) {
15
- return d[e.slice(e.lastIndexOf("."))] ?? "application/octet-stream";
14
+ function g(e) {
15
+ return h[e.slice(e.lastIndexOf("."))] ?? "application/octet-stream";
16
16
  }
17
- function p() {
17
+ function _() {
18
18
  return {
19
19
  name: "imf-ui:brand-assets",
20
20
  configureServer(e) {
21
21
  e.middlewares.use((e, t, n) => {
22
- let r = u.find(({ name: t }) => e.url?.split("?")[0] === `/${t}`);
22
+ let r = m.find(({ name: t }) => e.url?.split("?")[0] === `/${t}`);
23
23
  if (!r) {
24
24
  n();
25
25
  return;
26
26
  }
27
- t.setHeader("Content-Type", f(r.name)), t.end(r.source);
27
+ t.setHeader("Content-Type", g(r.name)), t.end(r.source);
28
28
  });
29
29
  },
30
30
  generateBundle() {
31
- for (let e of u) this.emitFile({
31
+ for (let e of m) this.emitFile({
32
32
  fileName: e.name,
33
33
  source: e.source,
34
34
  type: "asset"
@@ -38,33 +38,49 @@ function p() {
38
38
  }
39
39
  //#endregion
40
40
  //#region src/vite/local-web-ui-link.ts
41
- function m(e) {
42
- if (r(e).split(s).includes("node_modules")) return;
43
- let n = JSON.parse(t(o(e, "package.json"), "utf-8")), i = typeof n == "object" && n ? Reflect.get(n, "peerDependencies") : {};
41
+ function v(e) {
42
+ if (t(e)) return { optimizeDeps: {
43
+ exclude: ["@imfusion/web-ui"],
44
+ include: ["use-sync-external-store/shim", "use-sync-external-store/shim/with-selector"]
45
+ } };
46
+ if (a(e).split(d).includes("node_modules")) return;
47
+ let n = JSON.parse(r(u(e, "package.json"), "utf-8")), i = typeof n == "object" && n ? Reflect.get(n, "peerDependencies") : {};
44
48
  if (typeof i != "object" || !i) throw Error(`${e}/package.json has no peerDependencies`);
45
49
  return { resolve: { dedupe: Object.keys(i) } };
46
50
  }
47
- function h() {
51
+ function y() {
48
52
  return {
49
53
  name: "imf-ui:local-web-ui-link",
50
- config: () => m(e)
54
+ config: () => v(e),
55
+ configureServer(r) {
56
+ if (!t(e)) return;
57
+ let i = u(e, "dist"), a = /* @__PURE__ */ new Set(), c, l = s(i, { recursive: !0 }, (e, t) => {
58
+ t && a.add(u(i, t)), clearTimeout(c), c = setTimeout(() => {
59
+ for (let e of a) n(e) && o(e).isFile() && r.watcher.emit("change", e);
60
+ a.clear();
61
+ }, 100);
62
+ });
63
+ r.httpServer?.once("close", () => {
64
+ clearTimeout(c), l.close();
65
+ });
66
+ }
51
67
  };
52
68
  }
53
69
  //#endregion
54
70
  //#region src/vite/readable-css-module-names.ts
55
- function g(e, t) {
71
+ function b(e, t) {
56
72
  let { lightningcss: n, modules: r, transformer: i } = e.css ?? {}, a = n?.cssModules;
57
73
  if (typeof a != "boolean" && r !== !1 && !a?.pattern && !(typeof r == "object" && r.generateScopedName)) return i === "postcss" ? { css: { modules: { generateScopedName: t } } } : { css: {
58
74
  transformer: "lightningcss",
59
75
  lightningcss: { cssModules: { pattern: t } }
60
76
  } };
61
77
  }
62
- function _({ prefix: e }) {
78
+ function x({ prefix: e }) {
63
79
  let t = `${e}-[name]-[local]`;
64
80
  return {
65
81
  name: "imf-ui:readable-css-module-names",
66
- config: (e) => g(e, t)
82
+ config: (e) => b(e, t)
67
83
  };
68
84
  }
69
85
  //#endregion
70
- export { p as imfusionBrandAssets, h as localWebUILink, _ as readableCssModuleNames };
86
+ export { _ as imfusionBrandAssets, y as localWebUILink, x as readableCssModuleNames };
@@ -1,10 +1,10 @@
1
1
  #!/usr/bin/env node
2
- import { n as e, r as t, t as n } from "./paths-B5Ht3ETc.js";
3
- import { chmodSync as r, cpSync as i, existsSync as a, lstatSync as o, mkdirSync as s, readFileSync as c, readdirSync as l, readlinkSync as u, realpathSync as d, rmSync as f, symlinkSync as p, writeFileSync as m } from "node:fs";
4
- import { dirname as h, relative as g, resolve as _ } from "node:path";
5
- import { Command as ee, Option as te } from "commander";
6
- import * as v from "@clack/prompts";
7
- var y = {
2
+ import { a as e, c as t, i as n, n as r, o as i, r as a, t as o } from "./paths-CZtwNknt.js";
3
+ import { chmodSync as s, cpSync as c, existsSync as l, lstatSync as u, mkdirSync as d, readFileSync as f, readdirSync as p, readlinkSync as ee, realpathSync as m, rmSync as h, symlinkSync as te, writeFileSync as g } from "node:fs";
4
+ import { dirname as ne, relative as _, resolve as v } from "node:path";
5
+ import { Command as re, Option as ie } from "commander";
6
+ import * as y from "@clack/prompts";
7
+ var b = {
8
8
  harnesses: {
9
9
  claude: {
10
10
  label: "Claude Code",
@@ -24,91 +24,91 @@ var y = {
24
24
  skillsDir: ".agents/skills",
25
25
  linkDir: ".claude/skills",
26
26
  versionMarker: ".imf-web-ui-skill-version.json"
27
- }, ne = `<!-- ${y.namespace}:begin`, b = `<!-- ${y.namespace}:end -->`, re = _(e, y.templatesDir, "AGENTS.md"), x = _(t, "AGENTS.md");
28
- function S(e) {
29
- let t = e.indexOf(ne), n = e.indexOf(b);
30
- return t === -1 || n === -1 ? null : e.slice(t, n + b.length);
27
+ }, ae = `<!-- ${b.namespace}:begin`, x = `<!-- ${b.namespace}:end -->`, oe = v(r, b.templatesDir, "AGENTS.md"), S = v(a, "AGENTS.md");
28
+ function C(e) {
29
+ let t = e.indexOf(ae), n = e.indexOf(x);
30
+ return t === -1 || n === -1 ? null : e.slice(t, n + x.length);
31
31
  }
32
- function ie() {
33
- if (!a(x)) return "absent";
34
- let e = S(c(re, "utf-8"));
32
+ function se() {
33
+ if (!l(S)) return "absent";
34
+ let e = C(f(oe, "utf-8"));
35
35
  if (!e) return "absent";
36
- let t = c(x, "utf-8"), n = S(t), r = n ? t.replace(n, e) : `${t.trimEnd()}\n\n${e}\n`;
37
- return r === t ? "unchanged" : (m(x, r), n ? "updated" : "added");
36
+ let t = f(S, "utf-8"), n = C(t), r = n ? t.replace(n, e) : `${t.trimEnd()}\n\n${e}\n`;
37
+ return r === t ? "unchanged" : (g(S, r), n ? "updated" : "added");
38
38
  }
39
39
  //#endregion
40
40
  //#region src/cli/skills.ts
41
- var C = Object.keys(y.harnesses).filter((e) => e in y.harnesses), w = [...C, "all"];
41
+ var w = Object.keys(b.harnesses).filter((e) => e in b.harnesses), ce = [...w, "all"];
42
42
  function T(e) {
43
- return e === "all" ? C : [e];
43
+ return e === "all" ? w : [e];
44
44
  }
45
45
  function E(e) {
46
- return `./${g(t, e)}`;
46
+ return `./${_(a, e)}`;
47
47
  }
48
- var D = y.namespace, O = y.versionMarker, k = _(e, y.skillsSource), A = _(t, y.skillsDir), j = _(t, y.linkDir), M = class extends Error {}, N = JSON.parse(c(_(e, "package.json"), "utf-8"));
49
- if (typeof N != "object" || !N || !("version" in N) || typeof N.version != "string") throw Error(`${_(e, "package.json")} has no string "version" field`);
48
+ var D = b.namespace, O = b.versionMarker, k = v(r, b.skillsSource), A = v(a, b.skillsDir), j = v(a, b.linkDir), M = class extends Error {}, N = JSON.parse(f(v(r, "package.json"), "utf-8"));
49
+ if (typeof N != "object" || !N || !("version" in N) || typeof N.version != "string") throw Error(`${v(r, "package.json")} has no string "version" field`);
50
50
  var P = N.version;
51
51
  function F(e) {
52
52
  return e === D || e.startsWith(`${D}-`);
53
53
  }
54
54
  function I() {
55
- return a(k) ? l(k, { withFileTypes: !0 }).filter((e) => e.isDirectory() && F(e.name)).map((e) => e.name).sort() : [];
55
+ return l(k) ? p(k, { withFileTypes: !0 }).filter((e) => e.isDirectory() && F(e.name)).map((e) => e.name).sort() : [];
56
56
  }
57
- function ae(e) {
58
- let t = _(A, e, O);
59
- if (!a(t)) return null;
57
+ function le(e) {
58
+ let t = v(A, e, O);
59
+ if (!l(t)) return null;
60
60
  try {
61
- let e = JSON.parse(c(t, "utf-8"));
61
+ let e = JSON.parse(f(t, "utf-8"));
62
62
  if (typeof e != "object" || !e) return null;
63
63
  let n = "harnesses" in e && Array.isArray(e.harnesses) ? e.harnesses : null;
64
- return n ? C.filter((e) => n.includes(e)) : null;
64
+ return n ? w.filter((e) => n.includes(e)) : null;
65
65
  } catch {
66
66
  return null;
67
67
  }
68
68
  }
69
69
  function L(e) {
70
70
  for (let t of e) {
71
- let e = ae(t);
71
+ let e = le(t);
72
72
  if (e && e.length > 0) return e;
73
73
  }
74
74
  return null;
75
75
  }
76
76
  function R(e, t, n) {
77
- if (a(e)) for (let r of l(e).filter(F)) t.has(r) || (f(_(e, r), {
77
+ if (l(e)) for (let r of p(e).filter(F)) t.has(r) || (h(v(e, r), {
78
78
  recursive: !0,
79
79
  force: !0
80
- }), v.log.info(`Removed skill: ${r} (${n})`));
80
+ }), y.log.info(`Removed skill: ${r} (${n})`));
81
81
  }
82
- function oe() {
83
- return a(j) && a(A) && d(j) === d(A);
82
+ function ue() {
83
+ return l(j) && l(A) && m(j) === m(A);
84
84
  }
85
- function z(e) {
86
- let t = _(j, e), n = g(j, _(A, e)), r = o(t, { throwIfNoEntry: !1 });
87
- r?.isSymbolicLink() && u(t) === n || (r && f(t, {
85
+ function de(e) {
86
+ let t = v(j, e), n = _(j, v(A, e)), r = u(t, { throwIfNoEntry: !1 });
87
+ r?.isSymbolicLink() && ee(t) === n || (r && h(t, {
88
88
  recursive: !0,
89
89
  force: !0
90
- }), s(j, { recursive: !0 }), p(n, t));
90
+ }), d(j, { recursive: !0 }), te(n, t));
91
91
  }
92
- function se(e, t) {
92
+ function fe(e, t) {
93
93
  try {
94
- s(A, { recursive: !0 });
95
- let r = [];
96
- for (let n of e) {
97
- let e = _(A, n);
98
- f(e, {
94
+ d(A, { recursive: !0 });
95
+ let n = [];
96
+ for (let r of e) {
97
+ let e = v(A, r);
98
+ h(e, {
99
99
  recursive: !0,
100
100
  force: !0
101
- }), i(_(k, n), e, { recursive: !0 });
102
- let a = _(e, O);
103
- m(a, JSON.stringify({
101
+ }), c(v(k, r), e, { recursive: !0 });
102
+ let i = v(e, O);
103
+ g(i, JSON.stringify({
104
104
  version: P,
105
105
  harnesses: t
106
- }, null, 2) + "\n"), r.push(a);
106
+ }, null, 2) + "\n"), n.push(i);
107
107
  }
108
- if (n(r), R(A, new Set(e), "no longer in this bundle"), v.log.success(`Skills -> ${E(A)}/${D}*`), oe()) return;
108
+ if (o(n), R(A, new Set(e), "no longer in this bundle"), y.log.success(`Skills -> ${E(A)}/${D}*`), ue()) return;
109
109
  if (t.includes("claude")) {
110
- for (let t of e) z(t);
111
- R(j, new Set(e), "no longer in this bundle"), v.log.success(`Claude Code -> ${E(j)}/${D}* (symlinks -> ${E(A)})`);
110
+ for (let t of e) de(t);
111
+ R(j, new Set(e), "no longer in this bundle"), y.log.success(`Claude Code -> ${E(j)}/${D}* (symlinks -> ${E(A)})`);
112
112
  } else R(j, /* @__PURE__ */ new Set(), "claude not selected");
113
113
  } catch (e) {
114
114
  throw e instanceof Error ? new M(e.message) : e;
@@ -116,68 +116,68 @@ function se(e, t) {
116
116
  }
117
117
  //#endregion
118
118
  //#region src/cli/hooks.ts
119
- var B = _(e, y.templatesDir), V = _(B, "hooks"), H = _(t, y.hooksDir), U = class extends Error {};
120
- function ce(e, t) {
121
- if (typeof e != "object" || !e || Array.isArray(e)) throw new U(`${t} is not a JSON object.`);
119
+ var z = v(r, b.templatesDir), B = v(z, "hooks"), V = v(a, b.hooksDir), H = class extends Error {};
120
+ function pe(e, t) {
121
+ if (typeof e != "object" || !e || Array.isArray(e)) throw new H(`${t} is not a JSON object.`);
122
122
  let n = { ...e };
123
123
  if ("hooks" in n) {
124
- if (typeof n.hooks != "object" || n.hooks === null || Array.isArray(n.hooks)) throw new U(`${t}: "hooks" is not a JSON object.`);
125
- for (let [e, r] of Object.entries(n.hooks)) if (!Array.isArray(r)) throw new U(`${t}: "hooks.${e}" is not a JSON array.`);
124
+ if (typeof n.hooks != "object" || n.hooks === null || Array.isArray(n.hooks)) throw new H(`${t}: "hooks" is not a JSON object.`);
125
+ for (let [e, r] of Object.entries(n.hooks)) if (!Array.isArray(r)) throw new H(`${t}: "hooks.${e}" is not a JSON array.`);
126
126
  }
127
127
  return n;
128
128
  }
129
- function W(e) {
129
+ function U(e) {
130
130
  let t;
131
131
  try {
132
- t = JSON.parse(c(e, "utf-8"));
132
+ t = JSON.parse(f(e, "utf-8"));
133
133
  } catch {
134
- throw new U(`${e} is not valid JSON.`);
134
+ throw new H(`${e} is not valid JSON.`);
135
135
  }
136
- return ce(t, e);
136
+ return pe(t, e);
137
137
  }
138
- function le() {
139
- let e = l(V).filter((e) => e.endsWith(".sh"));
140
- s(H, { recursive: !0 });
138
+ function me() {
139
+ let e = p(B).filter((e) => e.endsWith(".sh"));
140
+ d(V, { recursive: !0 });
141
141
  for (let t of e) {
142
- let e = _(H, t);
143
- i(_(V, t), e, { force: !0 }), r(e, 493);
142
+ let e = v(V, t);
143
+ c(v(B, t), e, { force: !0 }), s(e, 493);
144
144
  }
145
- let t = l(H).filter((t) => t.endsWith(".sh") && !e.includes(t));
146
- for (let e of t) f(_(H, e), { force: !0 });
145
+ let t = p(V).filter((t) => t.endsWith(".sh") && !e.includes(t));
146
+ for (let e of t) h(v(V, e), { force: !0 });
147
147
  return {
148
148
  installed: e,
149
149
  removed: t
150
150
  };
151
151
  }
152
- var G = `${y.hooksDir}/`;
153
- function K(e) {
152
+ var W = `${b.hooksDir}/`;
153
+ function G(e) {
154
154
  if (typeof e != "string") return null;
155
- let t = e.lastIndexOf(G);
155
+ let t = e.lastIndexOf(W);
156
156
  if (t === -1) return null;
157
- let n = /^([\w.-]+)["']?$/.exec(e.slice(t + G.length));
157
+ let n = /^([\w.-]+)["']?$/.exec(e.slice(t + W.length));
158
158
  return n ? n[1] : null;
159
159
  }
160
- function q(e) {
160
+ function K(e) {
161
161
  return typeof e == "object" && !!e && "hooks" in e && Array.isArray(e.hooks);
162
162
  }
163
- function J(e) {
164
- return q(e) ? e.hooks : null;
163
+ function q(e) {
164
+ return K(e) ? e.hooks : null;
165
165
  }
166
- function Y(e) {
166
+ function J(e) {
167
167
  return typeof e == "object" && e && "command" in e ? e.command : void 0;
168
168
  }
169
- function X(e) {
170
- let t = J(e);
171
- return t ? t.map((e) => K(Y(e))).filter((e) => e !== null) : [];
169
+ function Y(e) {
170
+ let t = q(e);
171
+ return t ? t.map((e) => G(J(e))).filter((e) => e !== null) : [];
172
172
  }
173
- function ue(e, t, n) {
173
+ function he(e, t, n) {
174
174
  e.hooks ??= {};
175
175
  let r = 0, i = 0, a = [];
176
176
  for (let [r, o] of Object.entries(e.hooks)) {
177
177
  let s = 0, c = o.map((e) => {
178
- if (!q(e)) return e;
178
+ if (!K(e)) return e;
179
179
  let t = e.hooks, r = t.filter((e) => {
180
- let t = K(Y(e));
180
+ let t = G(J(e));
181
181
  return t === null || n.includes(t);
182
182
  });
183
183
  return s += t.length - r.length, r.length === t.length ? e : {
@@ -185,7 +185,7 @@ function ue(e, t, n) {
185
185
  hooks: r
186
186
  };
187
187
  }).filter((e) => {
188
- let t = J(e);
188
+ let t = q(e);
189
189
  return t === null || t.length > 0;
190
190
  });
191
191
  s !== 0 && (i += s, c.length === 0 && !(r in t) ? a.push(r) : e.hooks[r] = c);
@@ -194,8 +194,8 @@ function ue(e, t, n) {
194
194
  for (let [n, i] of Object.entries(t)) {
195
195
  e.hooks[n] ??= [];
196
196
  for (let t of i) {
197
- let i = X(t);
198
- e.hooks[n].some((e) => X(e).some((e) => i.includes(e))) || (e.hooks[n].push(t), r++);
197
+ let i = Y(t);
198
+ e.hooks[n].some((e) => Y(e).some((e) => i.includes(e))) || (e.hooks[n].push(t), r++);
199
199
  }
200
200
  }
201
201
  return {
@@ -203,72 +203,72 @@ function ue(e, t, n) {
203
203
  removed: i
204
204
  };
205
205
  }
206
- function de(e) {
207
- let r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map();
208
- for (let n of C) {
209
- let o = _(t, y.harnesses[n].hookSettings);
210
- if (a(o) && r.set(n, W(o)), e.includes(n)) {
211
- let e = _(B, y.harnesses[n].hookTemplate);
212
- i.set(n, W(e).hooks ?? {});
206
+ function ge(e) {
207
+ let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
208
+ for (let r of w) {
209
+ let i = v(a, b.harnesses[r].hookSettings);
210
+ if (l(i) && t.set(r, U(i)), e.includes(r)) {
211
+ let e = v(z, b.harnesses[r].hookTemplate);
212
+ n.set(r, U(e).hooks ?? {});
213
213
  }
214
214
  }
215
- let { installed: o, removed: c } = le();
216
- v.log.success(`Agent hooks -> ${E(H)} (${String(o.length)} scripts)`), c.length > 0 && v.log.info(`Removed stale hook script(s): ${c.join(", ")} (no longer shipped)`);
217
- for (let a of C) {
218
- let c = e.includes(a);
219
- if (!c && !r.has(a)) continue;
220
- let l = _(t, y.harnesses[a].hookSettings), u = i.get(a) ?? {}, d = r.get(a) ?? {}, f = ue(d, u, c ? o : []);
215
+ let { installed: r, removed: i } = me();
216
+ y.log.success(`Agent hooks -> ${E(V)} (${String(r.length)} scripts)`), i.length > 0 && y.log.info(`Removed stale hook script(s): ${i.join(", ")} (no longer shipped)`);
217
+ for (let i of w) {
218
+ let s = e.includes(i);
219
+ if (!s && !t.has(i)) continue;
220
+ let c = v(a, b.harnesses[i].hookSettings), l = n.get(i) ?? {}, u = t.get(i) ?? {}, f = he(u, l, s ? r : []);
221
221
  if (f.added === 0 && f.removed === 0) {
222
- c && v.log.info(`Hook registrations already present in ${E(l)}`);
222
+ s && y.log.info(`Hook registrations already present in ${E(c)}`);
223
223
  continue;
224
224
  }
225
- s(h(l), { recursive: !0 }), m(l, JSON.stringify(d, null, 2) + "\n"), n([l]);
225
+ d(ne(c), { recursive: !0 }), g(c, JSON.stringify(u, null, 2) + "\n"), o([c]);
226
226
  let p = [f.added > 0 && `registered ${String(f.added)}`, f.removed > 0 && `removed ${String(f.removed)} stale`].filter(Boolean);
227
- v.log.success(`${p.join(", ")} hook registration(s) in ${E(l)}`);
227
+ y.log.success(`${p.join(", ")} hook registration(s) in ${E(c)}`);
228
228
  }
229
229
  }
230
230
  //#endregion
231
231
  //#region src/cli/index.ts
232
- function Z() {
233
- return new te("--harness <harness>", "claude, codex, or all").choices(w);
232
+ function X() {
233
+ return new ie("--harness <harness>", "claude, codex, or all").choices(ce);
234
234
  }
235
- async function fe(e, t, n) {
236
- if (t) return v.log.info(`Harness from --harness flag: ${t.join(", ")}`), t;
235
+ async function Z(e, t, n) {
236
+ if (t) return y.log.info(`Harness from --harness flag: ${t.join(", ")}`), t;
237
237
  let r = L(e);
238
- if (r && !n) return v.log.info(`Refreshing the existing install: ${r.join(", ")} — pass --reconfigure to choose differently.`), r;
238
+ if (r && !n) return y.log.info(`Refreshing the existing install: ${r.join(", ")} — pass --reconfigure to choose differently.`), r;
239
239
  if (!process.stdin.isTTY) return console.error("Pass --harness=claude|codex|all — no terminal to prompt in."), process.exitCode = 1, null;
240
- let i = await v.multiselect({
240
+ let i = await y.multiselect({
241
241
  message: "Install into which harness (or harnesses)?",
242
- options: C.map((e) => ({
242
+ options: w.map((e) => ({
243
243
  value: e,
244
- label: y.harnesses[e].label
244
+ label: b.harnesses[e].label
245
245
  })),
246
246
  required: !0
247
247
  });
248
- return v.isCancel(i) ? (v.cancel("Cancelled — nothing installed."), null) : i;
248
+ return y.isCancel(i) ? (y.cancel("Cancelled — nothing installed."), null) : i;
249
249
  }
250
- async function pe(e) {
250
+ async function _e(e) {
251
251
  let t = e.harness ? T(e.harness) : null, n = I();
252
- if (v.intro(`@imfusion/web-ui install skills — ${String(n.length)} skills`), n.length === 0) {
253
- v.log.error("No skills found. Reinstall @imfusion/web-ui and try again."), v.outro("Nothing installed."), process.exitCode = 1;
252
+ if (y.intro(`@imfusion/web-ui install skills — ${String(n.length)} skills`), n.length === 0) {
253
+ y.log.error("No skills found. Reinstall @imfusion/web-ui and try again."), y.outro("Nothing installed."), process.exitCode = 1;
254
254
  return;
255
255
  }
256
- let r = await fe(n, t, e.reconfigure === !0);
256
+ let r = await Z(n, t, e.reconfigure === !0);
257
257
  if (!r) return;
258
- v.log.message(`Skills in this bundle:\n${n.map((e) => ` - ${e}`).join("\n")}`);
258
+ y.log.message(`Skills in this bundle:\n${n.map((e) => ` - ${e}`).join("\n")}`);
259
259
  try {
260
- se(n, r);
260
+ fe(n, r);
261
261
  } catch (e) {
262
262
  if (e instanceof M) {
263
- v.log.error(e.message), v.outro("Install failed."), process.exitCode = 1;
263
+ y.log.error(e.message), y.outro("Install failed."), process.exitCode = 1;
264
264
  return;
265
265
  }
266
266
  throw e;
267
267
  }
268
- let i = ie();
269
- (i === "updated" || i === "added") && v.log.success(`Refreshed the ${y.namespace} block in ./AGENTS.md`), v.outro(`Done — ${String(n.length)} skills installed.`);
268
+ let i = se();
269
+ (i === "updated" || i === "added") && y.log.success(`Refreshed the ${b.namespace} block in ./AGENTS.md`), y.outro(`Done — ${String(n.length)} skills installed.`);
270
270
  }
271
- function me(e) {
271
+ function ve(e) {
272
272
  let t = e.harness ? T(e.harness) : null, n = L(I());
273
273
  if (!t && !n) {
274
274
  console.error("No harness recorded. Pass --harness=claude|codex|all."), process.exitCode = 1;
@@ -280,22 +280,54 @@ function me(e) {
280
280
  process.exitCode = 1;
281
281
  return;
282
282
  }
283
- v.intro("@imfusion/web-ui install hooks");
283
+ y.intro("@imfusion/web-ui install hooks");
284
+ try {
285
+ ge(r);
286
+ } catch (e) {
287
+ if (e instanceof H) {
288
+ console.error(e.message), process.exitCode = 1;
289
+ return;
290
+ }
291
+ throw e;
292
+ }
293
+ y.outro("Done — agent hooks installed.");
294
+ }
295
+ function ye(r) {
296
+ let i = r ?? process.env.WEB_UI_CHECKOUT;
297
+ if (!i) {
298
+ console.error("Pass the checkout path, or set WEB_UI_CHECKOUT."), process.exitCode = 1;
299
+ return;
300
+ }
301
+ let o = v(i);
302
+ try {
303
+ let t = e(a, o);
304
+ y.log.success(`Linked ${o} into ${E(t)}`);
305
+ } catch (e) {
306
+ if (e instanceof n) {
307
+ console.error(e.message), process.exitCode = 1;
308
+ return;
309
+ }
310
+ throw e;
311
+ }
312
+ y.log.info("Syncing on every rebuild of dist/. Ctrl+C stops syncing; the app keeps the last synced build."), t(a, o, (e) => {
313
+ y.log.info(e);
314
+ });
315
+ }
316
+ function be() {
284
317
  try {
285
- de(r);
318
+ for (let e of i(a)) y.log.message(e);
286
319
  } catch (e) {
287
- if (e instanceof U) {
320
+ if (e instanceof n) {
288
321
  console.error(e.message), process.exitCode = 1;
289
322
  return;
290
323
  }
291
324
  throw e;
292
325
  }
293
- v.outro("Done — agent hooks installed.");
294
326
  }
295
- var Q = new ee();
327
+ var Q = new re();
296
328
  Q.name("web-ui").description("Command-line tools for @imfusion/web-ui").version(P);
297
329
  var $ = Q.command("install").description("Install @imfusion/web-ui agent skills or hooks into a project");
298
- $.command("skills").description("Install skills for the chosen harness").addOption(Z()).option("--reconfigure", "Re-open the harness selection prompt on an existing install").action(pe), $.command("hooks").description("Install agent lifecycle hooks (requires skills already installed for the harness)").addOption(Z()).action(me), $.action(() => {
330
+ $.command("skills").description("Install skills for the chosen harness").addOption(X()).option("--reconfigure", "Re-open the harness selection prompt on an existing install").action(_e), $.command("hooks").description("Install agent lifecycle hooks (requires skills already installed for the harness)").addOption(X()).action(ve), Q.command("link").description("Serve a local @imfusion/web-ui checkout from this project and sync it on every rebuild").argument("[path]", "checkout directory (default: WEB_UI_CHECKOUT)").action(ye), Q.command("unlink").description("Restore the published @imfusion/web-ui files in this project").action(be), $.action(() => {
299
331
  $.help();
300
332
  }), Q.action(() => {
301
333
  Q.help();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imfusion/web-ui",
3
- "version": "0.10.1-dev.37.g9147f90f",
3
+ "version": "0.10.1-dev.41.g467e0e1a",
4
4
  "description": "The official Web UI component library for ImFusion web apps",
5
5
  "author": "ImFusion GmbH",
6
6
  "homepage": "https://imfusion.com",