@construct-space/cli 1.6.2 → 1.6.4

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
@@ -2889,8 +2889,12 @@ function load2() {
2889
2889
  const path = credentialsPath();
2890
2890
  if (existsSync10(path)) {
2891
2891
  const data = JSON.parse(readFileSync7(path, "utf-8"));
2892
- if (data.token)
2892
+ if (data.token) {
2893
+ if (!data.publisherKey && data.token.startsWith("csk_live_")) {
2894
+ data.publisherKey = data.token;
2895
+ }
2893
2896
  return data;
2897
+ }
2894
2898
  }
2895
2899
  const fromProfile = loadFromActiveProfile();
2896
2900
  if (fromProfile)
@@ -2923,7 +2927,10 @@ function loadFromActiveProfile() {
2923
2927
  id: u.id || u.uuid || activeId,
2924
2928
  name: u.name || u.username || activeId,
2925
2929
  email: u.email || ""
2926
- }
2930
+ },
2931
+ publisherKey: a.publisher?.api_key,
2932
+ publisherKind: a.publisher?.kind,
2933
+ publisherName: a.publisher?.name
2927
2934
  };
2928
2935
  } catch {
2929
2936
  return null;
@@ -5291,8 +5298,7 @@ async function scaffold(nameArg, options) {
5291
5298
  join2(name, "agent", "skills"),
5292
5299
  join2(name, "agent", "hooks"),
5293
5300
  join2(name, "agent", "tools"),
5294
- join2(name, "widgets", "summary"),
5295
- join2(name, ".github", "workflows")
5301
+ join2(name, "widgets", "summary")
5296
5302
  ];
5297
5303
  for (const d of dirs)
5298
5304
  mkdirSync(d, { recursive: true });
@@ -5311,7 +5317,6 @@ async function scaffold(nameArg, options) {
5311
5317
  "config.md.tmpl": join2(name, "agent", "config.md"),
5312
5318
  "skill.md.tmpl": join2(name, "agent", "skills", "default.md"),
5313
5319
  "safety.json.tmpl": join2(name, "agent", "hooks", "safety.json"),
5314
- "build.yml.tmpl": join2(name, ".github", "workflows", "build.yml"),
5315
5320
  "tsconfig.json.tmpl": join2(name, "tsconfig.json"),
5316
5321
  "eslint.config.js.tmpl": join2(name, "eslint.config.js"),
5317
5322
  "gitignore.tmpl": join2(name, ".gitignore"),
@@ -5353,7 +5358,7 @@ async function scaffold(nameArg, options) {
5353
5358
 
5354
5359
  // src/commands/build.ts
5355
5360
  init_source();
5356
- import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync3, renameSync, statSync as statSync3 } from "fs";
5361
+ import { cpSync, existsSync as existsSync6, readFileSync as readFileSync4, readdirSync as readdirSync3, renameSync, statSync as statSync3 } from "fs";
5357
5362
  import { join as join6 } from "path";
5358
5363
  import { createHash } from "crypto";
5359
5364
 
@@ -7991,7 +7996,6 @@ function ora(options) {
7991
7996
  import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync3 } from "fs";
7992
7997
  import { join as join3 } from "path";
7993
7998
  var MANIFEST_FILE = "space.manifest.json";
7994
- var HOST_API_VERSION = "0.5.0";
7995
7999
  var idRegex = /^[a-z][a-z0-9-]*$/;
7996
8000
  var versionRegex = /^\d+\.\d+\.\d+/;
7997
8001
  function validate2(m) {
@@ -8248,174 +8252,47 @@ function bundleAgentDir(srcDir, distDir) {
8248
8252
  }
8249
8253
 
8250
8254
  // src/commands/build.ts
8251
- function stripComments(source) {
8252
- let out = "";
8253
- let i = 0;
8254
- let quote = null;
8255
- let escaped = false;
8256
- while (i < source.length) {
8257
- const ch = source[i];
8258
- const next = source[i + 1];
8259
- if (quote) {
8260
- out += ch;
8261
- if (escaped) {
8262
- escaped = false;
8263
- } else if (ch === "\\") {
8264
- escaped = true;
8265
- } else if (ch === quote) {
8266
- quote = null;
8267
- }
8268
- i++;
8269
- continue;
8270
- }
8271
- if (ch === '"' || ch === "'" || ch === "`") {
8272
- quote = ch;
8273
- out += ch;
8274
- i++;
8275
- continue;
8276
- }
8277
- if (ch === "/" && next === "/") {
8278
- while (i < source.length && source[i] !== `
8279
- `) {
8280
- out += " ";
8281
- i++;
8282
- }
8283
- continue;
8284
- }
8285
- if (ch === "/" && next === "*") {
8286
- out += " ";
8287
- i += 2;
8288
- while (i < source.length && !(source[i] === "*" && source[i + 1] === "/")) {
8289
- out += source[i] === `
8290
- ` ? `
8291
- ` : " ";
8292
- i++;
8293
- }
8294
- if (i < source.length) {
8295
- out += " ";
8296
- i += 2;
8297
- }
8298
- continue;
8299
- }
8300
- out += ch;
8301
- i++;
8302
- }
8303
- return out;
8304
- }
8305
- function findMatchingBrace(source, openIndex) {
8306
- let depth = 0;
8307
- let quote = null;
8308
- let escaped = false;
8309
- for (let i = openIndex;i < source.length; i++) {
8310
- const ch = source[i];
8311
- if (quote) {
8312
- if (escaped)
8313
- escaped = false;
8314
- else if (ch === "\\")
8315
- escaped = true;
8316
- else if (ch === quote)
8317
- quote = null;
8318
- continue;
8319
- }
8320
- if (ch === '"' || ch === "'" || ch === "`") {
8321
- quote = ch;
8322
- continue;
8323
- }
8324
- if (ch === "{")
8325
- depth++;
8326
- else if (ch === "}") {
8327
- depth--;
8328
- if (depth === 0)
8329
- return i;
8330
- }
8331
- }
8332
- return -1;
8333
- }
8334
- function objectLiteralAfter(source, start) {
8335
- const open = source.indexOf("{", start);
8336
- if (open < 0)
8337
- return null;
8338
- const close = findMatchingBrace(source, open);
8339
- if (close < 0)
8340
- return null;
8341
- return source.slice(open + 1, close);
8342
- }
8343
- function actionsObject(source) {
8344
- const stripped = stripComments(source);
8345
- const match = /export\s+const\s+actions\s*=/.exec(stripped);
8346
- if (!match)
8347
- return null;
8348
- return objectLiteralAfter(stripped, match.index + match[0].length);
8349
- }
8350
- function objectEntries(body) {
8351
- const entries = [];
8352
- let i = 0;
8353
- while (i < body.length) {
8354
- const match = /\s*,?\s*([A-Za-z_$][\w$]*)\s*:/.exec(body.slice(i));
8355
- if (!match)
8356
- break;
8357
- const name = match[1];
8358
- const valueStart = i + match.index + match[0].length;
8359
- const open = body.indexOf("{", valueStart);
8360
- if (open < 0)
8361
- break;
8362
- if (body.slice(valueStart, open).trim()) {
8363
- i = valueStart;
8255
+ var ASSET_DIRS = ["icons", "assets", "media", "public"];
8256
+ function copyAssetDirs(root, distDir) {
8257
+ const copied = [];
8258
+ for (const name of ASSET_DIRS) {
8259
+ const src = join6(root, name);
8260
+ if (!existsSync6(src) || !statSync3(src).isDirectory())
8364
8261
  continue;
8365
- }
8366
- const close = findMatchingBrace(body, open);
8367
- if (close < 0)
8368
- break;
8369
- entries.push({ name, body: body.slice(open + 1, close) });
8370
- i = close + 1;
8262
+ cpSync(src, join6(distDir, name), { recursive: true });
8263
+ copied.push(name);
8371
8264
  }
8372
- return entries;
8373
- }
8374
- function stringProperty(body, name) {
8375
- const match = new RegExp(`${name}\\s*:\\s*['"\`]([^'"\`]*)['"\`]`).exec(body);
8376
- return match?.[1];
8377
- }
8378
- function booleanProperty(body, name) {
8379
- const match = new RegExp(`${name}\\s*:\\s*(true|false)`).exec(body);
8380
- if (!match)
8381
- return;
8382
- return match[1] === "true";
8383
- }
8384
- function propertyObject(body, name) {
8385
- const match = new RegExp(`${name}\\s*:`).exec(body);
8386
- if (!match)
8387
- return null;
8388
- return objectLiteralAfter(body, match.index + match[0].length);
8265
+ return copied;
8389
8266
  }
8390
8267
  function extractActionMetadata(actionsPath) {
8391
8268
  try {
8392
- const actionsBody = actionsObject(readFileSync4(actionsPath, "utf-8"));
8393
- if (!actionsBody)
8394
- return null;
8269
+ const source = readFileSync4(actionsPath, "utf-8");
8395
8270
  const result = {};
8396
- for (const action of objectEntries(actionsBody)) {
8397
- const description = stringProperty(action.body, "description");
8398
- if (!description)
8399
- continue;
8400
- const metadata = { description };
8401
- const paramsBody = propertyObject(action.body, "params");
8402
- if (paramsBody) {
8271
+ const actionPattern = /(\w+)\s*:\s*\{[^}]*description\s*:\s*['"`]([^'"`]+)['"`]/g;
8272
+ let match;
8273
+ while ((match = actionPattern.exec(source)) !== null) {
8274
+ const actionId = match[1];
8275
+ const description = match[2];
8276
+ result[actionId] = { description };
8277
+ }
8278
+ for (const actionId of Object.keys(result)) {
8279
+ const paramBlockPattern = new RegExp(`${actionId}\\s*:\\s*\\{[\\s\\S]*?params\\s*:\\s*\\{([\\s\\S]*?)\\}\\s*,?\\s*(?:run|\\})`);
8280
+ const paramMatch = source.match(paramBlockPattern);
8281
+ if (paramMatch?.[1]) {
8403
8282
  const params = {};
8404
- for (const param of objectEntries(paramsBody)) {
8405
- const type = stringProperty(param.body, "type");
8406
- if (!type)
8407
- continue;
8408
- const required = booleanProperty(param.body, "required");
8409
- params[param.name] = {
8410
- type,
8411
- ...stringProperty(param.body, "description") ? { description: stringProperty(param.body, "description") } : {},
8412
- ...required === true ? { required: true } : {}
8283
+ const paramEntryPattern = /(\w+)\s*:\s*\{\s*type\s*:\s*['"`](\w+)['"`](?:\s*,\s*description\s*:\s*['"`]([^'"`]*)['"`])?(?:\s*,\s*required\s*:\s*(true|false))?\s*\}/g;
8284
+ let pm;
8285
+ while ((pm = paramEntryPattern.exec(paramMatch[1])) !== null) {
8286
+ params[pm[1]] = {
8287
+ type: pm[2],
8288
+ ...pm[3] ? { description: pm[3] } : {},
8289
+ ...pm[4] === "true" ? { required: true } : {}
8413
8290
  };
8414
8291
  }
8415
- if (Object.keys(params).length > 0)
8416
- metadata.params = params;
8292
+ if (Object.keys(params).length > 0) {
8293
+ result[actionId].params = params;
8294
+ }
8417
8295
  }
8418
- result[action.name] = metadata;
8419
8296
  }
8420
8297
  return Object.keys(result).length > 0 ? result : null;
8421
8298
  } catch {
@@ -8454,6 +8331,10 @@ async function build(options) {
8454
8331
  bundleAgentDir(agentDir, distDir2);
8455
8332
  bundleAgentDir(agentDir, root);
8456
8333
  }
8334
+ const copiedAssetDirs = copyAssetDirs(root, join6(root, "dist"));
8335
+ if (copiedAssetDirs.length > 0) {
8336
+ console.log(source_default.blue(` Assets: ${copiedAssetDirs.join(", ")}`));
8337
+ }
8457
8338
  const distDir = join6(root, "dist");
8458
8339
  const expectedBundle = `space-${m.id}.iife.js`;
8459
8340
  let bundlePath = join6(distDir, expectedBundle);
@@ -8481,7 +8362,7 @@ async function build(options) {
8481
8362
  writeWithBuild(distDir, raw, {
8482
8363
  checksum,
8483
8364
  size: bundleData.length,
8484
- hostApiVersion: HOST_API_VERSION,
8365
+ hostApiVersion: "0.5.0",
8485
8366
  builtAt: new Date().toISOString()
8486
8367
  });
8487
8368
  console.log(source_default.green(`Built ${m.name} v${m.version}`));
@@ -8493,16 +8374,16 @@ import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
8493
8374
  import { join as join9 } from "path";
8494
8375
  import { createHash as createHash2 } from "crypto";
8495
8376
 
8496
- // node_modules/chokidar/index.js
8377
+ // node_modules/chokidar/esm/index.js
8378
+ import { stat as statcb } from "fs";
8379
+ import { stat as stat3, readdir as readdir2 } from "fs/promises";
8497
8380
  import { EventEmitter } from "events";
8498
- import { stat as statcb, Stats } from "fs";
8499
- import { readdir as readdir2, stat as stat3 } from "fs/promises";
8500
- import * as sp2 from "path";
8381
+ import * as sysPath2 from "path";
8501
8382
 
8502
- // node_modules/readdirp/index.js
8503
- import { lstat, readdir, realpath, stat } from "fs/promises";
8504
- import { join as pjoin, relative as prelative, resolve as presolve, sep as psep } from "path";
8383
+ // node_modules/readdirp/esm/index.js
8384
+ import { stat, lstat, readdir, realpath } from "fs/promises";
8505
8385
  import { Readable } from "stream";
8386
+ import { resolve as presolve, relative as prelative, join as pjoin, sep as psep } from "path";
8506
8387
  var EntryTypes = {
8507
8388
  FILE_TYPE: "files",
8508
8389
  DIR_TYPE: "directories",
@@ -8558,20 +8439,6 @@ var normalizeFilter = (filter) => {
8558
8439
  };
8559
8440
 
8560
8441
  class ReaddirpStream extends Readable {
8561
- parents;
8562
- reading;
8563
- parent;
8564
- _stat;
8565
- _maxDepth;
8566
- _wantsDir;
8567
- _wantsFile;
8568
- _wantsEverything;
8569
- _root;
8570
- _isDirent;
8571
- _statsProp;
8572
- _rdOptions;
8573
- _fileFilter;
8574
- _directoryFilter;
8575
8442
  constructor(options = {}) {
8576
8443
  super({
8577
8444
  objectMode: true,
@@ -8588,7 +8455,7 @@ class ReaddirpStream extends Readable {
8588
8455
  } else {
8589
8456
  this._stat = statMethod;
8590
8457
  }
8591
- this._maxDepth = opts.depth != null && Number.isSafeInteger(opts.depth) ? opts.depth : defaultOptions.depth;
8458
+ this._maxDepth = opts.depth ?? defaultOptions.depth;
8592
8459
  this._wantsDir = type ? DIR_TYPES.has(type) : false;
8593
8460
  this._wantsFile = type ? FILE_TYPES.has(type) : false;
8594
8461
  this._wantsEverything = type === EntryTypes.EVERYTHING_TYPE;
@@ -8733,11 +8600,11 @@ function readdirp(root, options = {}) {
8733
8600
  return new ReaddirpStream(options);
8734
8601
  }
8735
8602
 
8736
- // node_modules/chokidar/handler.js
8737
- import { watch as fs_watch, unwatchFile, watchFile } from "fs";
8738
- import { realpath as fsrealpath, lstat as lstat2, open, stat as stat2 } from "fs/promises";
8603
+ // node_modules/chokidar/esm/handler.js
8604
+ import { watchFile, unwatchFile, watch as fs_watch } from "fs";
8605
+ import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
8606
+ import * as sysPath from "path";
8739
8607
  import { type as osType } from "os";
8740
- import * as sp from "path";
8741
8608
  var STR_DATA = "data";
8742
8609
  var STR_END = "end";
8743
8610
  var STR_CLOSE = "close";
@@ -9029,7 +8896,7 @@ var binaryExtensions = new Set([
9029
8896
  "zip",
9030
8897
  "zipx"
9031
8898
  ]);
9032
- var isBinaryPath = (filePath) => binaryExtensions.has(sp.extname(filePath).slice(1).toLowerCase());
8899
+ var isBinaryPath = (filePath) => binaryExtensions.has(sysPath.extname(filePath).slice(1).toLowerCase());
9033
8900
  var foreach = (val, fn) => {
9034
8901
  if (val instanceof Set) {
9035
8902
  val.forEach(fn);
@@ -9067,7 +8934,7 @@ function createFsWatchInstance(path, options, listener, errHandler, emitRaw) {
9067
8934
  listener(path);
9068
8935
  emitRaw(rawEvent, evPath, { watchedPath: path });
9069
8936
  if (evPath && path !== evPath) {
9070
- fsWatchBroadcast(sp.resolve(path, evPath), KEY_LISTENERS, sp.join(path, evPath));
8937
+ fsWatchBroadcast(sysPath.resolve(path, evPath), KEY_LISTENERS, sysPath.join(path, evPath));
9071
8938
  }
9072
8939
  };
9073
8940
  try {
@@ -9182,19 +9049,17 @@ var setFsWatchFileListener = (path, fullPath, options, handlers) => {
9182
9049
  };
9183
9050
 
9184
9051
  class NodeFsHandler {
9185
- fsw;
9186
- _boundHandleError;
9187
9052
  constructor(fsW) {
9188
9053
  this.fsw = fsW;
9189
9054
  this._boundHandleError = (error2) => fsW._handleError(error2);
9190
9055
  }
9191
9056
  _watchWithNodeFs(path, listener) {
9192
9057
  const opts = this.fsw.options;
9193
- const directory = sp.dirname(path);
9194
- const basename4 = sp.basename(path);
9058
+ const directory = sysPath.dirname(path);
9059
+ const basename4 = sysPath.basename(path);
9195
9060
  const parent = this.fsw._getWatchedDir(directory);
9196
9061
  parent.add(basename4);
9197
- const absolutePath = sp.resolve(path);
9062
+ const absolutePath = sysPath.resolve(path);
9198
9063
  const options = {
9199
9064
  persistent: opts.persistent
9200
9065
  };
@@ -9221,8 +9086,8 @@ class NodeFsHandler {
9221
9086
  if (this.fsw.closed) {
9222
9087
  return;
9223
9088
  }
9224
- const dirname3 = sp.dirname(file);
9225
- const basename4 = sp.basename(file);
9089
+ const dirname3 = sysPath.dirname(file);
9090
+ const basename4 = sysPath.basename(file);
9226
9091
  const parent = this.fsw._getWatchedDir(dirname3);
9227
9092
  let prevStats = stats;
9228
9093
  if (parent.has(basename4))
@@ -9305,9 +9170,8 @@ class NodeFsHandler {
9305
9170
  this.fsw._symlinkPaths.set(full, true);
9306
9171
  }
9307
9172
  _handleRead(directory, initialAdd, wh, target, dir, depth, throttler) {
9308
- directory = sp.join(directory, "");
9309
- const throttleKey = target ? `${directory}:${target}` : directory;
9310
- throttler = this.fsw._throttle("readdir", throttleKey, 1000);
9173
+ directory = sysPath.join(directory, "");
9174
+ throttler = this.fsw._throttle("readdir", directory, 1000);
9311
9175
  if (!throttler)
9312
9176
  return;
9313
9177
  const previous = this.fsw._getWatchedDir(wh.path);
@@ -9324,7 +9188,7 @@ class NodeFsHandler {
9324
9188
  return;
9325
9189
  }
9326
9190
  const item = entry.path;
9327
- let path = sp.join(directory, item);
9191
+ let path = sysPath.join(directory, item);
9328
9192
  current.add(item);
9329
9193
  if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path, item)) {
9330
9194
  return;
@@ -9335,7 +9199,7 @@ class NodeFsHandler {
9335
9199
  }
9336
9200
  if (item === target || !target && !previous.has(item)) {
9337
9201
  this.fsw._incrReadyCount();
9338
- path = sp.join(dir, sp.relative(dir, path));
9202
+ path = sysPath.join(dir, sysPath.relative(dir, path));
9339
9203
  this._addToNodeFs(path, initialAdd, wh, depth + 1);
9340
9204
  }
9341
9205
  }).on(EV.ERROR, this._boundHandleError);
@@ -9361,12 +9225,12 @@ class NodeFsHandler {
9361
9225
  });
9362
9226
  }
9363
9227
  async _handleDir(dir, stats, initialAdd, depth, target, wh, realpath2) {
9364
- const parentDir = this.fsw._getWatchedDir(sp.dirname(dir));
9365
- const tracked = parentDir.has(sp.basename(dir));
9228
+ const parentDir = this.fsw._getWatchedDir(sysPath.dirname(dir));
9229
+ const tracked = parentDir.has(sysPath.basename(dir));
9366
9230
  if (!(initialAdd && this.fsw.options.ignoreInitial) && !target && !tracked) {
9367
9231
  this.fsw._emit(EV.ADD_DIR, dir, stats);
9368
9232
  }
9369
- parentDir.add(sp.basename(dir));
9233
+ parentDir.add(sysPath.basename(dir));
9370
9234
  this.fsw._getWatchedDir(dir);
9371
9235
  let throttler;
9372
9236
  let closer;
@@ -9407,7 +9271,7 @@ class NodeFsHandler {
9407
9271
  const follow = this.fsw.options.followSymlinks;
9408
9272
  let closer;
9409
9273
  if (stats.isDirectory()) {
9410
- const absPath = sp.resolve(path);
9274
+ const absPath = sysPath.resolve(path);
9411
9275
  const targetPath = follow ? await fsrealpath(path) : path;
9412
9276
  if (this.fsw.closed)
9413
9277
  return;
@@ -9421,14 +9285,14 @@ class NodeFsHandler {
9421
9285
  const targetPath = follow ? await fsrealpath(path) : path;
9422
9286
  if (this.fsw.closed)
9423
9287
  return;
9424
- const parent = sp.dirname(wh.watchPath);
9288
+ const parent = sysPath.dirname(wh.watchPath);
9425
9289
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
9426
9290
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
9427
9291
  closer = await this._handleDir(parent, stats, initialAdd, depth, path, wh, targetPath);
9428
9292
  if (this.fsw.closed)
9429
9293
  return;
9430
9294
  if (targetPath !== undefined) {
9431
- this.fsw._symlinkPaths.set(sp.resolve(path), targetPath);
9295
+ this.fsw._symlinkPaths.set(sysPath.resolve(path), targetPath);
9432
9296
  }
9433
9297
  } else {
9434
9298
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
@@ -9446,7 +9310,7 @@ class NodeFsHandler {
9446
9310
  }
9447
9311
  }
9448
9312
 
9449
- // node_modules/chokidar/index.js
9313
+ // node_modules/chokidar/esm/index.js
9450
9314
  /*! chokidar - MIT License (c) 2012 Paul Miller (paulmillr.com) */
9451
9315
  var SLASH = "/";
9452
9316
  var SLASH_SLASH = "//";
@@ -9454,7 +9318,7 @@ var ONE_DOT = ".";
9454
9318
  var TWO_DOTS = "..";
9455
9319
  var STRING_TYPE = "string";
9456
9320
  var BACK_SLASH_RE = /\\/g;
9457
- var DOUBLE_SLASH_RE = /\/\//g;
9321
+ var DOUBLE_SLASH_RE = /\/\//;
9458
9322
  var DOT_RE = /\..*\.(sw[px])$|~$|\.subl.*\.tmp/;
9459
9323
  var REPLACER_RE = /^\.[/\\]/;
9460
9324
  function arrify(item) {
@@ -9473,11 +9337,11 @@ function createPattern(matcher) {
9473
9337
  if (matcher.path === string)
9474
9338
  return true;
9475
9339
  if (matcher.recursive) {
9476
- const relative4 = sp2.relative(matcher.path, string);
9340
+ const relative4 = sysPath2.relative(matcher.path, string);
9477
9341
  if (!relative4) {
9478
9342
  return false;
9479
9343
  }
9480
- return !relative4.startsWith("..") && !sp2.isAbsolute(relative4);
9344
+ return !relative4.startsWith("..") && !sysPath2.isAbsolute(relative4);
9481
9345
  }
9482
9346
  return false;
9483
9347
  };
@@ -9487,12 +9351,14 @@ function createPattern(matcher) {
9487
9351
  function normalizePath(path) {
9488
9352
  if (typeof path !== "string")
9489
9353
  throw new Error("string expected");
9490
- path = sp2.normalize(path);
9354
+ path = sysPath2.normalize(path);
9491
9355
  path = path.replace(/\\/g, "/");
9492
9356
  let prepend = false;
9493
9357
  if (path.startsWith("//"))
9494
9358
  prepend = true;
9495
- path = path.replace(DOUBLE_SLASH_RE, "/");
9359
+ const DOUBLE_SLASH_RE2 = /\/\//;
9360
+ while (path.match(DOUBLE_SLASH_RE2))
9361
+ path = path.replace(DOUBLE_SLASH_RE2, "/");
9496
9362
  if (prepend)
9497
9363
  path = "/" + path;
9498
9364
  return path;
@@ -9533,32 +9399,31 @@ var toUnix = (string) => {
9533
9399
  if (str.startsWith(SLASH_SLASH)) {
9534
9400
  prepend = true;
9535
9401
  }
9536
- str = str.replace(DOUBLE_SLASH_RE, SLASH);
9402
+ while (str.match(DOUBLE_SLASH_RE)) {
9403
+ str = str.replace(DOUBLE_SLASH_RE, SLASH);
9404
+ }
9537
9405
  if (prepend) {
9538
9406
  str = SLASH + str;
9539
9407
  }
9540
9408
  return str;
9541
9409
  };
9542
- var normalizePathToUnix = (path) => toUnix(sp2.normalize(toUnix(path)));
9410
+ var normalizePathToUnix = (path) => toUnix(sysPath2.normalize(toUnix(path)));
9543
9411
  var normalizeIgnored = (cwd = "") => (path) => {
9544
9412
  if (typeof path === "string") {
9545
- return normalizePathToUnix(sp2.isAbsolute(path) ? path : sp2.join(cwd, path));
9413
+ return normalizePathToUnix(sysPath2.isAbsolute(path) ? path : sysPath2.join(cwd, path));
9546
9414
  } else {
9547
9415
  return path;
9548
9416
  }
9549
9417
  };
9550
9418
  var getAbsolutePath = (path, cwd) => {
9551
- if (sp2.isAbsolute(path)) {
9419
+ if (sysPath2.isAbsolute(path)) {
9552
9420
  return path;
9553
9421
  }
9554
- return sp2.join(cwd, path);
9422
+ return sysPath2.join(cwd, path);
9555
9423
  };
9556
9424
  var EMPTY_SET = Object.freeze(new Set);
9557
9425
 
9558
9426
  class DirEntry {
9559
- path;
9560
- _removeWatcher;
9561
- items;
9562
9427
  constructor(dir, removeWatcher) {
9563
9428
  this.path = dir;
9564
9429
  this._removeWatcher = removeWatcher;
@@ -9583,7 +9448,7 @@ class DirEntry {
9583
9448
  await readdir2(dir);
9584
9449
  } catch (err) {
9585
9450
  if (this._removeWatcher) {
9586
- this._removeWatcher(sp2.dirname(dir), sp2.basename(dir));
9451
+ this._removeWatcher(sysPath2.dirname(dir), sysPath2.basename(dir));
9587
9452
  }
9588
9453
  }
9589
9454
  }
@@ -9611,19 +9476,12 @@ var STAT_METHOD_F = "stat";
9611
9476
  var STAT_METHOD_L = "lstat";
9612
9477
 
9613
9478
  class WatchHelper {
9614
- fsw;
9615
- path;
9616
- watchPath;
9617
- fullWatchPath;
9618
- dirParts;
9619
- followSymlinks;
9620
- statMethod;
9621
9479
  constructor(path, follow, fsw) {
9622
9480
  this.fsw = fsw;
9623
9481
  const watchPath = path;
9624
9482
  this.path = path = path.replace(REPLACER_RE, "");
9625
9483
  this.watchPath = watchPath;
9626
- this.fullWatchPath = sp2.resolve(watchPath);
9484
+ this.fullWatchPath = sysPath2.resolve(watchPath);
9627
9485
  this.dirParts = [];
9628
9486
  this.dirParts.forEach((parts) => {
9629
9487
  if (parts.length > 1)
@@ -9633,7 +9491,7 @@ class WatchHelper {
9633
9491
  this.statMethod = follow ? STAT_METHOD_F : STAT_METHOD_L;
9634
9492
  }
9635
9493
  entryPath(entry) {
9636
- return sp2.join(this.watchPath, sp2.relative(this.watchPath, entry.fullPath));
9494
+ return sysPath2.join(this.watchPath, sysPath2.relative(this.watchPath, entry.fullPath));
9637
9495
  }
9638
9496
  filterPath(entry) {
9639
9497
  const { stats } = entry;
@@ -9648,24 +9506,6 @@ class WatchHelper {
9648
9506
  }
9649
9507
 
9650
9508
  class FSWatcher extends EventEmitter {
9651
- closed;
9652
- options;
9653
- _closers;
9654
- _ignoredPaths;
9655
- _throttled;
9656
- _streams;
9657
- _symlinkPaths;
9658
- _watched;
9659
- _pendingWrites;
9660
- _pendingUnlinks;
9661
- _readyCount;
9662
- _emitReady;
9663
- _closePromise;
9664
- _userIgnored;
9665
- _readyEmitted;
9666
- _emitRaw;
9667
- _boundRemove;
9668
- _nodeFsHandler;
9669
9509
  constructor(_opts = {}) {
9670
9510
  super();
9671
9511
  this.closed = false;
@@ -9774,7 +9614,7 @@ class FSWatcher extends EventEmitter {
9774
9614
  return;
9775
9615
  results.forEach((item) => {
9776
9616
  if (item)
9777
- this.add(sp2.dirname(item), sp2.basename(_origAdd || item));
9617
+ this.add(sysPath2.dirname(item), sysPath2.basename(_origAdd || item));
9778
9618
  });
9779
9619
  });
9780
9620
  return this;
@@ -9785,10 +9625,10 @@ class FSWatcher extends EventEmitter {
9785
9625
  const paths = unifyPaths(paths_);
9786
9626
  const { cwd } = this.options;
9787
9627
  paths.forEach((path) => {
9788
- if (!sp2.isAbsolute(path) && !this._closers.has(path)) {
9628
+ if (!sysPath2.isAbsolute(path) && !this._closers.has(path)) {
9789
9629
  if (cwd)
9790
- path = sp2.join(cwd, path);
9791
- path = sp2.resolve(path);
9630
+ path = sysPath2.join(cwd, path);
9631
+ path = sysPath2.resolve(path);
9792
9632
  }
9793
9633
  this._closePath(path);
9794
9634
  this._addIgnoredPath(path);
@@ -9832,7 +9672,7 @@ class FSWatcher extends EventEmitter {
9832
9672
  getWatched() {
9833
9673
  const watchList = {};
9834
9674
  this._watched.forEach((entry, dir) => {
9835
- const key = this.options.cwd ? sp2.relative(this.options.cwd, dir) : dir;
9675
+ const key = this.options.cwd ? sysPath2.relative(this.options.cwd, dir) : dir;
9836
9676
  const index = key || ONE_DOT;
9837
9677
  watchList[index] = entry.getChildren().sort();
9838
9678
  });
@@ -9848,9 +9688,9 @@ class FSWatcher extends EventEmitter {
9848
9688
  return;
9849
9689
  const opts = this.options;
9850
9690
  if (isWindows)
9851
- path = sp2.normalize(path);
9691
+ path = sysPath2.normalize(path);
9852
9692
  if (opts.cwd)
9853
- path = sp2.relative(opts.cwd, path);
9693
+ path = sysPath2.relative(opts.cwd, path);
9854
9694
  const args = [path];
9855
9695
  if (stats != null)
9856
9696
  args.push(stats);
@@ -9901,7 +9741,7 @@ class FSWatcher extends EventEmitter {
9901
9741
  return this;
9902
9742
  }
9903
9743
  if (opts.alwaysStat && stats === undefined && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
9904
- const fullPath = opts.cwd ? sp2.join(opts.cwd, path) : path;
9744
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path) : path;
9905
9745
  let stats2;
9906
9746
  try {
9907
9747
  stats2 = await stat3(fullPath);
@@ -9957,8 +9797,8 @@ class FSWatcher extends EventEmitter {
9957
9797
  const pollInterval = awf.pollInterval;
9958
9798
  let timeoutHandler;
9959
9799
  let fullPath = path;
9960
- if (this.options.cwd && !sp2.isAbsolute(path)) {
9961
- fullPath = sp2.join(this.options.cwd, path);
9800
+ if (this.options.cwd && !sysPath2.isAbsolute(path)) {
9801
+ fullPath = sysPath2.join(this.options.cwd, path);
9962
9802
  }
9963
9803
  const now = new Date;
9964
9804
  const writes = this._pendingWrites;
@@ -10015,7 +9855,7 @@ class FSWatcher extends EventEmitter {
10015
9855
  return new WatchHelper(path, this.options.followSymlinks, this);
10016
9856
  }
10017
9857
  _getWatchedDir(directory) {
10018
- const dir = sp2.resolve(directory);
9858
+ const dir = sysPath2.resolve(directory);
10019
9859
  if (!this._watched.has(dir))
10020
9860
  this._watched.set(dir, new DirEntry(dir, this._boundRemove));
10021
9861
  return this._watched.get(dir);
@@ -10026,8 +9866,8 @@ class FSWatcher extends EventEmitter {
10026
9866
  return Boolean(Number(stats.mode) & 256);
10027
9867
  }
10028
9868
  _remove(directory, item, isDirectory) {
10029
- const path = sp2.join(directory, item);
10030
- const fullPath = sp2.resolve(path);
9869
+ const path = sysPath2.join(directory, item);
9870
+ const fullPath = sysPath2.resolve(path);
10031
9871
  isDirectory = isDirectory != null ? isDirectory : this._watched.has(path) || this._watched.has(fullPath);
10032
9872
  if (!this._throttle("remove", path, 100))
10033
9873
  return;
@@ -10045,7 +9885,7 @@ class FSWatcher extends EventEmitter {
10045
9885
  }
10046
9886
  let relPath = path;
10047
9887
  if (this.options.cwd)
10048
- relPath = sp2.relative(this.options.cwd, path);
9888
+ relPath = sysPath2.relative(this.options.cwd, path);
10049
9889
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
10050
9890
  const event = this._pendingWrites.get(relPath).cancelWait();
10051
9891
  if (event === EVENTS.ADD)
@@ -10060,8 +9900,8 @@ class FSWatcher extends EventEmitter {
10060
9900
  }
10061
9901
  _closePath(path) {
10062
9902
  this._closeFile(path);
10063
- const dir = sp2.dirname(path);
10064
- this._getWatchedDir(dir).remove(sp2.basename(path));
9903
+ const dir = sysPath2.dirname(path);
9904
+ this._getWatchedDir(dir).remove(sysPath2.basename(path));
10065
9905
  }
10066
9906
  _closeFile(path) {
10067
9907
  const closers = this._closers.get(path);
@@ -10163,7 +10003,7 @@ async function dev() {
10163
10003
  writeWithBuild(distDir, raw, {
10164
10004
  checksum,
10165
10005
  size: bundleData.length,
10166
- hostApiVersion: HOST_API_VERSION,
10006
+ hostApiVersion: "0.5.0",
10167
10007
  builtAt: new Date().toISOString()
10168
10008
  });
10169
10009
  console.log(source_default.green(`Built \u2192 dist/ (${(bundleData.length / 1024).toFixed(1)} KB)`));
@@ -10175,7 +10015,7 @@ async function dev() {
10175
10015
 
10176
10016
  // src/commands/run.ts
10177
10017
  init_source();
10178
- import { existsSync as existsSync9, cpSync, mkdirSync as mkdirSync3 } from "fs";
10018
+ import { existsSync as existsSync9, cpSync as cpSync2, mkdirSync as mkdirSync3 } from "fs";
10179
10019
  import { join as join11 } from "path";
10180
10020
  init_appdir();
10181
10021
  function install() {
@@ -10196,7 +10036,7 @@ function install() {
10196
10036
  }
10197
10037
  const installDir = spaceDir(m.id);
10198
10038
  mkdirSync3(installDir, { recursive: true });
10199
- cpSync(distDir, installDir, { recursive: true });
10039
+ cpSync2(distDir, installDir, { recursive: true });
10200
10040
  console.log(source_default.green(`Installed ${m.name} \u2192 ${installDir}`));
10201
10041
  console.log(source_default.dim(" Restart Construct to load the updated space."));
10202
10042
  }
@@ -10401,12 +10241,25 @@ async function publish(options) {
10401
10241
  m = read(root);
10402
10242
  console.log(source_default.green(`Version bumped to ${m.version}`));
10403
10243
  }
10244
+ const publishToken = creds.publisherKey ?? creds.token;
10245
+ if (!creds.publisherKey) {
10246
+ console.log(source_default.yellow("No publisher key in active profile."));
10247
+ console.log(source_default.dim(" Spaces will be attributed to your personal user identity."));
10248
+ console.log(source_default.dim(" To publish as an org: enroll the org from the desktop app"));
10249
+ console.log(source_default.dim(" (Org Settings \u2192 Developer), then re-run this command."));
10250
+ console.log();
10251
+ }
10404
10252
  console.log();
10405
10253
  console.log(` Space: ${source_default.cyan(m.name)}`);
10406
10254
  console.log(` Version: ${source_default.cyan("v" + m.version)}`);
10407
10255
  console.log(` Server: ${source_default.dim(creds.portal)}`);
10408
- if (creds.user)
10256
+ if (creds.publisherKey) {
10257
+ const kind = creds.publisherKind === "org" ? "org" : "personal";
10258
+ const label = creds.publisherName || creds.user?.name || "";
10259
+ console.log(` As: ${source_default.cyan(label)} ${source_default.dim(`(${kind} publisher)`)}`);
10260
+ } else if (creds.user) {
10409
10261
  console.log(` Author: ${source_default.dim(creds.user.name)}`);
10262
+ }
10410
10263
  console.log();
10411
10264
  if (!yes) {
10412
10265
  const proceed = await dist_default4({
@@ -10430,7 +10283,7 @@ async function publish(options) {
10430
10283
  }
10431
10284
  const uploadSpinner = ora("Uploading & building...").start();
10432
10285
  try {
10433
- const result = await uploadSource(creds.portal, creds.token, tarballPath, m);
10286
+ const result = await uploadSource(creds.portal, publishToken, tarballPath, m);
10434
10287
  unlinkSync2(tarballPath);
10435
10288
  gitSafe(root, "tag", `v${m.version}`);
10436
10289
  gitSafe(root, "push", "origin", `v${m.version}`);
@@ -11379,7 +11232,7 @@ function graphFork(newSpaceID) {
11379
11232
  // package.json
11380
11233
  var package_default = {
11381
11234
  name: "@construct-space/cli",
11382
- version: "1.6.2",
11235
+ version: "1.6.4",
11383
11236
  description: "Construct CLI \u2014 scaffold, build, develop, and publish spaces",
11384
11237
  type: "module",
11385
11238
  bin: {
@@ -215,7 +215,7 @@ await tasks.remove(id)
215
215
 
216
216
  ## Actions (agent surface)
217
217
 
218
- `src/actions.ts` exports an `actions` object — each entry becomes an agent-callable tool via `space_run_action`.
218
+ `src/actions.ts` exports an `actions` object — each entry is exposed to the space's agent as a first-class tool.
219
219
 
220
220
  ```ts
221
221
  export const actions = {
@@ -230,7 +230,24 @@ export const actions = {
230
230
  }
231
231
  ```
232
232
 
233
- The agent (configured in `agent/config.md`) calls `space_list_actions` then `space_run_action`. Keep descriptions tight and specific they're the only docstring the agent sees.
233
+ ### Wiring (REQUIREDeasy to miss)
234
+
235
+ Each action becomes a tool named **`{spaceID}.{actionName}`** (dot, not underscore). The operator only pre-registers actions that are **explicitly whitelisted** in the agent config. An empty `tools: []` means the agent sees zero action tools and will report "unknown tool".
236
+
237
+ ```yaml
238
+ # agent/config.md frontmatter
239
+ ---
240
+ id: {{.ID}}
241
+ tools:
242
+ - {{.ID}}.createTask
243
+ - {{.ID}}.listTasks
244
+ - {{.ID}}.updateTask
245
+ ---
246
+ ```
247
+
248
+ Fallback: agents can also discover/invoke actions via the generic `space_list_actions` + `space_run_action` bridge tools. Prefer the whitelist — it gives the model proper tool definitions instead of stringly-typed action names.
249
+
250
+ Keep action descriptions tight and specific — they're the only docstring the agent sees.
234
251
 
235
252
  ---
236
253
 
@@ -30,7 +30,7 @@
30
30
  "vue-tsc": "^3.2.5"
31
31
  },
32
32
  "dependencies": {
33
- "@construct-space/graph": "^0.5.0",
34
- "@construct-space/ui": "^0.5.2"
33
+ "@construct-space/graph": "^0.6.2",
34
+ "@construct-space/ui": "^0.6.1"
35
35
  }
36
36
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@construct-space/cli",
3
- "version": "1.6.2",
3
+ "version": "1.6.4",
4
4
  "description": "Construct CLI — scaffold, build, develop, and publish spaces",
5
5
  "type": "module",
6
6
  "bin": {
@@ -215,7 +215,7 @@ await tasks.remove(id)
215
215
 
216
216
  ## Actions (agent surface)
217
217
 
218
- `src/actions.ts` exports an `actions` object — each entry becomes an agent-callable tool via `space_run_action`.
218
+ `src/actions.ts` exports an `actions` object — each entry is exposed to the space's agent as a first-class tool.
219
219
 
220
220
  ```ts
221
221
  export const actions = {
@@ -230,7 +230,24 @@ export const actions = {
230
230
  }
231
231
  ```
232
232
 
233
- The agent (configured in `agent/config.md`) calls `space_list_actions` then `space_run_action`. Keep descriptions tight and specific they're the only docstring the agent sees.
233
+ ### Wiring (REQUIREDeasy to miss)
234
+
235
+ Each action becomes a tool named **`{spaceID}.{actionName}`** (dot, not underscore). The operator only pre-registers actions that are **explicitly whitelisted** in the agent config. An empty `tools: []` means the agent sees zero action tools and will report "unknown tool".
236
+
237
+ ```yaml
238
+ # agent/config.md frontmatter
239
+ ---
240
+ id: {{.ID}}
241
+ tools:
242
+ - {{.ID}}.createTask
243
+ - {{.ID}}.listTasks
244
+ - {{.ID}}.updateTask
245
+ ---
246
+ ```
247
+
248
+ Fallback: agents can also discover/invoke actions via the generic `space_list_actions` + `space_run_action` bridge tools. Prefer the whitelist — it gives the model proper tool definitions instead of stringly-typed action names.
249
+
250
+ Keep action descriptions tight and specific — they're the only docstring the agent sees.
234
251
 
235
252
  ---
236
253
 
@@ -30,7 +30,7 @@
30
30
  "vue-tsc": "^3.2.5"
31
31
  },
32
32
  "dependencies": {
33
- "@construct-space/graph": "^0.5.0",
34
- "@construct-space/ui": "^0.5.2"
33
+ "@construct-space/graph": "^0.6.2",
34
+ "@construct-space/ui": "^0.6.1"
35
35
  }
36
36
  }
@@ -1,44 +0,0 @@
1
- name: Build Space
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
- pull_request:
8
- branches: [main]
9
-
10
- jobs:
11
- build:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v4
15
- - uses: oven-sh/setup-bun@v2
16
- with:
17
- bun-version: latest
18
- - run: bun install
19
- - run: bun run build
20
- - name: Upload artifacts
21
- if: startsWith(github.ref, 'refs/tags/v')
22
- uses: actions/upload-artifact@v4
23
- with:
24
- name: space-dist
25
- path: dist/
26
-
27
- release:
28
- needs: build
29
- if: startsWith(github.ref, 'refs/tags/v')
30
- runs-on: ubuntu-latest
31
- permissions:
32
- contents: write
33
- steps:
34
- - uses: actions/download-artifact@v4
35
- with:
36
- name: space-dist
37
- path: dist/
38
- - run: tar -czf space-dist.tar.gz -C dist .
39
- - uses: softprops/action-gh-release@v2
40
- with:
41
- files: |
42
- space-dist.tar.gz
43
- dist/manifest.json
44
- generate_release_notes: true
@@ -1,44 +0,0 @@
1
- name: Build Space
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
- pull_request:
8
- branches: [main]
9
-
10
- jobs:
11
- build:
12
- runs-on: ubuntu-latest
13
- steps:
14
- - uses: actions/checkout@v4
15
- - uses: oven-sh/setup-bun@v2
16
- with:
17
- bun-version: latest
18
- - run: bun install
19
- - run: bun run build
20
- - name: Upload artifacts
21
- if: startsWith(github.ref, 'refs/tags/v')
22
- uses: actions/upload-artifact@v4
23
- with:
24
- name: space-dist
25
- path: dist/
26
-
27
- release:
28
- needs: build
29
- if: startsWith(github.ref, 'refs/tags/v')
30
- runs-on: ubuntu-latest
31
- permissions:
32
- contents: write
33
- steps:
34
- - uses: actions/download-artifact@v4
35
- with:
36
- name: space-dist
37
- path: dist/
38
- - run: tar -czf space-dist.tar.gz -C dist .
39
- - uses: softprops/action-gh-release@v2
40
- with:
41
- files: |
42
- space-dist.tar.gz
43
- dist/manifest.json
44
- generate_release_notes: true