@construct-space/cli 1.0.6 → 1.0.7

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/index.js CHANGED
@@ -5,43 +5,25 @@ var __getProtoOf = Object.getPrototypeOf;
5
5
  var __defProp = Object.defineProperty;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- function __accessProp(key) {
9
- return this[key];
10
- }
11
- var __toESMCache_node;
12
- var __toESMCache_esm;
13
8
  var __toESM = (mod, isNodeMode, target) => {
14
- var canCache = mod != null && typeof mod === "object";
15
- if (canCache) {
16
- var cache = isNodeMode ? __toESMCache_node ??= new WeakMap : __toESMCache_esm ??= new WeakMap;
17
- var cached = cache.get(mod);
18
- if (cached)
19
- return cached;
20
- }
21
9
  target = mod != null ? __create(__getProtoOf(mod)) : {};
22
10
  const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
23
11
  for (let key of __getOwnPropNames(mod))
24
12
  if (!__hasOwnProp.call(to, key))
25
13
  __defProp(to, key, {
26
- get: __accessProp.bind(mod, key),
14
+ get: () => mod[key],
27
15
  enumerable: true
28
16
  });
29
- if (canCache)
30
- cache.set(mod, to);
31
17
  return to;
32
18
  };
33
19
  var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
34
- var __returnValue = (v) => v;
35
- function __exportSetter(name, newValue) {
36
- this[name] = __returnValue.bind(null, newValue);
37
- }
38
20
  var __export = (target, all) => {
39
21
  for (var name in all)
40
22
  __defProp(target, name, {
41
23
  get: all[name],
42
24
  enumerable: true,
43
25
  configurable: true,
44
- set: __exportSetter.bind(all, name)
26
+ set: (newValue) => all[name] = () => newValue
45
27
  });
46
28
  };
47
29
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
@@ -2807,6 +2789,7 @@ Object.defineProperties(createChalk.prototype, styles2);
2807
2789
  var chalk = createChalk();
2808
2790
  var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
2809
2791
  var source_default = chalk;
2792
+
2810
2793
  // node_modules/@inquirer/core/dist/lib/key.js
2811
2794
  var isUpKey = (key, keybindings = []) => key.name === "up" || keybindings.includes("vim") && key.name === "k" || keybindings.includes("emacs") && key.ctrl && key.name === "p";
2812
2795
  var isDownKey = (key, keybindings = []) => key.name === "down" || keybindings.includes("vim") && key.name === "j" || keybindings.includes("emacs") && key.ctrl && key.name === "n";
@@ -2951,7 +2934,7 @@ var effectScheduler = {
2951
2934
  // node_modules/@inquirer/core/dist/lib/use-state.js
2952
2935
  function useState(defaultValue) {
2953
2936
  return withPointer((pointer) => {
2954
- const setState = AsyncResource2.bind(function setState2(newValue) {
2937
+ const setState = AsyncResource2.bind(function setState(newValue) {
2955
2938
  if (pointer.get() !== newValue) {
2956
2939
  pointer.set(newValue);
2957
2940
  handleChange();
@@ -4541,7 +4524,8 @@ function openBrowser(url) {
4541
4524
  } catch {}
4542
4525
  }
4543
4526
  function git(dir, ...args) {
4544
- return execSync(`git ${args.join(" ")}`, { cwd: dir, encoding: "utf-8" }).trim();
4527
+ const quoted = args.map((a) => a.includes(" ") || a.includes(":") ? `"${a}"` : a);
4528
+ return execSync(`git ${quoted.join(" ")}`, { cwd: dir, encoding: "utf-8" }).trim();
4545
4529
  }
4546
4530
  function gitSafe(dir, ...args) {
4547
4531
  try {
@@ -4627,7 +4611,11 @@ async function scaffold(nameArg, options) {
4627
4611
  ];
4628
4612
  for (const d of dirs)
4629
4613
  mkdirSync(d, { recursive: true });
4630
- const templateDir = join(dirname(new URL(import.meta.url).pathname), "..", "..", "templates", "space");
4614
+ const scriptDir = dirname(new URL(import.meta.url).pathname);
4615
+ let templateDir = join(scriptDir, "templates", "space");
4616
+ if (!existsSync(templateDir)) {
4617
+ templateDir = join(scriptDir, "..", "templates", "space");
4618
+ }
4631
4619
  const files = {
4632
4620
  "space.manifest.json.tmpl": join(name, "space.manifest.json"),
4633
4621
  "package.json.tmpl": join(name, "package.json"),
@@ -4641,7 +4629,8 @@ async function scaffold(nameArg, options) {
4641
4629
  "gitignore.tmpl": join(name, ".gitignore"),
4642
4630
  "readme.md.tmpl": join(name, "README.md"),
4643
4631
  "widgets/2x1.vue.tmpl": join(name, "widgets", "summary", "2x1.vue"),
4644
- "widgets/4x1.vue.tmpl": join(name, "widgets", "summary", "4x1.vue")
4632
+ "widgets/4x1.vue.tmpl": join(name, "widgets", "summary", "4x1.vue"),
4633
+ "actions.ts.tmpl": join(name, "src", "actions.ts")
4645
4634
  };
4646
4635
  for (const [tmpl, out] of Object.entries(files)) {
4647
4636
  writeTemplate(templateDir, tmpl, out, data);
@@ -4661,7 +4650,7 @@ async function scaffold(nameArg, options) {
4661
4650
  }
4662
4651
 
4663
4652
  // src/commands/build.ts
4664
- import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync2, renameSync, statSync as statSync3 } from "fs";
4653
+ import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync2, renameSync, statSync as statSync2 } from "fs";
4665
4654
  import { join as join6 } from "path";
4666
4655
  import { createHash } from "crypto";
4667
4656
 
@@ -7371,8 +7360,7 @@ function resolvePages(m, prefix) {
7371
7360
  function resolveWidgets(m, prefix) {
7372
7361
  const imports = [];
7373
7362
  for (const w of m.widgets || []) {
7374
- const sizeKeys = Object.keys(w.sizes).sort();
7375
- for (const sizeKey of sizeKeys) {
7363
+ for (const sizeKey of Object.keys(w.sizes).sort()) {
7376
7364
  imports.push({
7377
7365
  varName: capitalize(w.id) + "Widget" + sizeKey,
7378
7366
  importPath: prefix + w.sizes[sizeKey],
@@ -7387,6 +7375,9 @@ function generate(root, m) {
7387
7375
  const pagePrefix = existsSync3(join3(root, "src", "pages")) ? "./" : "../";
7388
7376
  const pages = resolvePages(m, pagePrefix);
7389
7377
  const widgets = resolveWidgets(m, "../");
7378
+ const actionsPath = join3(root, "src", "actions.ts");
7379
+ const hasActions = existsSync3(actionsPath);
7380
+ console.log(`[entry] root=${root} actionsPath=${actionsPath} hasActions=${hasActions}`);
7390
7381
  const lines = [
7391
7382
  "// Auto-generated entry — do not edit manually",
7392
7383
  "// Generated from space.manifest.json"
@@ -7395,6 +7386,8 @@ function generate(root, m) {
7395
7386
  lines.push(`import ${p.varName} from '${p.importPath}'`);
7396
7387
  for (const w of widgets)
7397
7388
  lines.push(`import ${w.varName} from '${w.importPath}'`);
7389
+ if (hasActions)
7390
+ lines.push("import { actions } from './actions'");
7398
7391
  lines.push("");
7399
7392
  lines.push("const spaceExport = {");
7400
7393
  lines.push(" pages: {");
@@ -7414,13 +7407,14 @@ function generate(root, m) {
7414
7407
  }
7415
7408
  for (const wid of order) {
7416
7409
  lines.push(` '${wid}': {`);
7417
- for (const w of byId.get(wid)) {
7410
+ for (const w of byId.get(wid))
7418
7411
  lines.push(` '${w.sizeKey}': ${w.varName},`);
7419
- }
7420
7412
  lines.push(" },");
7421
7413
  }
7422
7414
  lines.push(" },");
7423
7415
  }
7416
+ if (hasActions)
7417
+ lines.push(" actions,");
7424
7418
  lines.push("}");
7425
7419
  lines.push("");
7426
7420
  lines.push("export default spaceExport");
@@ -7561,7 +7555,7 @@ async function build(options) {
7561
7555
  }
7562
7556
  runHook(m.hooks, "postBuild", root);
7563
7557
  const agentDir = join6(root, "agent");
7564
- if (existsSync6(agentDir) && statSync3(agentDir).isDirectory()) {
7558
+ if (existsSync6(agentDir) && statSync2(agentDir).isDirectory()) {
7565
7559
  const distDir2 = join6(root, "dist");
7566
7560
  bundleAgentDir(agentDir, distDir2);
7567
7561
  bundleAgentDir(agentDir, root);
@@ -7596,16 +7590,16 @@ import { existsSync as existsSync7, mkdirSync as mkdirSync3, writeFileSync as wr
7596
7590
  import { join as join10 } from "path";
7597
7591
  import { createHash as createHash2 } from "crypto";
7598
7592
 
7599
- // node_modules/chokidar/esm/index.js
7600
- import { stat as statcb } from "fs";
7601
- import { stat as stat3, readdir as readdir2 } from "fs/promises";
7602
- import { EventEmitter } from "events";
7603
- import * as sysPath2 from "path";
7593
+ // node_modules/chokidar/index.js
7594
+ import { EventEmitter } from "node:events";
7595
+ import { stat as statcb, Stats } from "node:fs";
7596
+ import { readdir as readdir2, stat as stat3 } from "node:fs/promises";
7597
+ import * as sp2 from "node:path";
7604
7598
 
7605
- // node_modules/readdirp/esm/index.js
7606
- import { stat, lstat, readdir, realpath } from "node:fs/promises";
7599
+ // node_modules/readdirp/index.js
7600
+ import { lstat, readdir, realpath, stat } from "node:fs/promises";
7601
+ import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "node:path";
7607
7602
  import { Readable } from "node:stream";
7608
- import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "node:path";
7609
7603
  var EntryTypes = {
7610
7604
  FILE_TYPE: "files",
7611
7605
  DIR_TYPE: "directories",
@@ -7661,6 +7655,20 @@ var normalizeFilter = (filter) => {
7661
7655
  };
7662
7656
 
7663
7657
  class ReaddirpStream extends Readable {
7658
+ parents;
7659
+ reading;
7660
+ parent;
7661
+ _stat;
7662
+ _maxDepth;
7663
+ _wantsDir;
7664
+ _wantsFile;
7665
+ _wantsEverything;
7666
+ _root;
7667
+ _isDirent;
7668
+ _statsProp;
7669
+ _rdOptions;
7670
+ _fileFilter;
7671
+ _directoryFilter;
7664
7672
  constructor(options = {}) {
7665
7673
  super({
7666
7674
  objectMode: true,
@@ -7677,7 +7685,7 @@ class ReaddirpStream extends Readable {
7677
7685
  } else {
7678
7686
  this._stat = statMethod;
7679
7687
  }
7680
- this._maxDepth = opts.depth ?? defaultOptions.depth;
7688
+ this._maxDepth = opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;
7681
7689
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
7682
7690
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
7683
7691
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
@@ -7822,11 +7830,11 @@ function readdirp(root, options = {}) {
7822
7830
  return new ReaddirpStream(options);
7823
7831
  }
7824
7832
 
7825
- // node_modules/chokidar/esm/handler.js
7826
- import { watchFile, unwatchFile, watch as fs_watch } from "fs";
7827
- import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
7828
- import * as sysPath from "path";
7829
- import { type as osType } from "os";
7833
+ // node_modules/chokidar/handler.js
7834
+ import { watch as fs_watch, unwatchFile, watchFile } from "node:fs";
7835
+ import { realpath as fsrealpath, lstat as lstat2, open, stat as stat2 } from "node:fs/promises";
7836
+ import { type as osType } from "node:os";
7837
+ import * as sp from "node:path";
7830
7838
  var STR_DATA = "data";
7831
7839
  var STR_END = "end";
7832
7840
  var STR_CLOSE = "close";
@@ -8118,7 +8126,7 @@ var binaryExtensions = new Set([
8118
8126
  "zip",
8119
8127
  "zipx"
8120
8128
  ]);
8121
- var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
8129
+ var isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());
8122
8130
  var foreach = (val, fn) => {
8123
8131
  if (val instanceof Set) {
8124
8132
  val.forEach(fn);
@@ -8156,7 +8164,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
8156
8164
  listener(path);
8157
8165
  emitRaw(rawEvent, evPath, { watchedPath: path });
8158
8166
  if (evPath && path !== evPath) {
8159
- fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
8167
+ fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));
8160
8168
  }
8161
8169
  };
8162
8170
  try {
@@ -8271,17 +8279,19 @@ var setFsWatchFileListener = (path, fullPath, options, handlers) => {
8271
8279
  };
8272
8280
 
8273
8281
  class NodeFsHandler {
8282
+ fsw;
8283
+ _boundHandleError;
8274
8284
  constructor(fsW) {
8275
8285
  this.fsw = fsW;
8276
8286
  this._boundHandleError = (error2) => fsW._handleError(error2);
8277
8287
  }
8278
8288
  _watchWithNodeFs(path, listener) {
8279
8289
  const opts = this.fsw.options;
8280
- const directory = sysPath.dirname(path);
8281
- const basename4 = sysPath.basename(path);
8290
+ const directory = sp.dirname(path);
8291
+ const basename4 = sp.basename(path);
8282
8292
  const parent = this.fsw._getWatchedDir(directory);
8283
8293
  parent.add(basename4);
8284
- const absolutePath = sysPath.resolve(path);
8294
+ const absolutePath = sp.resolve(path);
8285
8295
  const options = {
8286
8296
  persistent: opts.persistent
8287
8297
  };
@@ -8308,8 +8318,8 @@ class NodeFsHandler {
8308
8318
  if (this.fsw.closed) {
8309
8319
  return;
8310
8320
  }
8311
- const dirname3 = sysPath.dirname(file);
8312
- const basename4 = sysPath.basename(file);
8321
+ const dirname3 = sp.dirname(file);
8322
+ const basename4 = sp.basename(file);
8313
8323
  const parent = this.fsw._getWatchedDir(dirname3);
8314
8324
  let prevStats = stats;
8315
8325
  if (parent.has(basename4))
@@ -8392,8 +8402,9 @@ class NodeFsHandler {
8392
8402
  this.fsw._symlinkPaths.set(full, true);
8393
8403
  }
8394
8404
  _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
8395
- directory = sysPath.join(directory, "");
8396
- throttler = this.fsw._throttle("readdir", directory, 1000);
8405
+ directory = sp.join(directory, "");
8406
+ const throttleKey = target ? `${directory}:${target}` : directory;
8407
+ throttler = this.fsw._throttle("readdir", throttleKey, 1000);
8397
8408
  if (!throttler)
8398
8409
  return;
8399
8410
  const previous = this.fsw._getWatchedDir(wh.path);
@@ -8410,7 +8421,7 @@ class NodeFsHandler {
8410
8421
  return;
8411
8422
  }
8412
8423
  const item = entry.path;
8413
- let path = sysPath.join(directory, item);
8424
+ let path = sp.join(directory, item);
8414
8425
  current.add(item);
8415
8426
  if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
8416
8427
  return;
@@ -8421,7 +8432,7 @@ class NodeFsHandler {
8421
8432
  }
8422
8433
  if (item === target || !target && !previous.has(item)) {
8423
8434
  this.fsw._incrReadyCount();
8424
- path = sysPath.join(dir, sysPath.relative(dir, path));
8435
+ path = sp.join(dir, sp.relative(dir, path));
8425
8436
  this._addToNodeFs(path, initialAdd, wh, depth + 1);
8426
8437
  }
8427
8438
  }).on(EV.ERROR, this._boundHandleError);
@@ -8447,12 +8458,12 @@ class NodeFsHandler {
8447
8458
  });
8448
8459
  }
8449
8460
  async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
8450
- const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
8451
- const tracked = parentDir.has(sysPath.basename(dir));
8461
+ const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));
8462
+ const tracked = parentDir.has(sp.basename(dir));
8452
8463
  if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
8453
8464
  this.fsw._emit(EV.ADD_DIR, dir, stats);
8454
8465
  }
8455
- parentDir.add(sysPath.basename(dir));
8466
+ parentDir.add(sp.basename(dir));
8456
8467
  this.fsw._getWatchedDir(dir);
8457
8468
  let throttler;
8458
8469
  let closer;
@@ -8493,7 +8504,7 @@ class NodeFsHandler {
8493
8504
  const follow = this.fsw.options.followSymlinks;
8494
8505
  let closer;
8495
8506
  if (stats.isDirectory()) {
8496
- const absPath = sysPath.resolve(path);
8507
+ const absPath = sp.resolve(path);
8497
8508
  const targetPath = follow ? await fsrealpath(path) : path;
8498
8509
  if (this.fsw.closed)
8499
8510
  return;
@@ -8507,14 +8518,14 @@ class NodeFsHandler {
8507
8518
  const targetPath = follow ? await fsrealpath(path) : path;
8508
8519
  if (this.fsw.closed)
8509
8520
  return;
8510
- const parent = sysPath.dirname(wh.watchPath);
8521
+ const parent = sp.dirname(wh.watchPath);
8511
8522
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
8512
8523
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
8513
8524
  closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
8514
8525
  if (this.fsw.closed)
8515
8526
  return;
8516
8527
  if (targetPath !== undefined) {
8517
- this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
8528
+ this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);
8518
8529
  }
8519
8530
  } else {
8520
8531
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
@@ -8532,7 +8543,7 @@ class NodeFsHandler {
8532
8543
  }
8533
8544
  }
8534
8545
 
8535
- // node_modules/chokidar/esm/index.js
8546
+ // node_modules/chokidar/index.js
8536
8547
  /*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
8537
8548
  var SLASH = "/";
8538
8549
  var SLASH_SLASH = "//";
@@ -8540,7 +8551,7 @@ var ONE_DOT = ".";
8540
8551
  var TWO_DOTS = "..";
8541
8552
  var STRING_TYPE = "string";
8542
8553
  var BACK_SLASH_RE = /\\/g;
8543
- var DOUBLE_SLASH_RE = /\/\//;
8554
+ var DOUBLE_SLASH_RE = /\/\//g;
8544
8555
  var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
8545
8556
  var REPLACER_RE = /^\.[/\\]/;
8546
8557
  function arrify(item) {
@@ -8559,11 +8570,11 @@ function createPattern(matcher) {
8559
8570
  if (matcher.path === string)
8560
8571
  return true;
8561
8572
  if (matcher.recursive) {
8562
- const relative3 = sysPath2.relative(matcher.path, string);
8573
+ const relative3 = sp2.relative(matcher.path, string);
8563
8574
  if (!relative3) {
8564
8575
  return false;
8565
8576
  }
8566
- return !relative3.startsWith("..") && !sysPath2.isAbsolute(relative3);
8577
+ return !relative3.startsWith("..") && !sp2.isAbsolute(relative3);
8567
8578
  }
8568
8579
  return false;
8569
8580
  };
@@ -8573,14 +8584,12 @@ function createPattern(matcher) {
8573
8584
  function normalizePath(path) {
8574
8585
  if (typeof path !== "string")
8575
8586
  throw new Error("string expected");
8576
- path = sysPath2.normalize(path);
8587
+ path = sp2.normalize(path);
8577
8588
  path = path.replace(/\\/g, "/");
8578
8589
  let prepend = false;
8579
8590
  if (path.startsWith("//"))
8580
8591
  prepend = true;
8581
- const DOUBLE_SLASH_RE2 = /\/\//;
8582
- while (path.match(DOUBLE_SLASH_RE2))
8583
- path = path.replace(DOUBLE_SLASH_RE2, "/");
8592
+ path = path.replace(DOUBLE_SLASH_RE, "/");
8584
8593
  if (prepend)
8585
8594
  path = "/" + path;
8586
8595
  return path;
@@ -8621,31 +8630,32 @@ var toUnix = (string) => {
8621
8630
  if (str.startsWith(SLASH_SLASH)) {
8622
8631
  prepend = true;
8623
8632
  }
8624
- while (str.match(DOUBLE_SLASH_RE)) {
8625
- str = str.replace(DOUBLE_SLASH_RE, SLASH);
8626
- }
8633
+ str = str.replace(DOUBLE_SLASH_RE, SLASH);
8627
8634
  if (prepend) {
8628
8635
  str = SLASH + str;
8629
8636
  }
8630
8637
  return str;
8631
8638
  };
8632
- var normalizePathToUnix = (path) => toUnix(sysPath2.normalize(toUnix(path)));
8639
+ var normalizePathToUnix = (path) => toUnix(sp2.normalize(toUnix(path)));
8633
8640
  var normalizeIgnored = (cwd = "") => (path) => {
8634
8641
  if (typeof path === "string") {
8635
- return normalizePathToUnix(sysPath2.isAbsolute(path) ? path : sysPath2.join(cwd, path));
8642
+ return normalizePathToUnix(sp2.isAbsolute(path) ? path : sp2.join(cwd, path));
8636
8643
  } else {
8637
8644
  return path;
8638
8645
  }
8639
8646
  };
8640
8647
  var getAbsolutePath = (path, cwd) => {
8641
- if (sysPath2.isAbsolute(path)) {
8648
+ if (sp2.isAbsolute(path)) {
8642
8649
  return path;
8643
8650
  }
8644
- return sysPath2.join(cwd, path);
8651
+ return sp2.join(cwd, path);
8645
8652
  };
8646
8653
  var EMPTY_SET = Object.freeze(new Set);
8647
8654
 
8648
8655
  class DirEntry {
8656
+ path;
8657
+ _removeWatcher;
8658
+ items;
8649
8659
  constructor(dir, removeWatcher) {
8650
8660
  this.path = dir;
8651
8661
  this._removeWatcher = removeWatcher;
@@ -8670,7 +8680,7 @@ class DirEntry {
8670
8680
  await readdir2(dir);
8671
8681
  } catch (err) {
8672
8682
  if (this._removeWatcher) {
8673
- this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
8683
+ this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
8674
8684
  }
8675
8685
  }
8676
8686
  }
@@ -8698,12 +8708,19 @@ var STAT_METHOD_F = "stat";
8698
8708
  var STAT_METHOD_L = "lstat";
8699
8709
 
8700
8710
  class WatchHelper {
8711
+ fsw;
8712
+ path;
8713
+ watchPath;
8714
+ fullWatchPath;
8715
+ dirParts;
8716
+ followSymlinks;
8717
+ statMethod;
8701
8718
  constructor(path, follow, fsw) {
8702
8719
  this.fsw = fsw;
8703
8720
  const watchPath = path;
8704
8721
  this.path = path = path.replace(REPLACER_RE, "");
8705
8722
  this.watchPath = watchPath;
8706
- this.fullWatchPath = sysPath2.resolve(watchPath);
8723
+ this.fullWatchPath = sp2.resolve(watchPath);
8707
8724
  this.dirParts = [];
8708
8725
  this.dirParts.forEach((parts) => {
8709
8726
  if (parts.length > 1)
@@ -8713,7 +8730,7 @@ class WatchHelper {
8713
8730
  this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
8714
8731
  }
8715
8732
  entryPath(entry) {
8716
- return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
8733
+ return sp2.join(this.watchPath, sp2.relative(this.watchPath, entry.fullPath));
8717
8734
  }
8718
8735
  filterPath(entry) {
8719
8736
  const { stats } = entry;
@@ -8728,6 +8745,24 @@ class WatchHelper {
8728
8745
  }
8729
8746
 
8730
8747
  class FSWatcher extends EventEmitter {
8748
+ closed;
8749
+ options;
8750
+ _closers;
8751
+ _ignoredPaths;
8752
+ _throttled;
8753
+ _streams;
8754
+ _symlinkPaths;
8755
+ _watched;
8756
+ _pendingWrites;
8757
+ _pendingUnlinks;
8758
+ _readyCount;
8759
+ _emitReady;
8760
+ _closePromise;
8761
+ _userIgnored;
8762
+ _readyEmitted;
8763
+ _emitRaw;
8764
+ _boundRemove;
8765
+ _nodeFsHandler;
8731
8766
  constructor(_opts = {}) {
8732
8767
  super();
8733
8768
  this.closed = false;
@@ -8836,7 +8871,7 @@ class FSWatcher extends EventEmitter {
8836
8871
  return;
8837
8872
  results.forEach((item) => {
8838
8873
  if (item)
8839
- this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
8874
+ this.add(sp2.dirname(item), sp2.basename(_origAdd || item));
8840
8875
  });
8841
8876
  });
8842
8877
  return this;
@@ -8847,10 +8882,10 @@ class FSWatcher extends EventEmitter {
8847
8882
  const paths = unifyPaths(paths_);
8848
8883
  const { cwd } = this.options;
8849
8884
  paths.forEach((path) => {
8850
- if (!sysPath2.isAbsolute(path) && !this._closers.has(path)) {
8885
+ if (!sp2.isAbsolute(path) && !this._closers.has(path)) {
8851
8886
  if (cwd)
8852
- path = sysPath2.join(cwd, path);
8853
- path = sysPath2.resolve(path);
8887
+ path = sp2.join(cwd, path);
8888
+ path = sp2.resolve(path);
8854
8889
  }
8855
8890
  this._closePath(path);
8856
8891
  this._addIgnoredPath(path);
@@ -8894,7 +8929,7 @@ class FSWatcher extends EventEmitter {
8894
8929
  getWatched() {
8895
8930
  const watchList = {};
8896
8931
  this._watched.forEach((entry, dir) => {
8897
- const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
8932
+ const key = this.options.cwd ? sp2.relative(this.options.cwd, dir) : dir;
8898
8933
  const index = key || ONE_DOT;
8899
8934
  watchList[index] = entry.getChildren().sort();
8900
8935
  });
@@ -8910,9 +8945,9 @@ class FSWatcher extends EventEmitter {
8910
8945
  return;
8911
8946
  const opts = this.options;
8912
8947
  if (isWindows)
8913
- path = sysPath2.normalize(path);
8948
+ path = sp2.normalize(path);
8914
8949
  if (opts.cwd)
8915
- path = sysPath2.relative(opts.cwd, path);
8950
+ path = sp2.relative(opts.cwd, path);
8916
8951
  const args = [path];
8917
8952
  if (stats != null)
8918
8953
  args.push(stats);
@@ -8963,7 +8998,7 @@ class FSWatcher extends EventEmitter {
8963
8998
  return this;
8964
8999
  }
8965
9000
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
8966
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path) : path;
9001
+ const fullPath = opts.cwd ? sp2.join(opts.cwd, path) : path;
8967
9002
  let stats2;
8968
9003
  try {
8969
9004
  stats2 = await stat3(fullPath);
@@ -9019,8 +9054,8 @@ class FSWatcher extends EventEmitter {
9019
9054
  const pollInterval = awf.pollInterval;
9020
9055
  let timeoutHandler;
9021
9056
  let fullPath = path;
9022
- if (this.options.cwd && !sysPath2.isAbsolute(path)) {
9023
- fullPath = sysPath2.join(this.options.cwd, path);
9057
+ if (this.options.cwd && !sp2.isAbsolute(path)) {
9058
+ fullPath = sp2.join(this.options.cwd, path);
9024
9059
  }
9025
9060
  const now = new Date;
9026
9061
  const writes = this._pendingWrites;
@@ -9077,7 +9112,7 @@ class FSWatcher extends EventEmitter {
9077
9112
  return new WatchHelper(path, this.options.followSymlinks, this);
9078
9113
  }
9079
9114
  _getWatchedDir(directory) {
9080
- const dir = sysPath2.resolve(directory);
9115
+ const dir = sp2.resolve(directory);
9081
9116
  if (!this._watched.has(dir))
9082
9117
  this._watched.set(dir, new DirEntry(dir, this._boundRemove));
9083
9118
  return this._watched.get(dir);
@@ -9088,8 +9123,8 @@ class FSWatcher extends EventEmitter {
9088
9123
  return Boolean(Number(stats.mode) & 256);
9089
9124
  }
9090
9125
  _remove(directory, item, isDirectory) {
9091
- const path = sysPath2.join(directory, item);
9092
- const fullPath = sysPath2.resolve(path);
9126
+ const path = sp2.join(directory, item);
9127
+ const fullPath = sp2.resolve(path);
9093
9128
  isDirectory = isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
9094
9129
  if (!this._throttle("remove", path, 100))
9095
9130
  return;
@@ -9107,7 +9142,7 @@ class FSWatcher extends EventEmitter {
9107
9142
  }
9108
9143
  let relPath = path;
9109
9144
  if (this.options.cwd)
9110
- relPath = sysPath2.relative(this.options.cwd, path);
9145
+ relPath = sp2.relative(this.options.cwd, path);
9111
9146
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
9112
9147
  const event = this._pendingWrites.get(relPath).cancelWait();
9113
9148
  if (event === EVENTS.ADD)
@@ -9122,8 +9157,8 @@ class FSWatcher extends EventEmitter {
9122
9157
  }
9123
9158
  _closePath(path) {
9124
9159
  this._closeFile(path);
9125
- const dir = sysPath2.dirname(path);
9126
- this._getWatchedDir(dir).remove(sysPath2.basename(path));
9160
+ const dir = sp2.dirname(path);
9161
+ this._getWatchedDir(dir).remove(sp2.basename(path));
9127
9162
  }
9128
9163
  _closeFile(path) {
9129
9164
  const closers = this._closers.get(path);
@@ -9218,6 +9253,12 @@ function devSpaceDir(spaceId) {
9218
9253
  }
9219
9254
 
9220
9255
  // src/commands/dev.ts
9256
+ function getEntryWatchPaths(root) {
9257
+ return [
9258
+ join10(root, MANIFEST_FILE),
9259
+ join10(root, "src", "actions.ts")
9260
+ ];
9261
+ }
9221
9262
  async function dev() {
9222
9263
  const root = process.cwd();
9223
9264
  if (!exists(root)) {
@@ -9253,15 +9294,23 @@ async function dev() {
9253
9294
  vite.stderr?.on("data", (data) => {
9254
9295
  process.stderr.write(source_default.dim(data.toString()));
9255
9296
  });
9256
- const manifestWatcher = watch(join10(root, MANIFEST_FILE), { ignoreInitial: true });
9257
- manifestWatcher.on("change", () => {
9297
+ const regenerateEntry = () => {
9258
9298
  try {
9259
9299
  const newM = read(root);
9260
9300
  writeEntry(root, newM);
9261
- console.log(source_default.blue("Manifest changed — entry regenerated"));
9301
+ console.log(source_default.blue("Entry regenerated"));
9262
9302
  } catch (err) {
9263
9303
  console.error(source_default.red(`Manifest error: ${err.message}`));
9264
9304
  }
9305
+ };
9306
+ const entryWatcher = watch(getEntryWatchPaths(root), { ignoreInitial: true });
9307
+ entryWatcher.on("all", (_, changedPath) => {
9308
+ regenerateEntry();
9309
+ if (changedPath.endsWith(MANIFEST_FILE)) {
9310
+ console.log(source_default.blue("Manifest changed — entry regenerated"));
9311
+ return;
9312
+ }
9313
+ console.log(source_default.blue("Actions changed — entry regenerated"));
9265
9314
  });
9266
9315
  const distDir = join10(root, "dist");
9267
9316
  const bundleFile = join10(distDir, `space-${m.id}.iife.js`);
@@ -9285,11 +9334,18 @@ async function dev() {
9285
9334
  mkdirSync3(installDir, { recursive: true });
9286
9335
  cpSync(distDir, installDir, { recursive: true });
9287
9336
  writeFileSync5(join10(installDir, ".dev"), "dev");
9337
+ const configAgent = join10(root, "config.agent");
9338
+ if (existsSync7(configAgent)) {
9339
+ cpSync(configAgent, join10(installDir, "config.agent"));
9340
+ }
9288
9341
  const devInstall = devSpaceDir(m.id);
9289
9342
  const devParent = join10(devInstall, "..");
9290
9343
  if (existsSync7(devParent)) {
9291
9344
  mkdirSync3(devInstall, { recursive: true });
9292
9345
  cpSync(distDir, devInstall, { recursive: true });
9346
+ if (existsSync7(configAgent)) {
9347
+ cpSync(configAgent, join10(devInstall, "config.agent"));
9348
+ }
9293
9349
  }
9294
9350
  console.log(source_default.green(`Installed → ${m.id}`));
9295
9351
  });
@@ -9324,7 +9380,7 @@ function run() {
9324
9380
  }
9325
9381
 
9326
9382
  // src/commands/publish.ts
9327
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, statSync as statSync6, unlinkSync as unlinkSync3 } from "fs";
9383
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, statSync as statSync5, unlinkSync as unlinkSync3 } from "fs";
9328
9384
  import { join as join14, basename as basename6 } from "path";
9329
9385
 
9330
9386
  // src/lib/auth.ts
@@ -9367,7 +9423,7 @@ function clear() {
9367
9423
  }
9368
9424
 
9369
9425
  // src/lib/pack.ts
9370
- import { readdirSync as readdirSync3, statSync as statSync5, existsSync as existsSync10 } from "fs";
9426
+ import { readdirSync as readdirSync3, statSync as statSync4, existsSync as existsSync10 } from "fs";
9371
9427
  import { join as join13 } from "path";
9372
9428
  import { tmpdir } from "os";
9373
9429
  import { execSync as execSync3 } from "child_process";
@@ -9410,7 +9466,7 @@ async function packSource(root) {
9410
9466
  entries.push(name);
9411
9467
  }
9412
9468
  for (const entry of readdirSync3(root)) {
9413
- if (statSync5(join13(root, entry)).isDirectory())
9469
+ if (statSync4(join13(root, entry)).isDirectory())
9414
9470
  continue;
9415
9471
  if (allowedRootFiles.includes(entry))
9416
9472
  continue;
@@ -9430,7 +9486,7 @@ async function packSource(root) {
9430
9486
  const excludes = "--exclude=node_modules --exclude=dist --exclude=.git --exclude=*.env --exclude=*.log --exclude=*.lock --exclude=*.lockb";
9431
9487
  const cmd = `tar czf "${tarballPath}" ${excludes} ${validEntries.join(" ")}`;
9432
9488
  execSync3(cmd, { cwd: root });
9433
- const size = statSync5(tarballPath).size;
9489
+ const size = statSync4(tarballPath).size;
9434
9490
  if (size > MAX_SIZE) {
9435
9491
  throw new Error(`Source exceeds maximum size of ${MAX_SIZE / 1024 / 1024}MB`);
9436
9492
  }
@@ -9570,7 +9626,7 @@ async function publish(options) {
9570
9626
  let tarballPath;
9571
9627
  try {
9572
9628
  tarballPath = await packSource(root);
9573
- const size = statSync6(tarballPath).size;
9629
+ const size = statSync5(tarballPath).size;
9574
9630
  spinner.succeed(`Source packed (${formatBytes(size)})`);
9575
9631
  } catch (err) {
9576
9632
  spinner.fail("Pack failed");
@@ -10386,7 +10442,7 @@ function parseModelFields(content, fileName) {
10386
10442
  }
10387
10443
 
10388
10444
  // src/index.ts
10389
- var VERSION = "1.0.6";
10445
+ var VERSION = "1.0.7";
10390
10446
  var program2 = new Command;
10391
10447
  program2.name("construct").description("Construct CLI — scaffold, build, develop, and publish spaces").version(VERSION);
10392
10448
  program2.command("scaffold [name]").alias("new").alias("create").description("Create a new Construct space project").option("--with-tests", "Include E2E testing boilerplate").action(async (name, opts) => scaffold(name, opts));
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Space Actions — exposed to the AI agent via space_run_action
3
+ *
4
+ * Define actions here and they'll be automatically available as agent tools.
5
+ * The agent calls: space_run_action(action: "action_id", payload: {...})
6
+ */
7
+
8
+ export const actions = {
9
+ // Example action:
10
+ // hello: {
11
+ // description: 'Say hello',
12
+ // params: {
13
+ // name: { type: 'string', description: 'Name to greet', required: true },
14
+ // },
15
+ // run: (p: any) => ({ message: `Hello ${p.name}!` }),
16
+ // },
17
+ }
@@ -4,14 +4,20 @@ name: {{.DisplayName}}
4
4
  category: space
5
5
  description: AI agent for the {{.DisplayName}} space
6
6
  maxIterations: 15
7
+ tools: []
7
8
  canInvokeAgents: []
8
9
  ---
9
10
 
10
- You are Construct's {{.DisplayName}} agent. You help users work effectively within the {{.DisplayName}} space.
11
+ You are Construct's {{.DisplayName}} agent. You help users work within the {{.DisplayName}} space.
12
+
13
+ ## Context
14
+
15
+ Use space_list_actions to discover available actions for this space.
16
+ Use space_run_action to execute actions.
17
+ Do NOT call get_project_context — you work with space content, not project files.
11
18
 
12
19
  ## Behavior
13
20
 
14
- - Use get_project_context to understand the current project before acting
15
- - Read files before modifying them
16
- - Focus on tasks relevant to this space
21
+ - Start by listing available actions to understand what you can do
17
22
  - Be concise and action-oriented
23
+ - Focus on tasks relevant to this space
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@construct-space/cli",
3
- "version": "1.0.6",
3
+ "version": "1.0.7",
4
4
  "description": "Construct CLI — scaffold, build, develop, and publish spaces",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,10 +25,10 @@
25
25
  "@inquirer/prompts": "^8.3.2",
26
26
  "chalk": "^5.6.2",
27
27
  "ora": "^9.3.0",
28
- "chokidar": "^4.0.3"
28
+ "chokidar": "^5.0.0"
29
29
  },
30
30
  "devDependencies": {
31
- "@types/node": "^22.15.17",
31
+ "@types/node": "^25.5.0",
32
32
  "typescript": "^6.0.2"
33
33
  },
34
34
  "keywords": [
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Space Actions — exposed to the AI agent via space_run_action
3
+ *
4
+ * Define actions here and they'll be automatically available as agent tools.
5
+ * The agent calls: space_run_action(action: "action_id", payload: {...})
6
+ */
7
+
8
+ export const actions = {
9
+ // Example action:
10
+ // hello: {
11
+ // description: 'Say hello',
12
+ // params: {
13
+ // name: { type: 'string', description: 'Name to greet', required: true },
14
+ // },
15
+ // run: (p: any) => ({ message: `Hello ${p.name}!` }),
16
+ // },
17
+ }
@@ -4,14 +4,20 @@ name: {{.DisplayName}}
4
4
  category: space
5
5
  description: AI agent for the {{.DisplayName}} space
6
6
  maxIterations: 15
7
+ tools: []
7
8
  canInvokeAgents: []
8
9
  ---
9
10
 
10
- You are Construct's {{.DisplayName}} agent. You help users work effectively within the {{.DisplayName}} space.
11
+ You are Construct's {{.DisplayName}} agent. You help users work within the {{.DisplayName}} space.
12
+
13
+ ## Context
14
+
15
+ Use space_list_actions to discover available actions for this space.
16
+ Use space_run_action to execute actions.
17
+ Do NOT call get_project_context — you work with space content, not project files.
11
18
 
12
19
  ## Behavior
13
20
 
14
- - Use get_project_context to understand the current project before acting
15
- - Read files before modifying them
16
- - Focus on tasks relevant to this space
21
+ - Start by listing available actions to understand what you can do
17
22
  - Be concise and action-oriented
23
+ - Focus on tasks relevant to this space