@construct-space/cli 1.9.5 → 1.9.6

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
@@ -2790,8 +2790,8 @@ var require_lib = __commonJS((exports, module) => {
2790
2790
  });
2791
2791
 
2792
2792
  // src/lib/appdir.ts
2793
- import { existsSync as existsSync8, readFileSync as readFileSync6 } from "fs";
2794
- import { join as join10 } from "path";
2793
+ import { existsSync as existsSync9, readFileSync as readFileSync6 } from "fs";
2794
+ import { join as join11 } from "path";
2795
2795
  import { homedir } from "os";
2796
2796
  import { platform } from "process";
2797
2797
  function dataDir() {
@@ -2800,32 +2800,32 @@ function dataDir() {
2800
2800
  const home = homedir();
2801
2801
  switch (platform) {
2802
2802
  case "darwin":
2803
- return join10(home, "Library", "Application Support", "Construct");
2803
+ return join11(home, "Library", "Application Support", "Construct");
2804
2804
  case "win32": {
2805
- const appData = process.env.APPDATA || join10(home, "AppData", "Roaming");
2806
- return join10(appData, "Construct");
2805
+ const appData = process.env.APPDATA || join11(home, "AppData", "Roaming");
2806
+ return join11(appData, "Construct");
2807
2807
  }
2808
2808
  default: {
2809
- const xdg = process.env.XDG_DATA_HOME || join10(home, ".local", "share");
2810
- return join10(xdg, "construct");
2809
+ const xdg = process.env.XDG_DATA_HOME || join11(home, ".local", "share");
2810
+ return join11(xdg, "construct");
2811
2811
  }
2812
2812
  }
2813
2813
  }
2814
2814
  function profilesDir() {
2815
- return join10(dataDir(), "profiles");
2815
+ return join11(dataDir(), "profiles");
2816
2816
  }
2817
2817
  function activeProfileId() {
2818
2818
  try {
2819
- const credsPath = join10(dataDir(), "credentials.json");
2820
- if (existsSync8(credsPath)) {
2819
+ const credsPath = join11(dataDir(), "credentials.json");
2820
+ if (existsSync9(credsPath)) {
2821
2821
  const c = JSON.parse(readFileSync6(credsPath, "utf-8"));
2822
2822
  if (c.profileId)
2823
2823
  return c.profileId;
2824
2824
  }
2825
2825
  } catch {}
2826
2826
  try {
2827
- const regPath = join10(dataDir(), "profiles.json");
2828
- if (existsSync8(regPath)) {
2827
+ const regPath = join11(dataDir(), "profiles.json");
2828
+ if (existsSync9(regPath)) {
2829
2829
  const r = JSON.parse(readFileSync6(regPath, "utf-8"));
2830
2830
  if (r.active_profile)
2831
2831
  return r.active_profile;
@@ -2836,29 +2836,29 @@ function activeProfileId() {
2836
2836
  function spacesDir() {
2837
2837
  const profileId = activeProfileId();
2838
2838
  if (profileId)
2839
- return join10(profilesDir(), profileId, "spaces");
2840
- return join10(dataDir(), "spaces");
2839
+ return join11(profilesDir(), profileId, "spaces");
2840
+ return join11(dataDir(), "spaces");
2841
2841
  }
2842
2842
  function spaceDir(spaceId) {
2843
- return join10(spacesDir(), spaceId);
2843
+ return join11(spacesDir(), `${spaceId}.space`);
2844
2844
  }
2845
2845
  var init_appdir = () => {};
2846
2846
 
2847
2847
  // src/lib/auth.ts
2848
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, unlinkSync, existsSync as existsSync10, readdirSync as readdirSync5, statSync as statSync3 } from "fs";
2849
- import { join as join12, dirname as dirname4 } from "path";
2848
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync5, mkdirSync as mkdirSync6, unlinkSync, existsSync as existsSync11, readdirSync as readdirSync5, statSync as statSync2 } from "fs";
2849
+ import { join as join13, dirname as dirname5 } from "path";
2850
2850
  function listDesktopProfiles() {
2851
2851
  const dir = profilesDir();
2852
- if (!existsSync10(dir))
2852
+ if (!existsSync11(dir))
2853
2853
  return [];
2854
2854
  const results = [];
2855
2855
  for (const entry of readdirSync5(dir)) {
2856
- const full = join12(dir, entry);
2856
+ const full = join13(dir, entry);
2857
2857
  try {
2858
- if (!statSync3(full).isDirectory())
2858
+ if (!statSync2(full).isDirectory())
2859
2859
  continue;
2860
- const authPath = join12(full, "auth.json");
2861
- if (!existsSync10(authPath))
2860
+ const authPath = join13(full, "auth.json");
2861
+ if (!existsSync11(authPath))
2862
2862
  continue;
2863
2863
  const data = JSON.parse(readFileSync7(authPath, "utf-8"));
2864
2864
  if (!data.token)
@@ -2877,14 +2877,14 @@ function listDesktopProfiles() {
2877
2877
  return results;
2878
2878
  }
2879
2879
  function legacyCredentialsPath() {
2880
- return join12(dataDir(), LEGACY_CREDENTIALS_FILE);
2880
+ return join13(dataDir(), LEGACY_CREDENTIALS_FILE);
2881
2881
  }
2882
2882
  function registryPath() {
2883
- return join12(dataDir(), PROFILES_REGISTRY);
2883
+ return join13(dataDir(), PROFILES_REGISTRY);
2884
2884
  }
2885
2885
  function readRegistry() {
2886
2886
  const path = registryPath();
2887
- if (!existsSync10(path))
2887
+ if (!existsSync11(path))
2888
2888
  return {};
2889
2889
  try {
2890
2890
  return JSON.parse(readFileSync7(path, "utf-8"));
@@ -2894,7 +2894,7 @@ function readRegistry() {
2894
2894
  }
2895
2895
  function writeRegistry(reg) {
2896
2896
  const path = registryPath();
2897
- mkdirSync4(dirname4(path), { recursive: true });
2897
+ mkdirSync6(dirname5(path), { recursive: true });
2898
2898
  writeFileSync5(path, JSON.stringify({ version: 1, ...reg }, null, 2));
2899
2899
  }
2900
2900
  function store(creds) {
@@ -2902,10 +2902,10 @@ function store(creds) {
2902
2902
  if (!profileId) {
2903
2903
  throw new Error("cannot store credentials without a profile id (user.id or profileId)");
2904
2904
  }
2905
- const profilePath = join12(profilesDir(), profileId, "auth.json");
2906
- mkdirSync4(dirname4(profilePath), { recursive: true });
2905
+ const profilePath = join13(profilesDir(), profileId, "auth.json");
2906
+ mkdirSync6(dirname5(profilePath), { recursive: true });
2907
2907
  let existing = {};
2908
- if (existsSync10(profilePath)) {
2908
+ if (existsSync11(profilePath)) {
2909
2909
  try {
2910
2910
  existing = JSON.parse(readFileSync7(profilePath, "utf-8"));
2911
2911
  } catch {}
@@ -2945,7 +2945,7 @@ function store(creds) {
2945
2945
  }
2946
2946
  function migrateLegacyCredentials() {
2947
2947
  const legacy = legacyCredentialsPath();
2948
- if (!existsSync10(legacy))
2948
+ if (!existsSync11(legacy))
2949
2949
  return;
2950
2950
  try {
2951
2951
  const data = JSON.parse(readFileSync7(legacy, "utf-8"));
@@ -2954,8 +2954,8 @@ function migrateLegacyCredentials() {
2954
2954
  const pid = data.profileId || data.user?.id;
2955
2955
  if (!pid)
2956
2956
  return;
2957
- const profilePath = join12(profilesDir(), pid, "auth.json");
2958
- if (existsSync10(profilePath))
2957
+ const profilePath = join13(profilesDir(), pid, "auth.json");
2958
+ if (existsSync11(profilePath))
2959
2959
  return;
2960
2960
  store({ ...data, profileId: pid });
2961
2961
  } catch {}
@@ -2969,15 +2969,15 @@ function load2() {
2969
2969
  }
2970
2970
  function loadFromActiveProfile() {
2971
2971
  try {
2972
- const regPath = join12(dataDir(), "profiles.json");
2973
- if (!existsSync10(regPath))
2972
+ const regPath = join13(dataDir(), "profiles.json");
2973
+ if (!existsSync11(regPath))
2974
2974
  return null;
2975
2975
  const reg = JSON.parse(readFileSync7(regPath, "utf-8"));
2976
2976
  const activeId = reg.active_profile;
2977
2977
  if (!activeId)
2978
2978
  return null;
2979
- const authPath = join12(profilesDir(), activeId, "auth.json");
2980
- if (!existsSync10(authPath))
2979
+ const authPath = join13(profilesDir(), activeId, "auth.json");
2980
+ if (!existsSync11(authPath))
2981
2981
  return null;
2982
2982
  const a = JSON.parse(readFileSync7(authPath, "utf-8"));
2983
2983
  if (!a.token)
@@ -3014,8 +3014,8 @@ function clear() {
3014
3014
  const reg = readRegistry();
3015
3015
  const activeId = reg.active_profile;
3016
3016
  if (activeId) {
3017
- const profilePath = join12(profilesDir(), activeId, "auth.json");
3018
- if (existsSync10(profilePath)) {
3017
+ const profilePath = join13(profilesDir(), activeId, "auth.json");
3018
+ if (existsSync11(profilePath)) {
3019
3019
  try {
3020
3020
  const data = JSON.parse(readFileSync7(profilePath, "utf-8"));
3021
3021
  data.authenticated = false;
@@ -3025,7 +3025,7 @@ function clear() {
3025
3025
  }
3026
3026
  }
3027
3027
  const legacy = legacyCredentialsPath();
3028
- if (existsSync10(legacy))
3028
+ if (existsSync11(legacy))
3029
3029
  unlinkSync(legacy);
3030
3030
  }
3031
3031
  var LEGACY_CREDENTIALS_FILE = "credentials.json", PROFILES_REGISTRY = "profiles.json", DEFAULT_PORTAL = "https://my.construct.space/api/developer";
@@ -5453,6 +5453,8 @@ async function scaffold(nameArg, options) {
5453
5453
  join2(name, "scripts"),
5454
5454
  join2(name, "references"),
5455
5455
  join2(name, "assets"),
5456
+ join2(name, "tools"),
5457
+ join2(name, "lib"),
5456
5458
  join2(name, "agent", "hooks"),
5457
5459
  join2(name, "agent", "tools"),
5458
5460
  join2(name, "widgets", "summary")
@@ -5516,9 +5518,9 @@ async function scaffold(nameArg, options) {
5516
5518
 
5517
5519
  // src/commands/build.ts
5518
5520
  init_source();
5519
- import { cpSync, existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync3, renameSync, statSync as statSync2 } from "fs";
5520
- import { join as join6 } from "path";
5521
- import { createHash } from "crypto";
5521
+ import { existsSync as existsSync7, readFileSync as readFileSync4, readdirSync as readdirSync3, renameSync, rmSync as rmSync2 } from "fs";
5522
+ import { join as join7 } from "path";
5523
+ import { createHash as createHash2 } from "crypto";
5522
5524
 
5523
5525
  // node_modules/ora/index.js
5524
5526
  init_source();
@@ -8154,6 +8156,7 @@ function ora(options) {
8154
8156
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync3 } from "fs";
8155
8157
  import { join as join3 } from "path";
8156
8158
  var MANIFEST_FILE = "space.manifest.json";
8159
+ var HOST_API_VERSION = "0.6.0";
8157
8160
  var idRegex = /^[a-z][a-z0-9-]*$/;
8158
8161
  var versionRegex = /^\d+\.\d+\.\d+/;
8159
8162
  function validate2(m) {
@@ -8362,74 +8365,216 @@ function writeEntry(root, m) {
8362
8365
  writeFileSync3(join4(srcDir, "entry.ts"), generate(root, m));
8363
8366
  }
8364
8367
 
8365
- // src/lib/agent.ts
8366
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, readdirSync as readdirSync2, existsSync as existsSync5 } from "fs";
8367
- import { join as join5, extname as extname2, basename as basename2 } from "path";
8368
- var AGENT_KEY = "construct-agent-obfuscate-v1";
8369
- function encode(content) {
8370
- const key = Buffer.from(AGENT_KEY);
8371
- const data = Buffer.from(content);
8372
- const xored = Buffer.alloc(data.length);
8373
- for (let i = 0;i < data.length; i++) {
8374
- xored[i] = data[i] ^ key[i % key.length];
8375
- }
8376
- return xored.toString("base64");
8377
- }
8378
- function readMdFiles(dir) {
8379
- const result = {};
8380
- if (!existsSync5(dir))
8381
- return result;
8382
- for (const f of readdirSync2(dir)) {
8383
- if (extname2(f) !== ".md")
8368
+ // src/lib/spaceBundle.ts
8369
+ import { createHash } from "crypto";
8370
+ import { cpSync, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync3, readFileSync as readFileSync3, readdirSync as readdirSync2, rmSync, writeFileSync as writeFileSync4 } from "fs";
8371
+ import { basename as basename2, dirname as dirname2, join as join5, relative as relative2 } from "path";
8372
+ var BUNDLE_DIRS = ["agent", "scripts", "references", "assets", "icons", "media", "public", "tools", "lib"];
8373
+ var BUNDLE_FILES = ["SKILL.md"];
8374
+ function stageSpaceResources(root, distDir) {
8375
+ const copied = [];
8376
+ for (const name of BUNDLE_DIRS) {
8377
+ rmSync(join5(distDir, name), { recursive: true, force: true });
8378
+ const src = join5(root, name);
8379
+ if (!existsSync5(src) || !lstatSync(src).isDirectory())
8384
8380
  continue;
8385
- result[basename2(f, ".md")] = readFileSync3(join5(dir, f), "utf-8");
8381
+ cpSync(src, join5(distDir, name), { recursive: true, verbatimSymlinks: true });
8382
+ copied.push(name);
8386
8383
  }
8387
- return result;
8384
+ for (const name of BUNDLE_FILES) {
8385
+ rmSync(join5(distDir, name), { recursive: true, force: true });
8386
+ const src = join5(root, name);
8387
+ if (!existsSync5(src) || !lstatSync(src).isFile())
8388
+ continue;
8389
+ cpSync(src, join5(distDir, name), { verbatimSymlinks: true });
8390
+ copied.push(name);
8391
+ }
8392
+ return copied;
8388
8393
  }
8389
- function readJsonFiles(dir) {
8390
- const result = {};
8391
- if (!existsSync5(dir))
8392
- return result;
8393
- for (const f of readdirSync2(dir)) {
8394
- if (extname2(f) !== ".json")
8394
+ function slashPath(path) {
8395
+ return path.replace(/\\/g, "/");
8396
+ }
8397
+ function copyFileIntoBundle(src, dst) {
8398
+ mkdirSync3(dirname2(dst), { recursive: true });
8399
+ cpSync(src, dst, { verbatimSymlinks: true });
8400
+ }
8401
+ function collectFiles(root) {
8402
+ const files = [];
8403
+ function walk(dir) {
8404
+ for (const name of readdirSync2(dir).sort()) {
8405
+ const path = join5(dir, name);
8406
+ const stat = lstatSync(path);
8407
+ if (stat.isSymbolicLink())
8408
+ continue;
8409
+ if (stat.isDirectory()) {
8410
+ walk(path);
8411
+ } else if (stat.isFile()) {
8412
+ files.push(slashPath(relative2(root, path)));
8413
+ }
8414
+ }
8415
+ }
8416
+ walk(root);
8417
+ return files;
8418
+ }
8419
+ function sha256(path) {
8420
+ return createHash("sha256").update(readFileSync3(path)).digest("hex");
8421
+ }
8422
+ function writeChecksums(spaceDir, spaceId) {
8423
+ const files = collectFiles(spaceDir).filter((file) => file !== "checksums.json");
8424
+ const checksums = {};
8425
+ for (const file of files) {
8426
+ checksums[file] = sha256(join5(spaceDir, file));
8427
+ }
8428
+ writeFileSync4(join5(spaceDir, "checksums.json"), JSON.stringify({
8429
+ format: "construct.space/v1",
8430
+ id: spaceId,
8431
+ files: checksums
8432
+ }, null, 2) + `
8433
+ `);
8434
+ return collectFiles(spaceDir);
8435
+ }
8436
+ function createSpaceBundle(options) {
8437
+ const spaceDir = join5(options.distDir, `${options.spaceId}.space`);
8438
+ const appName = basename2(options.appBundlePath);
8439
+ const cssName = options.cssPath ? basename2(options.cssPath) : "";
8440
+ rmSync(spaceDir, { recursive: true, force: true });
8441
+ mkdirSync3(spaceDir, { recursive: true });
8442
+ copyFileIntoBundle(join5(options.distDir, "manifest.json"), join5(spaceDir, "manifest.json"));
8443
+ copyFileIntoBundle(options.appBundlePath, join5(spaceDir, "app.iife.js"));
8444
+ const hasStyle = Boolean(options.cssPath && existsSync5(options.cssPath));
8445
+ if (hasStyle && options.cssPath) {
8446
+ copyFileIntoBundle(options.cssPath, join5(spaceDir, "style.css"));
8447
+ }
8448
+ for (const entry of readdirSync2(options.distDir)) {
8449
+ if (entry === `${options.spaceId}.space`)
8395
8450
  continue;
8396
- result[basename2(f, ".json")] = readFileSync3(join5(dir, f), "utf-8");
8451
+ if (entry.endsWith(".space"))
8452
+ continue;
8453
+ if (entry === "manifest.json")
8454
+ continue;
8455
+ if (entry === appName || entry === cssName)
8456
+ continue;
8457
+ if (entry.endsWith(".iife.js") || entry.endsWith(".css"))
8458
+ continue;
8459
+ cpSync(join5(options.distDir, entry), join5(spaceDir, entry), {
8460
+ recursive: true,
8461
+ verbatimSymlinks: true
8462
+ });
8397
8463
  }
8398
- return result;
8464
+ return {
8465
+ dir: spaceDir,
8466
+ hasStyle,
8467
+ files: writeChecksums(spaceDir, options.spaceId)
8468
+ };
8399
8469
  }
8400
- function bundleAgentDir(srcDir, distDir) {
8401
- const bundle = {
8402
- config: "",
8403
- tools: readMdFiles(join5(srcDir, "tools")),
8404
- skills: readMdFiles(join5(srcDir, "skills")),
8405
- hooks: readJsonFiles(join5(srcDir, "hooks"))
8470
+
8471
+ // src/lib/spaceTools.ts
8472
+ import { existsSync as existsSync6, mkdirSync as mkdirSync4 } from "fs";
8473
+ import { join as join6 } from "path";
8474
+ import { arch as nodeArch, platform as nodePlatform } from "process";
8475
+ import { spawnSync } from "child_process";
8476
+ var SPACE_TOOL_TARGETS = [
8477
+ "darwin-arm64",
8478
+ "darwin-x64",
8479
+ "linux-arm64",
8480
+ "linux-x64",
8481
+ "windows-arm64",
8482
+ "windows-x64"
8483
+ ];
8484
+ var GO_TARGETS = {
8485
+ "darwin-arm64": { goos: "darwin", goarch: "arm64", ext: "" },
8486
+ "darwin-x64": { goos: "darwin", goarch: "amd64", ext: "" },
8487
+ "linux-arm64": { goos: "linux", goarch: "arm64", ext: "" },
8488
+ "linux-x64": { goos: "linux", goarch: "amd64", ext: "" },
8489
+ "windows-arm64": { goos: "windows", goarch: "arm64", ext: ".exe" },
8490
+ "windows-x64": { goos: "windows", goarch: "amd64", ext: ".exe" }
8491
+ };
8492
+ function isSpaceToolTarget(value) {
8493
+ return SPACE_TOOL_TARGETS.includes(value);
8494
+ }
8495
+ function currentSpaceToolTarget(platform = nodePlatform, arch = nodeArch) {
8496
+ if (platform === "darwin" && arch === "arm64")
8497
+ return "darwin-arm64";
8498
+ if (platform === "darwin" && arch === "x64")
8499
+ return "darwin-x64";
8500
+ if (platform === "linux" && arch === "arm64")
8501
+ return "linux-arm64";
8502
+ if (platform === "linux" && arch === "x64")
8503
+ return "linux-x64";
8504
+ if (platform === "win32" && arch === "arm64")
8505
+ return "windows-arm64";
8506
+ if (platform === "win32" && arch === "x64")
8507
+ return "windows-x64";
8508
+ return null;
8509
+ }
8510
+ function parseSpaceToolTargets(value = process.env.CONSTRUCT_TOOL_TARGETS) {
8511
+ const raw = value?.trim();
8512
+ if (!raw) {
8513
+ const current = currentSpaceToolTarget();
8514
+ if (!current)
8515
+ throw new Error(`Unsupported tool build platform: ${nodePlatform}-${nodeArch}`);
8516
+ return [current];
8517
+ }
8518
+ if (raw === "all")
8519
+ return [...SPACE_TOOL_TARGETS];
8520
+ const targets = raw.split(/[,\s]+/).filter(Boolean);
8521
+ const invalid = targets.filter((target) => !isSpaceToolTarget(target));
8522
+ if (invalid.length > 0) {
8523
+ throw new Error(`Invalid CONSTRUCT_TOOL_TARGETS value: ${invalid.join(", ")}. ` + `Expected one or more of: ${SPACE_TOOL_TARGETS.join(", ")}, or "all".`);
8524
+ }
8525
+ return Array.from(new Set(targets));
8526
+ }
8527
+ function defaultRunner(invocation) {
8528
+ const result = spawnSync("go", invocation.args, {
8529
+ cwd: invocation.root,
8530
+ env: invocation.env,
8531
+ encoding: "utf-8"
8532
+ });
8533
+ return {
8534
+ status: result.status,
8535
+ stdout: result.stdout || "",
8536
+ stderr: result.stderr || "",
8537
+ error: result.error
8406
8538
  };
8407
- for (const name of ["config.md", "agent.md"]) {
8408
- const path = join5(srcDir, name);
8409
- if (existsSync5(path)) {
8410
- bundle.config = readFileSync3(path, "utf-8");
8411
- break;
8539
+ }
8540
+ function buildSpaceTools(root, distDir, spaceId, options = {}) {
8541
+ const sourcePath = join6(root, "tools.go");
8542
+ if (!existsSync6(sourcePath))
8543
+ return [];
8544
+ const built = [];
8545
+ const targets = options.targets ?? parseSpaceToolTargets(options.env?.CONSTRUCT_TOOL_TARGETS);
8546
+ const runner = options.runner ?? defaultRunner;
8547
+ for (const target of targets) {
8548
+ const goTarget = GO_TARGETS[target];
8549
+ const outputDir = join6(distDir, "tools", target);
8550
+ const outputName = `${spaceId}-tools${goTarget.ext}`;
8551
+ const outputPath = join6(outputDir, outputName);
8552
+ mkdirSync4(outputDir, { recursive: true });
8553
+ const env2 = {
8554
+ ...process.env,
8555
+ ...options.env,
8556
+ GOOS: goTarget.goos,
8557
+ GOARCH: goTarget.goarch
8558
+ };
8559
+ if (!env2.CGO_ENABLED)
8560
+ env2.CGO_ENABLED = "0";
8561
+ const args = ["build", "-trimpath", "-o", outputPath, "./tools.go"];
8562
+ const result = runner({ root, target, outputPath, args, env: env2 });
8563
+ if (result.error) {
8564
+ throw new Error(`Failed to build tools.go for ${target}: ${result.error.message}`);
8412
8565
  }
8566
+ if (result.status !== 0) {
8567
+ const details = [result.stderr, result.stdout].filter(Boolean).join(`
8568
+ `).trim();
8569
+ throw new Error(`Failed to build tools.go for ${target}${details ? `:
8570
+ ${details}` : ""}`);
8571
+ }
8572
+ built.push(`tools/${target}/${outputName}`);
8413
8573
  }
8414
- if (!bundle.config)
8415
- return;
8416
- const encoded = encode(JSON.stringify(bundle));
8417
- writeFileSync4(join5(distDir, "config.agent"), encoded);
8574
+ return built;
8418
8575
  }
8419
8576
 
8420
8577
  // src/commands/build.ts
8421
- var ASSET_DIRS = ["icons", "assets", "media", "public", "bin"];
8422
- function copyAssetDirs(root, distDir) {
8423
- const copied = [];
8424
- for (const name of ASSET_DIRS) {
8425
- const src = join6(root, name);
8426
- if (!existsSync6(src) || !statSync2(src).isDirectory())
8427
- continue;
8428
- cpSync(src, join6(distDir, name), { recursive: true, verbatimSymlinks: true });
8429
- copied.push(name);
8430
- }
8431
- return copied;
8432
- }
8433
8578
  function stripTsComments(source) {
8434
8579
  let out = "";
8435
8580
  let i = 0;
@@ -8629,41 +8774,52 @@ async function build(options) {
8629
8774
  process.exit(1);
8630
8775
  }
8631
8776
  runHook(m.hooks, "postBuild", root);
8632
- const agentDir = join6(root, "agent");
8633
- if (existsSync6(agentDir) && statSync2(agentDir).isDirectory()) {
8634
- const distDir2 = join6(root, "dist");
8635
- bundleAgentDir(agentDir, distDir2);
8636
- bundleAgentDir(agentDir, root);
8777
+ const copiedResources = stageSpaceResources(root, join7(root, "dist"));
8778
+ if (copiedResources.length > 0) {
8779
+ console.log(source_default.blue(` Resources: ${copiedResources.join(", ")}`));
8637
8780
  }
8638
- const copiedAssetDirs = copyAssetDirs(root, join6(root, "dist"));
8639
- if (copiedAssetDirs.length > 0) {
8640
- console.log(source_default.blue(` Assets: ${copiedAssetDirs.join(", ")}`));
8781
+ try {
8782
+ const builtTools = buildSpaceTools(root, join7(root, "dist"), m.id);
8783
+ if (builtTools.length > 0) {
8784
+ console.log(source_default.blue(` Tools: ${builtTools.join(", ")}`));
8785
+ }
8786
+ } catch (err) {
8787
+ console.error(source_default.red(err?.message || String(err)));
8788
+ process.exit(1);
8641
8789
  }
8642
- const distDir = join6(root, "dist");
8790
+ const distDir = join7(root, "dist");
8643
8791
  const expectedBundle = `space-${m.id}.iife.js`;
8644
- const bundlePath = join6(distDir, expectedBundle);
8645
- if (!existsSync6(bundlePath)) {
8792
+ const bundlePath = join7(distDir, expectedBundle);
8793
+ if (!existsSync7(bundlePath)) {
8646
8794
  const matches = readdirSync3(distDir).filter((f) => f.startsWith("space-") && f.endsWith(".iife.js"));
8647
8795
  if (matches.length === 1) {
8648
- renameSync(join6(distDir, matches[0]), bundlePath);
8649
- const oldCSS = join6(distDir, matches[0].replace(".iife.js", ".css"));
8650
- const newCSS = join6(distDir, `space-${m.id}.css`);
8651
- if (existsSync6(oldCSS))
8796
+ renameSync(join7(distDir, matches[0]), bundlePath);
8797
+ const oldCSS = join7(distDir, matches[0].replace(".iife.js", ".css"));
8798
+ const newCSS = join7(distDir, `space-${m.id}.css`);
8799
+ if (existsSync7(oldCSS))
8652
8800
  renameSync(oldCSS, newCSS);
8653
8801
  }
8654
8802
  }
8655
- const expectedCSS = join6(distDir, `space-${m.id}.css`);
8656
- if (!existsSync6(expectedCSS)) {
8803
+ if (!existsSync7(bundlePath)) {
8804
+ console.error(source_default.red(`Build did not emit ${expectedBundle}`));
8805
+ process.exit(1);
8806
+ }
8807
+ const expectedCSS = join7(distDir, `space-${m.id}.css`);
8808
+ if (!existsSync7(expectedCSS)) {
8657
8809
  const cssMatches = readdirSync3(distDir).filter((f) => f.endsWith(".css"));
8658
8810
  const renamedCSS = cssMatches.find((f) => f.startsWith("space-")) || (cssMatches.length === 1 ? cssMatches[0] : undefined);
8659
8811
  if (renamedCSS)
8660
- renameSync(join6(distDir, renamedCSS), expectedCSS);
8812
+ renameSync(join7(distDir, renamedCSS), expectedCSS);
8813
+ }
8814
+ if (!existsSync7(expectedCSS)) {
8815
+ console.error(source_default.red(`Build did not emit CSS. Spaces must import src/style.css so pages and widgets are self-contained.`));
8816
+ process.exit(1);
8661
8817
  }
8662
8818
  const bundleData = readFileSync4(bundlePath);
8663
- const checksum = createHash("sha256").update(bundleData).digest("hex");
8819
+ const checksum = createHash2("sha256").update(bundleData).digest("hex");
8664
8820
  const raw = readRaw(root);
8665
- const actionsPath = join6(root, "src", "actions.ts");
8666
- if (existsSync6(actionsPath)) {
8821
+ const actionsPath = join7(root, "src", "actions.ts");
8822
+ if (existsSync7(actionsPath)) {
8667
8823
  const actionMeta = extractActionMetadata(actionsPath);
8668
8824
  if (actionMeta && Object.keys(actionMeta).length > 0) {
8669
8825
  raw.actions = actionMeta;
@@ -8673,17 +8829,29 @@ async function build(options) {
8673
8829
  writeWithBuild(distDir, raw, {
8674
8830
  checksum,
8675
8831
  size: bundleData.length,
8676
- hostApiVersion: "0.5.0",
8832
+ hostApiVersion: HOST_API_VERSION,
8677
8833
  builtAt: new Date().toISOString()
8678
8834
  });
8679
- console.log(source_default.green(`Built ${m.name} v${m.version}`));
8835
+ const spaceBundle = createSpaceBundle({
8836
+ distDir,
8837
+ spaceId: m.id,
8838
+ appBundlePath: bundlePath,
8839
+ cssPath: expectedCSS
8840
+ });
8841
+ for (const entry of readdirSync3(distDir)) {
8842
+ if (entry === `${m.id}.space`)
8843
+ continue;
8844
+ rmSync2(join7(distDir, entry), { recursive: true, force: true });
8845
+ }
8846
+ console.log(source_default.green(`Built ${m.name} v${m.version} -> dist/${m.id}.space`));
8847
+ console.log(source_default.dim(` ${spaceBundle.files.length} files, ${spaceBundle.hasStyle ? "style.css included" : "no style.css"}`));
8680
8848
  }
8681
8849
 
8682
8850
  // src/commands/dev.ts
8683
8851
  init_source();
8684
- import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
8685
- import { join as join9 } from "path";
8686
- import { createHash as createHash2 } from "crypto";
8852
+ import { existsSync as existsSync8, readFileSync as readFileSync5 } from "fs";
8853
+ import { join as join10 } from "path";
8854
+ import { createHash as createHash3 } from "crypto";
8687
8855
 
8688
8856
  // node_modules/chokidar/index.js
8689
8857
  import { EventEmitter } from "events";
@@ -9413,9 +9581,9 @@ class NodeFsHandler {
9413
9581
  if (this.fsw.closed) {
9414
9582
  return;
9415
9583
  }
9416
- const dirname3 = sp.dirname(file);
9584
+ const dirname4 = sp.dirname(file);
9417
9585
  const basename4 = sp.basename(file);
9418
- const parent = this.fsw._getWatchedDir(dirname3);
9586
+ const parent = this.fsw._getWatchedDir(dirname4);
9419
9587
  let prevStats = stats;
9420
9588
  if (parent.has(basename4))
9421
9589
  return;
@@ -9442,7 +9610,7 @@ class NodeFsHandler {
9442
9610
  prevStats = newStats2;
9443
9611
  }
9444
9612
  } catch (error2) {
9445
- this.fsw._remove(dirname3, basename4);
9613
+ this.fsw._remove(dirname4, basename4);
9446
9614
  }
9447
9615
  } else if (parent.has(basename4)) {
9448
9616
  const at = newStats.atimeMs;
@@ -9665,11 +9833,11 @@ function createPattern(matcher) {
9665
9833
  if (matcher.path === string)
9666
9834
  return true;
9667
9835
  if (matcher.recursive) {
9668
- const relative4 = sp2.relative(matcher.path, string);
9669
- if (!relative4) {
9836
+ const relative5 = sp2.relative(matcher.path, string);
9837
+ if (!relative5) {
9670
9838
  return false;
9671
9839
  }
9672
- return !relative4.startsWith("..") && !sp2.isAbsolute(relative4);
9840
+ return !relative5.startsWith("..") && !sp2.isAbsolute(relative5);
9673
9841
  }
9674
9842
  return false;
9675
9843
  };
@@ -10299,8 +10467,8 @@ function watch(paths, options = {}) {
10299
10467
  // src/commands/dev.ts
10300
10468
  function getEntryWatchPaths(root) {
10301
10469
  return [
10302
- join9(root, MANIFEST_FILE),
10303
- join9(root, "src", "actions.ts")
10470
+ join10(root, MANIFEST_FILE),
10471
+ join10(root, "src", "actions.ts")
10304
10472
  ];
10305
10473
  }
10306
10474
  async function dev() {
@@ -10339,26 +10507,59 @@ async function dev() {
10339
10507
  }
10340
10508
  console.log(source_default.blue("Actions changed -- entry regenerated"));
10341
10509
  });
10342
- const distDir = join9(root, "dist");
10343
- const bundleFile = join9(distDir, `space-${m.id}.iife.js`);
10510
+ const distDir = join10(root, "dist");
10511
+ const bundleFile = join10(distDir, `space-${m.id}.iife.js`);
10512
+ const cssFile = join10(distDir, `space-${m.id}.css`);
10344
10513
  let lastChecksum = "";
10345
- const distWatcher = watch(bundleFile, { ignoreInitial: false });
10346
- distWatcher.on("all", () => {
10347
- if (!existsSync7(bundleFile))
10514
+ const packageSpace = (force = false) => {
10515
+ if (!existsSync8(bundleFile) || !existsSync8(cssFile))
10348
10516
  return;
10349
10517
  const bundleData = readFileSync5(bundleFile);
10350
- const checksum = createHash2("sha256").update(bundleData).digest("hex");
10351
- if (checksum === lastChecksum)
10518
+ const checksum = createHash3("sha256").update(bundleData).digest("hex");
10519
+ if (!force && checksum === lastChecksum)
10352
10520
  return;
10353
10521
  lastChecksum = checksum;
10354
10522
  const raw = readRaw(root);
10355
10523
  writeWithBuild(distDir, raw, {
10356
10524
  checksum,
10357
10525
  size: bundleData.length,
10358
- hostApiVersion: "0.5.0",
10526
+ hostApiVersion: HOST_API_VERSION,
10359
10527
  builtAt: new Date().toISOString()
10360
10528
  });
10361
- console.log(source_default.green(`Built -> dist/ (${(bundleData.length / 1024).toFixed(1)} KB)`));
10529
+ stageSpaceResources(root, distDir);
10530
+ buildSpaceTools(root, distDir, m.id);
10531
+ createSpaceBundle({
10532
+ distDir,
10533
+ spaceId: m.id,
10534
+ appBundlePath: bundleFile,
10535
+ cssPath: cssFile
10536
+ });
10537
+ console.log(source_default.green(`Built -> dist/${m.id}.space (${(bundleData.length / 1024).toFixed(1)} KB)`));
10538
+ };
10539
+ const distWatcher = watch([bundleFile, cssFile], { ignoreInitial: false });
10540
+ distWatcher.on("all", () => {
10541
+ try {
10542
+ packageSpace();
10543
+ } catch (err) {
10544
+ console.error(source_default.red(err?.message || String(err)));
10545
+ }
10546
+ });
10547
+ const resourceWatcher = watch([
10548
+ join10(root, "tools.go"),
10549
+ join10(root, "tools"),
10550
+ join10(root, "lib"),
10551
+ join10(root, "agent"),
10552
+ join10(root, "scripts"),
10553
+ join10(root, "references"),
10554
+ join10(root, "assets"),
10555
+ join10(root, "SKILL.md")
10556
+ ], { ignoreInitial: true });
10557
+ resourceWatcher.on("all", () => {
10558
+ try {
10559
+ packageSpace(true);
10560
+ } catch (err) {
10561
+ console.error(source_default.red(err?.message || String(err)));
10562
+ }
10362
10563
  });
10363
10564
  console.log(source_default.green("Watching for changes... (Ctrl+C to stop)"));
10364
10565
  console.log(source_default.dim("Use the Preview button in Construct to open the Space Runner"));
@@ -10367,19 +10568,16 @@ async function dev() {
10367
10568
 
10368
10569
  // src/commands/run.ts
10369
10570
  init_source();
10370
- import { existsSync as existsSync9, cpSync as cpSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync4, chmodSync, lstatSync, rmSync } from "fs";
10371
- import { join as join11 } from "path";
10571
+ import { existsSync as existsSync10, cpSync as cpSync2, mkdirSync as mkdirSync5, readdirSync as readdirSync4, chmodSync, lstatSync as lstatSync2, rmSync as rmSync3 } from "fs";
10572
+ import { join as join12 } from "path";
10372
10573
  init_appdir();
10373
- function ensureBinExecutable(installDir) {
10574
+ function ensureExecutableResources(installDir) {
10374
10575
  if (process.platform === "win32")
10375
10576
  return;
10376
- const binRoot = join11(installDir, "bin");
10377
- if (!existsSync9(binRoot))
10378
- return;
10379
10577
  const walk = (dir) => {
10380
10578
  for (const name of readdirSync4(dir)) {
10381
- const path = join11(dir, name);
10382
- const st = lstatSync(path);
10579
+ const path = join12(dir, name);
10580
+ const st = lstatSync2(path);
10383
10581
  if (st.isSymbolicLink())
10384
10582
  continue;
10385
10583
  if (st.isDirectory()) {
@@ -10389,7 +10587,11 @@ function ensureBinExecutable(installDir) {
10389
10587
  }
10390
10588
  }
10391
10589
  };
10392
- walk(binRoot);
10590
+ for (const dirname5 of ["tools", "lib"]) {
10591
+ const root = join12(installDir, dirname5);
10592
+ if (existsSync10(root))
10593
+ walk(root);
10594
+ }
10393
10595
  }
10394
10596
  function install() {
10395
10597
  const root = process.cwd();
@@ -10397,34 +10599,36 @@ function install() {
10397
10599
  console.error(source_default.red("No space.manifest.json found in current directory"));
10398
10600
  process.exit(1);
10399
10601
  }
10400
- const distDir = join11(root, "dist");
10401
- if (!existsSync9(distDir)) {
10602
+ const distDir = join12(root, "dist");
10603
+ if (!existsSync10(distDir)) {
10402
10604
  console.error(source_default.red("No dist/ directory found. Run 'construct build' first."));
10403
10605
  process.exit(1);
10404
10606
  }
10405
10607
  const m = read(root);
10406
- const agentDir = join11(root, "agent");
10407
- if (existsSync9(agentDir)) {
10408
- bundleAgentDir(agentDir, distDir);
10608
+ const bundleDir = join12(distDir, `${m.id}.space`);
10609
+ if (!existsSync10(bundleDir)) {
10610
+ console.error(source_default.red(`No dist/${m.id}.space directory found. Run 'construct build' first.`));
10611
+ process.exit(1);
10409
10612
  }
10410
10613
  const installDir = spaceDir(m.id);
10411
- rmSync(installDir, { recursive: true, force: true });
10412
- mkdirSync3(installDir, { recursive: true });
10413
- cpSync2(distDir, installDir, { recursive: true, verbatimSymlinks: true, force: true });
10414
- ensureBinExecutable(installDir);
10614
+ rmSync3(join12(spacesDir(), m.id), { recursive: true, force: true });
10615
+ rmSync3(installDir, { recursive: true, force: true });
10616
+ mkdirSync5(installDir, { recursive: true });
10617
+ cpSync2(bundleDir, installDir, { recursive: true, verbatimSymlinks: true, force: true });
10618
+ ensureExecutableResources(installDir);
10415
10619
  console.log(source_default.green(`Installed ${m.name} -> ${installDir}`));
10416
10620
  console.log(source_default.dim(" Restart Construct to load the updated space."));
10417
10621
  }
10418
10622
 
10419
10623
  // src/commands/publish.ts
10420
10624
  init_source();
10421
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, statSync as statSync5, unlinkSync as unlinkSync2 } from "fs";
10422
- import { join as join14, basename as basename5 } from "path";
10625
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync6, statSync as statSync4, unlinkSync as unlinkSync2 } from "fs";
10626
+ import { join as join15, basename as basename5 } from "path";
10423
10627
  init_auth();
10424
10628
 
10425
10629
  // src/lib/pack.ts
10426
- import { readdirSync as readdirSync6, statSync as statSync4, existsSync as existsSync11 } from "fs";
10427
- import { join as join13 } from "path";
10630
+ import { readdirSync as readdirSync6, statSync as statSync3, existsSync as existsSync12 } from "fs";
10631
+ import { join as join14 } from "path";
10428
10632
  import { tmpdir } from "os";
10429
10633
  import { execFileSync as execFileSync2 } from "child_process";
10430
10634
  var allowedDirs = [
@@ -10447,7 +10651,9 @@ var allowedDirs = [
10447
10651
  "icons",
10448
10652
  "assets",
10449
10653
  "media",
10450
- "bin"
10654
+ "tools",
10655
+ "lib",
10656
+ "go-tools"
10451
10657
  ];
10452
10658
  var allowedRootFiles = [
10453
10659
  "space.manifest.json",
@@ -10457,20 +10663,24 @@ var allowedRootFiles = [
10457
10663
  "vite.config.js",
10458
10664
  "space.config.ts",
10459
10665
  "types.ts",
10460
- "index.ts"
10666
+ "index.ts",
10667
+ "SKILL.md",
10668
+ "tools.go",
10669
+ "go.mod",
10670
+ "go.sum"
10461
10671
  ];
10462
10672
  var allowedRootPatterns = [/.*\.config\.ts$/, /.*\.config\.js$/];
10463
10673
  var blockedExtensions = [".env", ".log", ".lock", ".lockb"];
10464
10674
  var MAX_SIZE = 50 * 1024 * 1024;
10465
10675
  async function packSource(root) {
10466
- const tarballPath = join13(tmpdir(), `space-source-${Date.now()}.tar.gz`);
10676
+ const tarballPath = join14(tmpdir(), `space-source-${Date.now()}.tar.gz`);
10467
10677
  const entries = [];
10468
10678
  for (const name of allowedRootFiles) {
10469
- if (existsSync11(join13(root, name)))
10679
+ if (existsSync12(join14(root, name)))
10470
10680
  entries.push(name);
10471
10681
  }
10472
10682
  for (const entry of readdirSync6(root)) {
10473
- if (statSync4(join13(root, entry)).isDirectory())
10683
+ if (statSync3(join14(root, entry)).isDirectory())
10474
10684
  continue;
10475
10685
  if (allowedRootFiles.includes(entry))
10476
10686
  continue;
@@ -10480,10 +10690,10 @@ async function packSource(root) {
10480
10690
  entries.push(entry);
10481
10691
  }
10482
10692
  for (const dir of allowedDirs) {
10483
- if (existsSync11(join13(root, dir)))
10693
+ if (existsSync12(join14(root, dir)))
10484
10694
  entries.push(dir);
10485
10695
  }
10486
- const validEntries = entries.filter((e) => existsSync11(join13(root, e)));
10696
+ const validEntries = entries.filter((e) => existsSync12(join14(root, e)));
10487
10697
  if (validEntries.length === 0) {
10488
10698
  throw new Error("No files to pack");
10489
10699
  }
@@ -10491,13 +10701,15 @@ async function packSource(root) {
10491
10701
  "--exclude=node_modules",
10492
10702
  "--exclude=dist",
10493
10703
  "--exclude=.git",
10704
+ "--exclude=go-tools/spaceprobe",
10705
+ "--exclude=go-tools/spaceprobe.exe",
10494
10706
  "--exclude=*.env",
10495
10707
  "--exclude=*.log",
10496
10708
  "--exclude=*.lock",
10497
10709
  "--exclude=*.lockb"
10498
10710
  ];
10499
10711
  execFileSync2("tar", ["czf", tarballPath, ...excludes, ...validEntries], { cwd: root });
10500
- const size = statSync4(tarballPath).size;
10712
+ const size = statSync3(tarballPath).size;
10501
10713
  if (size > MAX_SIZE) {
10502
10714
  throw new Error(`Source exceeds maximum size of ${MAX_SIZE / 1024 / 1024}MB`);
10503
10715
  }
@@ -10576,7 +10788,7 @@ function setVersionInFiles(root, oldVer, newVer) {
10576
10788
  const oldStr = `"version": "${oldVer}"`;
10577
10789
  const newStr = `"version": "${newVer}"`;
10578
10790
  for (const file of ["package.json", "space.manifest.json"]) {
10579
- const path = join14(root, file);
10791
+ const path = join15(root, file);
10580
10792
  try {
10581
10793
  const data = readFileSync8(path, "utf-8");
10582
10794
  writeFileSync6(path, data.replace(oldStr, newStr));
@@ -10735,7 +10947,7 @@ async function publish(options) {
10735
10947
  let tarballPath;
10736
10948
  try {
10737
10949
  tarballPath = await packSource(root);
10738
- const size = statSync5(tarballPath).size;
10950
+ const size = statSync4(tarballPath).size;
10739
10951
  spinner.succeed(`Source packed (${formatBytes(size)})`);
10740
10952
  } catch (err) {
10741
10953
  spinner.fail("Pack failed");
@@ -10803,8 +11015,8 @@ async function publish(options) {
10803
11015
 
10804
11016
  // src/commands/validate.ts
10805
11017
  init_source();
10806
- import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
10807
- import { join as join15 } from "path";
11018
+ import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
11019
+ import { join as join16 } from "path";
10808
11020
 
10809
11021
  // src/lib/pagePaths.ts
10810
11022
  function pageComponentFromPath(path) {
@@ -10838,21 +11050,21 @@ function validate3() {
10838
11050
  let warnings = 0;
10839
11051
  for (const page of m.pages) {
10840
11052
  const component = page.component || pageComponentFromPath(page.path);
10841
- const fullPath = join15(root, "src", component);
10842
- if (!existsSync12(fullPath)) {
11053
+ const fullPath = join16(root, "src", component);
11054
+ if (!existsSync13(fullPath)) {
10843
11055
  console.log(source_default.yellow(` \u26A0 Page component not found: src/${component}`));
10844
11056
  warnings++;
10845
11057
  }
10846
11058
  }
10847
11059
  if (m.agent) {
10848
- const agentPath = join15(root, m.agent);
10849
- if (!existsSync12(agentPath)) {
11060
+ const agentPath = join16(root, m.agent);
11061
+ if (!existsSync13(agentPath)) {
10850
11062
  console.log(source_default.yellow(` \u26A0 Agent config not found: ${m.agent}`));
10851
11063
  warnings++;
10852
11064
  }
10853
11065
  }
10854
- const pkgPath = join15(root, "package.json");
10855
- if (existsSync12(pkgPath)) {
11066
+ const pkgPath = join16(root, "package.json");
11067
+ if (existsSync13(pkgPath)) {
10856
11068
  const pkg = JSON.parse(readFileSync9(pkgPath, "utf-8"));
10857
11069
  if (pkg.version && pkg.version !== m.version) {
10858
11070
  console.log(source_default.yellow(` \u26A0 Version mismatch: manifest=${m.version} package.json=${pkg.version}`));
@@ -10869,8 +11081,8 @@ function validate3() {
10869
11081
  // src/commands/check.ts
10870
11082
  init_source();
10871
11083
  import { execSync as execSync2 } from "child_process";
10872
- import { existsSync as existsSync13, readFileSync as readFileSync10 } from "fs";
10873
- import { join as join16 } from "path";
11084
+ import { existsSync as existsSync14, readFileSync as readFileSync10 } from "fs";
11085
+ import { join as join17 } from "path";
10874
11086
  function check() {
10875
11087
  const root = process.cwd();
10876
11088
  if (!exists(root)) {
@@ -10889,17 +11101,17 @@ function check() {
10889
11101
  let warnings = 0;
10890
11102
  for (const page of m.pages) {
10891
11103
  const component = page.component || pageComponentFromPath(page.path);
10892
- if (!existsSync13(join16(root, "src", component))) {
11104
+ if (!existsSync14(join17(root, "src", component))) {
10893
11105
  console.log(source_default.yellow(` \u26A0 Page not found: src/${component}`));
10894
11106
  warnings++;
10895
11107
  }
10896
11108
  }
10897
- if (m.agent && !existsSync13(join16(root, m.agent))) {
11109
+ if (m.agent && !existsSync14(join17(root, m.agent))) {
10898
11110
  console.log(source_default.yellow(` \u26A0 Agent config not found: ${m.agent}`));
10899
11111
  warnings++;
10900
11112
  }
10901
- const pkgPath = join16(root, "package.json");
10902
- if (existsSync13(pkgPath)) {
11113
+ const pkgPath = join17(root, "package.json");
11114
+ if (existsSync14(pkgPath)) {
10903
11115
  const pkg = JSON.parse(readFileSync10(pkgPath, "utf-8"));
10904
11116
  if (pkg.version && pkg.version !== m.version) {
10905
11117
  console.log(source_default.yellow(` \u26A0 Version mismatch: manifest=${m.version} package.json=${pkg.version}`));
@@ -10932,8 +11144,8 @@ function check() {
10932
11144
 
10933
11145
  // src/commands/clean.ts
10934
11146
  init_source();
10935
- import { rmSync as rmSync2, existsSync as existsSync14 } from "fs";
10936
- import { join as join17 } from "path";
11147
+ import { rmSync as rmSync4, existsSync as existsSync15 } from "fs";
11148
+ import { join as join18 } from "path";
10937
11149
  function clean(options) {
10938
11150
  const root = process.cwd();
10939
11151
  const dirs = ["dist", ".vite"];
@@ -10942,17 +11154,17 @@ function clean(options) {
10942
11154
  }
10943
11155
  const lockfiles = ["bun.lockb", "package-lock.json", "yarn.lock", "pnpm-lock.yaml"];
10944
11156
  for (const dir of dirs) {
10945
- const path = join17(root, dir);
10946
- if (existsSync14(path)) {
10947
- rmSync2(path, { recursive: true });
11157
+ const path = join18(root, dir);
11158
+ if (existsSync15(path)) {
11159
+ rmSync4(path, { recursive: true });
10948
11160
  console.log(source_default.dim(` Removed ${dir}/`));
10949
11161
  }
10950
11162
  }
10951
11163
  if (options?.all) {
10952
11164
  for (const file of lockfiles) {
10953
- const path = join17(root, file);
10954
- if (existsSync14(path)) {
10955
- rmSync2(path);
11165
+ const path = join18(root, file);
11166
+ if (existsSync15(path)) {
11167
+ rmSync4(path);
10956
11168
  console.log(source_default.dim(` Removed ${file}`));
10957
11169
  }
10958
11170
  }
@@ -11112,8 +11324,8 @@ function update() {
11112
11324
 
11113
11325
  // src/commands/graph/init.ts
11114
11326
  init_source();
11115
- import { existsSync as existsSync15, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync5 } from "fs";
11116
- import { join as join18 } from "path";
11327
+ import { existsSync as existsSync16, readFileSync as readFileSync11, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
11328
+ import { join as join19 } from "path";
11117
11329
  import { execSync as execSync4 } from "child_process";
11118
11330
  function graphInit() {
11119
11331
  const root = process.cwd();
@@ -11123,10 +11335,10 @@ function graphInit() {
11123
11335
  process.exit(1);
11124
11336
  }
11125
11337
  const m = read(root);
11126
- const modelsDir = join18(root, "src", "models");
11127
- mkdirSync5(modelsDir, { recursive: true });
11128
- const indexPath = join18(modelsDir, "index.ts");
11129
- if (!existsSync15(indexPath)) {
11338
+ const modelsDir = join19(root, "src", "models");
11339
+ mkdirSync7(modelsDir, { recursive: true });
11340
+ const indexPath = join19(modelsDir, "index.ts");
11341
+ if (!existsSync16(indexPath)) {
11130
11342
  writeFileSync7(indexPath, `// Data models for ${m.name}
11131
11343
  // Generated by construct graph init
11132
11344
 
@@ -11134,7 +11346,7 @@ function graphInit() {
11134
11346
  // export { User } from './User'
11135
11347
  `);
11136
11348
  }
11137
- const pkgPath = join18(root, "package.json");
11349
+ const pkgPath = join19(root, "package.json");
11138
11350
  const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
11139
11351
  if (!pkg.dependencies)
11140
11352
  pkg.dependencies = {};
@@ -11166,8 +11378,8 @@ function graphInit() {
11166
11378
 
11167
11379
  // src/commands/graph/generate.ts
11168
11380
  init_source();
11169
- import { existsSync as existsSync16, readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync6 } from "fs";
11170
- import { join as join19 } from "path";
11381
+ import { existsSync as existsSync17, readFileSync as readFileSync12, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8 } from "fs";
11382
+ import { join as join20 } from "path";
11171
11383
  var FIELD_TYPES = {
11172
11384
  string: "field.string()",
11173
11385
  int: "field.int()",
@@ -11319,10 +11531,10 @@ function generate2(modelName, fieldSpecs, options) {
11319
11531
  lines.push("");
11320
11532
  const content = lines.join(`
11321
11533
  `);
11322
- const modelsDir = join19(root, "src", "models");
11323
- mkdirSync6(modelsDir, { recursive: true });
11324
- const filePath = join19(modelsDir, `${name}.ts`);
11325
- if (existsSync16(filePath)) {
11534
+ const modelsDir = join20(root, "src", "models");
11535
+ mkdirSync8(modelsDir, { recursive: true });
11536
+ const filePath = join20(modelsDir, `${name}.ts`);
11537
+ if (existsSync17(filePath)) {
11326
11538
  console.log(source_default.yellow(` Model file already exists: src/models/${name}.ts`));
11327
11539
  console.log(source_default.dim(" Overwriting..."));
11328
11540
  }
@@ -11339,9 +11551,9 @@ function generate2(modelName, fieldSpecs, options) {
11339
11551
  console.log();
11340
11552
  }
11341
11553
  function updateBarrel(modelsDir, modelName) {
11342
- const indexPath = join19(modelsDir, "index.ts");
11554
+ const indexPath = join20(modelsDir, "index.ts");
11343
11555
  const exportLine = `export { ${modelName} } from './${modelName}'`;
11344
- if (existsSync16(indexPath)) {
11556
+ if (existsSync17(indexPath)) {
11345
11557
  const content = readFileSync12(indexPath, "utf-8");
11346
11558
  if (content.includes(exportLine))
11347
11559
  return;
@@ -11357,8 +11569,8 @@ function updateBarrel(modelsDir, modelName) {
11357
11569
 
11358
11570
  // src/commands/graph/push.ts
11359
11571
  init_source();
11360
- import { existsSync as existsSync17, readdirSync as readdirSync7, readFileSync as readFileSync13 } from "fs";
11361
- import { join as join20 } from "path";
11572
+ import { existsSync as existsSync18, readdirSync as readdirSync7, readFileSync as readFileSync13 } from "fs";
11573
+ import { join as join21 } from "path";
11362
11574
  init_auth();
11363
11575
  async function graphPush() {
11364
11576
  const root = process.cwd();
@@ -11367,8 +11579,8 @@ async function graphPush() {
11367
11579
  process.exit(1);
11368
11580
  }
11369
11581
  const m = read(root);
11370
- const modelsDir = join20(root, "src", "models");
11371
- if (!existsSync17(modelsDir)) {
11582
+ const modelsDir = join21(root, "src", "models");
11583
+ if (!existsSync18(modelsDir)) {
11372
11584
  console.error(source_default.red("No src/models/ directory found. Run 'construct graph init' first."));
11373
11585
  process.exit(1);
11374
11586
  }
@@ -11381,7 +11593,7 @@ async function graphPush() {
11381
11593
  console.log(source_default.blue(`Pushing ${modelFiles.length} model(s) for space: ${m.id}`));
11382
11594
  const models = [];
11383
11595
  for (const file of modelFiles) {
11384
- const content = readFileSync13(join20(modelsDir, file), "utf-8");
11596
+ const content = readFileSync13(join21(modelsDir, file), "utf-8");
11385
11597
  const model = parseModelFile(content);
11386
11598
  if (model)
11387
11599
  models.push(model);
@@ -11564,8 +11776,8 @@ function parseModelFile(content) {
11564
11776
 
11565
11777
  // src/commands/graph/migrate.ts
11566
11778
  init_source();
11567
- import { existsSync as existsSync18, readdirSync as readdirSync8, readFileSync as readFileSync14 } from "fs";
11568
- import { join as join21 } from "path";
11779
+ import { existsSync as existsSync19, readdirSync as readdirSync8, readFileSync as readFileSync14 } from "fs";
11780
+ import { join as join22 } from "path";
11569
11781
  init_auth();
11570
11782
  async function graphMigrate(options) {
11571
11783
  const root = process.cwd();
@@ -11574,8 +11786,8 @@ async function graphMigrate(options) {
11574
11786
  process.exit(1);
11575
11787
  }
11576
11788
  const m = read(root);
11577
- const modelsDir = join21(root, "src", "models");
11578
- if (!existsSync18(modelsDir)) {
11789
+ const modelsDir = join22(root, "src", "models");
11790
+ if (!existsSync19(modelsDir)) {
11579
11791
  console.error(source_default.red("No src/models/ directory. Run 'construct graph init' first."));
11580
11792
  process.exit(1);
11581
11793
  }
@@ -11605,7 +11817,7 @@ async function graphMigrate(options) {
11605
11817
  const modelFiles = readdirSync8(modelsDir).filter((f) => f.endsWith(".ts") && f !== "index.ts");
11606
11818
  const localModels = [];
11607
11819
  for (const file of modelFiles) {
11608
- const content = readFileSync14(join21(modelsDir, file), "utf-8");
11820
+ const content = readFileSync14(join22(modelsDir, file), "utf-8");
11609
11821
  const model = parseModelFields(content);
11610
11822
  if (model)
11611
11823
  localModels.push(model);
@@ -11741,7 +11953,7 @@ function graphFork(newSpaceID) {
11741
11953
  // package.json
11742
11954
  var package_default = {
11743
11955
  name: "@construct-space/cli",
11744
- version: "1.9.5",
11956
+ version: "1.9.6",
11745
11957
  description: "Construct CLI \u2014 scaffold, build, develop, and publish spaces",
11746
11958
  type: "module",
11747
11959
  bin: {