flyspace-cli 0.1.9 → 0.1.10

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.
@@ -843,6 +843,8 @@ var CONTAINER_ENV_ALLOWLIST = [
843
843
  // Re-enables the Artifact tool, which the CLI's own backstop switches off for
844
844
  // SDK entrypoints. Set per-run in `runCli()`; carries no secret.
845
845
  "CLAUDE_CODE_ARTIFACT",
846
+ // Set per-run when the `agent-memory` Labs flag turns the CLI's own memory off.
847
+ "CLAUDE_CODE_DISABLE_AUTO_MEMORY",
846
848
  // Locale and proxy settings, which change behaviour but carry no secrets.
847
849
  "LANG",
848
850
  "LC_ALL",
@@ -1801,6 +1803,8 @@ function runCli(prompt, cwd, botName, options, claudeConfigDir, resumeSessionId,
1801
1803
  const env = resolveMiseEnv(cwd);
1802
1804
  env["FLYSPACE_SCRATCH_DIR"] = paths.SCRATCH_DIR;
1803
1805
  env["CLAUDE_CODE_ARTIFACT"] = "1";
1806
+ if (options.disableAutoMemory) env["CLAUDE_CODE_DISABLE_AUTO_MEMORY"] = "1";
1807
+ else delete env["CLAUDE_CODE_DISABLE_AUTO_MEMORY"];
1804
1808
  const pinnedDir = pinnedClaudeConfigDir(claudeConfigDir);
1805
1809
  if (pinnedDir) env["CLAUDE_CONFIG_DIR"] = pinnedDir;
1806
1810
  else delete env["CLAUDE_CONFIG_DIR"];
package/dist/cli.js CHANGED
@@ -152,7 +152,7 @@ import {
152
152
  warnOnBrokenChannelCwds,
153
153
  workspaceSkillsDir,
154
154
  writeSkillFile
155
- } from "./chunk-JG6LNX5D.js";
155
+ } from "./chunk-UYLVSUD6.js";
156
156
  import {
157
157
  firstReplyBody,
158
158
  getThread,
@@ -439,9 +439,23 @@ import { confirm as confirm2 } from "@inquirer/prompts";
439
439
 
440
440
  // src/service.ts
441
441
  import { execSync } from "child_process";
442
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
443
- import { join as join2 } from "path";
442
+ import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync } from "fs";
443
+ import { basename, dirname as dirname2, join as join2 } from "path";
444
444
  import { homedir, platform } from "os";
445
+ function flyspaceHome(entry = process.argv[1]) {
446
+ let cliPath;
447
+ try {
448
+ cliPath = realpathSync(entry ?? "");
449
+ } catch {
450
+ return void 0;
451
+ }
452
+ const at = cliPath.indexOf("/lib/node_modules/flyspace-cli/");
453
+ if (at <= 0) return void 0;
454
+ const npmPrefix = cliPath.slice(0, at);
455
+ if (basename(npmPrefix) !== "cli") return void 0;
456
+ const home = dirname2(npmPrefix);
457
+ return existsSync3(join2(home, "bin", "flyspace")) && existsSync3(join2(home, "node", "bin", "node")) ? home : void 0;
458
+ }
445
459
  function serviceLabel(profile) {
446
460
  return profile === DEFAULT_PROFILE ? "ai.flyspace" : `ai.flyspace.${profile}`;
447
461
  }
@@ -557,7 +571,7 @@ function isHostServiceRunning() {
557
571
  // src/commands/install.ts
558
572
  import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync3, unlinkSync } from "fs";
559
573
  import { execSync as execSync2 } from "child_process";
560
- import { dirname as dirname2, join as join3, resolve as resolve3 } from "path";
574
+ import { dirname as dirname3, join as join3, resolve as resolve3 } from "path";
561
575
  import { homedir as homedir2, platform as platform2 } from "os";
562
576
  function log(msg) {
563
577
  console.log(`
@@ -578,17 +592,23 @@ function run(cmd, opts = {}) {
578
592
  function detectClaudeBinDir() {
579
593
  try {
580
594
  const claudePath = execSync2("which claude", { encoding: "utf-8", stdio: "pipe" }).trim();
581
- return claudePath ? dirname2(claudePath) : void 0;
595
+ return claudePath ? dirname3(claudePath) : void 0;
582
596
  } catch {
583
597
  return void 0;
584
598
  }
585
599
  }
600
+ function detectNodeBinDir() {
601
+ const home = flyspaceHome();
602
+ return home ? join3(home, "node", "bin") : dirname3(process.execPath);
603
+ }
586
604
  function nodeShimDirs() {
587
605
  return [join3(homedir2(), ".local", "share", "mise", "shims"), join3(homedir2(), ".asdf", "shims")].filter(
588
606
  (d) => existsSync4(d)
589
607
  );
590
608
  }
591
609
  function detectCustieBin() {
610
+ const home = flyspaceHome();
611
+ if (home) return join3(home, "bin", "flyspace");
592
612
  const argv1 = process.argv[1];
593
613
  if (argv1) {
594
614
  return resolve3(argv1);
@@ -644,14 +664,13 @@ function hostSpec() {
644
664
  async function installMacOS(spec) {
645
665
  log("Setting up macOS LaunchAgent...");
646
666
  const custieBin = detectCustieBin();
647
- const nodePath = process.execPath;
648
667
  const claudeBinDir = detectClaudeBinDir();
649
668
  const logDir = paths.LOG_DIR;
650
669
  mkdirSync2(logDir, { recursive: true });
651
670
  const envVars = spec.env;
652
671
  const homebrewBin = existsSync4("/opt/homebrew/bin") ? "/opt/homebrew/bin" : void 0;
653
672
  const pathParts = [
654
- dirname2(nodePath),
673
+ detectNodeBinDir(),
655
674
  claudeBinDir,
656
675
  ...nodeShimDirs(),
657
676
  homebrewBin,
@@ -695,7 +714,7 @@ ${Object.entries(envVars).map(([k, v]) => ` <key>${k}</key>
695
714
  </dict>
696
715
  </plist>`;
697
716
  const agentPlistPath = spec.plistPath;
698
- mkdirSync2(dirname2(agentPlistPath), { recursive: true });
717
+ mkdirSync2(dirname3(agentPlistPath), { recursive: true });
699
718
  try {
700
719
  run(`launchctl unload "${agentPlistPath}"`, { silent: true });
701
720
  } catch {
@@ -713,14 +732,13 @@ ${Object.entries(envVars).map(([k, v]) => ` <key>${k}</key>
713
732
  async function installLinux(spec) {
714
733
  log("Setting up systemd user service...");
715
734
  const custieBin = detectCustieBin();
716
- const nodePath = process.execPath;
717
735
  const claudeBinDir = detectClaudeBinDir();
718
736
  const logDir = paths.LOG_DIR;
719
737
  mkdirSync2(logDir, { recursive: true });
720
738
  const envLines = Object.entries(spec.env).map(([k, v]) => `Environment="${k}=${v}"`).join("\n");
721
739
  const linuxbrewBin = existsSync4("/home/linuxbrew/.linuxbrew/bin") ? "/home/linuxbrew/.linuxbrew/bin" : void 0;
722
740
  const pathParts = [
723
- dirname2(nodePath),
741
+ detectNodeBinDir(),
724
742
  claudeBinDir,
725
743
  ...nodeShimDirs(),
726
744
  linuxbrewBin,
@@ -814,7 +832,7 @@ function isServiceRunning2(profile) {
814
832
  // src/auth/device-auth.ts
815
833
  import { createPrivateKey, createPublicKey, generateKeyPairSync, sign } from "crypto";
816
834
  import { existsSync as existsSync6, mkdirSync as mkdirSync3, readFileSync as readFileSync5, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
817
- import { dirname as dirname3, join as join5 } from "path";
835
+ import { dirname as dirname4, join as join5 } from "path";
818
836
  var DEFAULT_API_URL = "https://app.flyspace.ai";
819
837
  var EXPIRY_SKEW_MS = 6e4;
820
838
  var AuthApiError = class extends Error {
@@ -837,7 +855,7 @@ function ensureDeviceKey(path = deviceKeyPath()) {
837
855
  let created = false;
838
856
  if (!existsSync6(path)) {
839
857
  const { privateKey: privateKey2 } = generateKeyPairSync("ed25519");
840
- mkdirSync3(dirname3(path), { recursive: true });
858
+ mkdirSync3(dirname4(path), { recursive: true });
841
859
  writeFileSync4(path, privateKey2.export({ type: "pkcs8", format: "pem" }), { mode: 384 });
842
860
  created = true;
843
861
  }
@@ -856,7 +874,7 @@ function loadCredentials(path = credentialsPath()) {
856
874
  }
857
875
  }
858
876
  function saveCredentials(creds, path = credentialsPath()) {
859
- mkdirSync3(dirname3(path), { recursive: true });
877
+ mkdirSync3(dirname4(path), { recursive: true });
860
878
  writeFileSync4(path, `${JSON.stringify(creds, null, 2)}
861
879
  `, { mode: 384 });
862
880
  }
@@ -1001,7 +1019,7 @@ import {
1001
1019
  symlinkSync
1002
1020
  } from "fs";
1003
1021
  import { homedir as homedir3 } from "os";
1004
- import { basename, join as join6, resolve as resolve4 } from "path";
1022
+ import { basename as basename2, join as join6, resolve as resolve4 } from "path";
1005
1023
  var MAX_JSONL_HEAD_BYTES = 64 * 1024;
1006
1024
  var GIT_SCAN_ROOTS = ["Workspaces", "Projects", "code"];
1007
1025
  function flyspaceRoot() {
@@ -1150,7 +1168,7 @@ function scanOnboarding() {
1150
1168
  } else {
1151
1169
  byPath.set(path, {
1152
1170
  path,
1153
- name: basename(path),
1171
+ name: basename2(path),
1154
1172
  sources: [source],
1155
1173
  lastUsed: mtime,
1156
1174
  sessions,
@@ -1553,7 +1571,7 @@ async function runAuthCmd(args) {
1553
1571
  }
1554
1572
 
1555
1573
  // src/version.ts
1556
- var CLI_VERSION = true ? "0.1.9" : null;
1574
+ var CLI_VERSION = true ? "0.1.10" : null;
1557
1575
  function isOlderVersion(a, b) {
1558
1576
  const parse2 = (v) => v.replace(/^v/, "").split("-")[0].split(".").map(Number);
1559
1577
  const [pa, pb] = [parse2(a), parse2(b)];
@@ -1833,7 +1851,7 @@ ${BOLD3}Flyspace Doctor${RESET3}
1833
1851
  // src/commands/uninstall.ts
1834
1852
  import { existsSync as existsSync8, unlinkSync as unlinkSync2 } from "fs";
1835
1853
  import { execSync as execSync5 } from "child_process";
1836
- import { basename as basename2, join as join8 } from "path";
1854
+ import { basename as basename3, join as join8 } from "path";
1837
1855
  import { homedir as homedir4, platform as platform5 } from "os";
1838
1856
  function log2(msg) {
1839
1857
  console.log(`
@@ -1862,7 +1880,7 @@ async function runUninstall() {
1862
1880
  }
1863
1881
  try {
1864
1882
  unlinkSync2(plist);
1865
- removed.push(basename2(plist));
1883
+ removed.push(basename3(plist));
1866
1884
  } catch {
1867
1885
  }
1868
1886
  }
@@ -1968,7 +1986,8 @@ async function runProfiles(args = []) {
1968
1986
 
1969
1987
  // src/commands/upgrade.ts
1970
1988
  import { execSync as execSync6 } from "child_process";
1971
- import { realpathSync } from "fs";
1989
+ import { realpathSync as realpathSync2 } from "fs";
1990
+ import { join as join9 } from "path";
1972
1991
  function restartInstalledProfiles() {
1973
1992
  if (isHostServiceInstalled()) {
1974
1993
  console.log(restartHostService() ? "\nHost restarted." : "\nHost restart failed; run: flyspace setup --start-host --restart");
@@ -1991,26 +2010,31 @@ Restarting ${installed.length} instance(s)...`);
1991
2010
  function npmInstallCommand() {
1992
2011
  let prefix;
1993
2012
  try {
1994
- const entry = realpathSync(process.argv[1] ?? "");
2013
+ const entry = realpathSync2(process.argv[1] ?? "");
1995
2014
  const at = entry.indexOf(`/lib/node_modules/${"flyspace-cli"}/`);
1996
2015
  if (at > 0) prefix = entry.slice(0, at);
1997
2016
  } catch {
1998
2017
  }
1999
- return `npm install -g${prefix ? ` --prefix "${prefix}"` : ""} ${"flyspace-cli"}@latest`;
2018
+ const global = `-g${prefix ? ` --prefix "${prefix}"` : ""}`;
2019
+ return `npm install ${global} --ignore-scripts ${"flyspace-cli"}@latest && npm rebuild ${global} better-sqlite3`;
2020
+ }
2021
+ function npmEnv() {
2022
+ const home = flyspaceHome();
2023
+ return home ? { ...process.env, PATH: `${join9(home, "node", "bin")}:${process.env.PATH ?? ""}` } : process.env;
2000
2024
  }
2001
2025
  async function runUpgrade() {
2002
- const current = "0.1.9";
2026
+ const current = "0.1.10";
2003
2027
  console.log(`Current version: ${current}`);
2004
2028
  console.log("Checking for updates...\n");
2005
2029
  try {
2006
- const latest = execSync6(`npm view ${"flyspace-cli"} version`, { encoding: "utf-8" }).trim();
2030
+ const latest = execSync6(`npm view ${"flyspace-cli"} version`, { encoding: "utf-8", env: npmEnv() }).trim();
2007
2031
  if (latest === current) {
2008
2032
  console.log(`Already on the latest version (${current}).`);
2009
2033
  return;
2010
2034
  }
2011
2035
  console.log(`New version available: ${latest}`);
2012
2036
  console.log("Upgrading...\n");
2013
- execSync6(npmInstallCommand(), { stdio: "inherit" });
2037
+ execSync6(npmInstallCommand(), { stdio: "inherit", env: npmEnv() });
2014
2038
  console.log(`
2015
2039
  Upgraded from ${current} to ${latest}.`);
2016
2040
  restartInstalledProfiles();
@@ -2613,11 +2637,11 @@ async function runRestart() {
2613
2637
  // src/commands/logs.ts
2614
2638
  import { spawn as spawn4 } from "child_process";
2615
2639
  import { existsSync as existsSync10 } from "fs";
2616
- import { join as join9 } from "path";
2640
+ import { join as join10 } from "path";
2617
2641
  async function runLogs(args) {
2618
2642
  const showErrors = args.includes("--error") || args.includes("-e");
2619
2643
  const filename = showErrors ? "custie-error.log" : "custie.log";
2620
- const logFile = join9(paths.LOG_DIR, filename);
2644
+ const logFile = join10(paths.LOG_DIR, filename);
2621
2645
  if (!existsSync10(logFile)) {
2622
2646
  console.error(`Log file not found: ${logFile}`);
2623
2647
  console.error("Is the service installed? Run `flyspace install` first.");
@@ -2696,7 +2720,7 @@ async function emailForToken(token, type) {
2696
2720
 
2697
2721
  // src/dashboard/profile-config.ts
2698
2722
  import { homedir as homedir5 } from "os";
2699
- import { join as join10 } from "path";
2723
+ import { join as join11 } from "path";
2700
2724
 
2701
2725
  // src/dashboard/profile-config-cache.ts
2702
2726
  var cache = /* @__PURE__ */ new Map();
@@ -2715,7 +2739,7 @@ function profileEnv(key) {
2715
2739
  function profileClaudeConfigDir() {
2716
2740
  const config = cachedProfileConfig();
2717
2741
  if (!config) return process.env["CLAUDE_CONFIG_DIR"] || void 0;
2718
- return config.env["CLAUDE_CONFIG_DIR"]?.trim() || join10(homedir5(), ".claude");
2742
+ return config.env["CLAUDE_CONFIG_DIR"]?.trim() || join11(homedir5(), ".claude");
2719
2743
  }
2720
2744
  function profileOauthToken() {
2721
2745
  const env = cachedProfileConfig()?.env ?? {};
@@ -4169,7 +4193,7 @@ async function deliverPasswordResetLink(email, redirectTo) {
4169
4193
  // src/dashboard/server.ts
4170
4194
  import { existsSync as existsSync26 } from "fs";
4171
4195
  import { createServer } from "net";
4172
- import { join as join22 } from "path";
4196
+ import { join as join23 } from "path";
4173
4197
  import { Hono as Hono33 } from "hono";
4174
4198
  import { serve } from "@hono/node-server";
4175
4199
  import { serveStatic } from "@hono/node-server/serve-static";
@@ -4374,7 +4398,7 @@ import { Hono as Hono30 } from "hono";
4374
4398
 
4375
4399
  // src/dashboard/public-share-routes.ts
4376
4400
  import { existsSync as existsSync12, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
4377
- import { join as join12 } from "path";
4401
+ import { join as join13 } from "path";
4378
4402
  import { Hono as Hono3 } from "hono";
4379
4403
  import { GetObjectCommand } from "@aws-sdk/client-s3";
4380
4404
  import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
@@ -4840,11 +4864,11 @@ function injectShareHead(html, head) {
4840
4864
  // src/dashboard/app-icon.ts
4841
4865
  import { createHash as createHash2 } from "crypto";
4842
4866
  import { readFileSync as readFileSync7 } from "fs";
4843
- import { join as join11 } from "path";
4867
+ import { join as join12 } from "path";
4844
4868
  import sharp from "sharp";
4845
4869
  var PLATE = "#0A0A0F";
4846
- var MARK_FILE = join11(paths.PACKAGE_ROOT, "web", "public", "icons", "icon-512.png");
4847
- var MARK_SVG_FILE = join11(paths.PACKAGE_ROOT, "web", "public", "favicon.svg");
4870
+ var MARK_FILE = join12(paths.PACKAGE_ROOT, "web", "public", "icons", "icon-512.png");
4871
+ var MARK_SVG_FILE = join12(paths.PACKAGE_ROOT, "web", "public", "favicon.svg");
4848
4872
  var LAYOUT = {
4849
4873
  standard: { logo: 0.7, logoCx: 0.5, logoCy: 0.48, badge: 0.27, badgeCx: 0.22, badgeCy: 0.76 },
4850
4874
  maskable: { logo: 0.56, logoCx: 0.5, logoCy: 0.48, badge: 0.23, badgeCx: 0.33, badgeCy: 0.66 }
@@ -6160,7 +6184,7 @@ function serveBuildFile(c, webDist, dir, name) {
6160
6184
  if (!type || !/^[A-Za-z0-9._-]+$/.test(name) || name.includes("..")) {
6161
6185
  return c.text("not found", 404);
6162
6186
  }
6163
- const path = join12(webDist, dir, name);
6187
+ const path = join13(webDist, dir, name);
6164
6188
  if (!existsSync12(path)) return c.text("not found", 404);
6165
6189
  c.header("Content-Type", type);
6166
6190
  c.header("Cache-Control", "public, max-age=31536000, immutable");
@@ -6306,7 +6330,7 @@ ${analytics}` : head);
6306
6330
  const requested = c.req.param("lang");
6307
6331
  const lang = canonicalLanguage(requested);
6308
6332
  if (!isTranslatableLanguage(lang)) return next();
6309
- const shell = join12(webDist, "index.html");
6333
+ const shell = join13(webDist, "index.html");
6310
6334
  if (!existsSync12(shell)) return next();
6311
6335
  const share = await getDocShare(c.req.param("id"));
6312
6336
  if (!share) return next();
@@ -6342,7 +6366,7 @@ ${analytics}` : head);
6342
6366
  const share = await getDocShare(c.req.param("id"));
6343
6367
  if (!share) return next();
6344
6368
  if (share.kind === "html") return servePublishedHtml(c, share);
6345
- const shell = join12(webDist, "index.html");
6369
+ const shell = join13(webDist, "index.html");
6346
6370
  if (!existsSync12(shell)) return next();
6347
6371
  return readerPage(
6348
6372
  c,
@@ -6974,7 +6998,7 @@ async function offlineAgentIdentities() {
6974
6998
 
6975
6999
  // src/dashboard/host-api.ts
6976
7000
  import { existsSync as existsSync21, readFileSync as readFileSync12, statSync as statSync8 } from "fs";
6977
- import { join as join19 } from "path";
7001
+ import { join as join20 } from "path";
6978
7002
  import sharp3 from "sharp";
6979
7003
 
6980
7004
  // src/dashboard/channels-routes.ts
@@ -7010,6 +7034,11 @@ var featureFlags = {
7010
7034
  title: "Dictation",
7011
7035
  description: "A mic button in the message composer that turns speech into text as you talk. Each phrase uses speech-to-text.",
7012
7036
  stage: "dev"
7037
+ },
7038
+ "agent-memory": {
7039
+ title: "Agent memory",
7040
+ description: "Channel memory the agent reads every turn, saved by the agent and picked up from idle threads, with a Memory tab and an undo chip. While on, Claude's built-in auto memory is switched off so the two can be compared; turning this off keeps every memory.",
7041
+ stage: "beta"
7013
7042
  }
7014
7043
  };
7015
7044
  var featureFlagIds = Object.keys(featureFlags);
@@ -7035,6 +7064,11 @@ async function listEnabledFeatureFlags(workspaceId) {
7035
7064
  if (error2) throw new Error(`listEnabledFeatureFlags(${workspaceId}): ${error2.message}`);
7036
7065
  return (data ?? []).map((r) => r.flag_id);
7037
7066
  }
7067
+ async function listEnabledFeatureFlagsBySlug(slug) {
7068
+ const { data, error: error2 } = await getSupabaseClient().from("workspaces").select("id").eq("slug", slug).maybeSingle();
7069
+ if (error2) throw new Error(`listEnabledFeatureFlagsBySlug(${slug}): ${error2.message}`);
7070
+ return data ? listEnabledFeatureFlags(data.id) : [];
7071
+ }
7038
7072
  async function enableFeatureFlag(workspaceId, flagId, userId) {
7039
7073
  const { error: error2 } = await getSupabaseClient().from("feature_flags").upsert(
7040
7074
  { workspace_id: workspaceId, flag_id: flagId, enabled_by: userId },
@@ -7272,19 +7306,19 @@ import {
7272
7306
  readSync,
7273
7307
  readdirSync as readdirSync4,
7274
7308
  readFileSync as readFileSync11,
7275
- realpathSync as realpathSync2,
7309
+ realpathSync as realpathSync3,
7276
7310
  renameSync,
7277
7311
  rmSync as rmSync5,
7278
7312
  statSync as statSync5,
7279
7313
  writeFileSync as writeFileSync7
7280
7314
  } from "fs";
7281
- import { basename as basename5, dirname as dirname4, extname, join as join17, relative, resolve as resolve5, sep } from "path";
7315
+ import { basename as basename6, dirname as dirname5, extname, join as join18, relative, resolve as resolve5, sep } from "path";
7282
7316
  import { Hono as Hono10 } from "hono";
7283
7317
  import { streamSSE } from "hono/streaming";
7284
7318
 
7285
7319
  // src/dashboard/docs-watcher.ts
7286
7320
  import { existsSync as existsSync14, watch } from "fs";
7287
- import { basename as basename3, join as join13 } from "path";
7321
+ import { basename as basename4, join as join14 } from "path";
7288
7322
  var DEBOUNCE_MS = 200;
7289
7323
  var MAX_PENDING = 200;
7290
7324
  var IGNORED_SEGMENTS = /* @__PURE__ */ new Set([
@@ -7320,12 +7354,12 @@ function flush(cwd) {
7320
7354
  function watchDocs(cwd, listener) {
7321
7355
  let entry = entries.get(cwd);
7322
7356
  if (!entry) {
7323
- const root = basename3(cwd);
7357
+ const root = basename4(cwd);
7324
7358
  const watcher = watch(cwd, { recursive: true, persistent: false }, (_event, filename) => {
7325
7359
  const current = entries.get(cwd);
7326
7360
  if (!current || filename === null) return;
7327
7361
  const rel = filename.split("\\").join("/");
7328
- if (rel === root && !existsSync14(join13(cwd, rel))) return;
7362
+ if (rel === root && !existsSync14(join14(cwd, rel))) return;
7329
7363
  if (isIgnoredDocPath(rel)) return;
7330
7364
  if (current.pending.size < MAX_PENDING) current.pending.add(rel);
7331
7365
  if (current.timer === null) current.timer = setTimeout(() => flush(cwd), DEBOUNCE_MS);
@@ -7570,7 +7604,7 @@ import { homedir as homedir7 } from "os";
7570
7604
  // src/mcp/config.ts
7571
7605
  import { mkdtempSync, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "fs";
7572
7606
  import { tmpdir as tmpdir2 } from "os";
7573
- import { join as join14 } from "path";
7607
+ import { join as join15 } from "path";
7574
7608
 
7575
7609
  // src/mcp/crypto.ts
7576
7610
  import { createCipheriv, createDecipheriv, randomBytes as randomBytes3, timingSafeEqual } from "crypto";
@@ -8256,8 +8290,8 @@ async function buildMcpConfig(profile, connectionIds) {
8256
8290
  return { config, skipped };
8257
8291
  }
8258
8292
  function writeMcpConfigFile(config) {
8259
- const dir = mkdtempSync(join14(tmpdir2(), "flyspace-mcp-"));
8260
- const path = join14(dir, "mcp-config.json");
8293
+ const dir = mkdtempSync(join15(tmpdir2(), "flyspace-mcp-"));
8294
+ const path = join15(dir, "mcp-config.json");
8261
8295
  writeFileSync6(path, JSON.stringify(config), { mode: 384 });
8262
8296
  return {
8263
8297
  path,
@@ -8280,14 +8314,14 @@ async function withMcpConfig(profile, connectionIds, fn) {
8280
8314
  // src/claude/agents.ts
8281
8315
  import { existsSync as existsSync15, readdirSync as readdirSync3, readFileSync as readFileSync9 } from "fs";
8282
8316
  import { homedir as homedir6 } from "os";
8283
- import { basename as basename4, join as join15 } from "path";
8317
+ import { basename as basename5, join as join16 } from "path";
8284
8318
  import yaml from "js-yaml";
8285
8319
  function defaultConfigDir() {
8286
- return join15(homedir6(), ".claude");
8320
+ return join16(homedir6(), ".claude");
8287
8321
  }
8288
8322
  function expandHome(p) {
8289
8323
  if (p === "~") return homedir6();
8290
- if (p.startsWith("~/")) return join15(homedir6(), p.slice(2));
8324
+ if (p.startsWith("~/")) return join16(homedir6(), p.slice(2));
8291
8325
  return p;
8292
8326
  }
8293
8327
  function parseFrontmatter(file) {
@@ -8317,17 +8351,17 @@ function collectFrom(root, source) {
8317
8351
  return [];
8318
8352
  }
8319
8353
  return entries2.map((file) => {
8320
- const path = join15(root, file);
8354
+ const path = join16(root, file);
8321
8355
  const fm = parseFrontmatter(path);
8322
- const name = fm.name?.trim() || basename4(file, ".md");
8356
+ const name = fm.name?.trim() || basename5(file, ".md");
8323
8357
  return { name, description: (fm.description ?? "").trim(), source, path };
8324
8358
  });
8325
8359
  }
8326
8360
  function listAgents(configDir2, cwd) {
8327
8361
  const base = configDir2 ? expandHome(configDir2) : defaultConfigDir();
8328
8362
  const collected = [
8329
- ...collectFrom(join15(cwd, ".claude", "agents"), "project"),
8330
- ...collectFrom(join15(base, "agents"), "user")
8363
+ ...collectFrom(join16(cwd, ".claude", "agents"), "project"),
8364
+ ...collectFrom(join16(base, "agents"), "user")
8331
8365
  ];
8332
8366
  const byName = /* @__PURE__ */ new Map();
8333
8367
  for (const agent of collected) {
@@ -8839,7 +8873,7 @@ ${recent.map((m) => `${m.author}: ${m.body}`).join("\n")}`;
8839
8873
 
8840
8874
  // src/dashboard/attachment-downloader.ts
8841
8875
  import { writeFile } from "fs/promises";
8842
- import { join as join16 } from "path";
8876
+ import { join as join17 } from "path";
8843
8877
  import { GetObjectCommand as GetObjectCommand4 } from "@aws-sdk/client-s3";
8844
8878
  var debug = process.env["DEBUG"] === "true";
8845
8879
  var ATTACHMENT_LINK = /\]\(\/api\/attachments\/([^)?\s]+)(?:\?[^)\s]*)?\)/g;
@@ -8886,7 +8920,7 @@ async function downloadOne(key) {
8886
8920
  if (bytes.length > sizeLimit) {
8887
8921
  return { kind: "skip", skipped: { name, mimetype, reason: "too_large" } };
8888
8922
  }
8889
- const localPath = join16(paths.UPLOADS_DIR, lastSegment);
8923
+ const localPath = join17(paths.UPLOADS_DIR, lastSegment);
8890
8924
  await writeFile(localPath, bytes);
8891
8925
  if (debug)
8892
8926
  console.log(`[attachment-downloader] saved ${key} -> ${localPath} (${bytes.length} bytes)`);
@@ -9432,7 +9466,12 @@ var ChatAgent = class {
9432
9466
  thread.channel_id
9433
9467
  );
9434
9468
  if (docsAccess && docsAccess !== "write") channelConfig = { ...channelConfig, docsAccess };
9435
- if (docsAccess !== "none" && isUuid(thread.channel_id)) {
9469
+ const agentMemory = await listEnabledFeatureFlagsBySlug(owningProfile).then((ids) => resolveFeatureFlags(ids, false)["agent-memory"]).catch((err) => {
9470
+ console.error("[chat-agent] feature flag lookup failed:", err.message);
9471
+ return false;
9472
+ });
9473
+ if (agentMemory) channelConfig = { ...channelConfig, disableAutoMemory: true };
9474
+ if (agentMemory && docsAccess !== "none" && isUuid(thread.channel_id)) {
9436
9475
  const memoryPrompt = await listChannelMemories(thread.channel_id).then((memories) => formatMemoryPrompt(thread.channel_id, memories)).catch((err) => {
9437
9476
  console.error("[chat-agent] memory lookup failed:", err.message);
9438
9477
  return void 0;
@@ -9847,7 +9886,8 @@ ${msg.body}` : msg.body;
9847
9886
  mcpConfigPath,
9848
9887
  ...usageContext ? { usageContext } : {},
9849
9888
  ...channelConfig.docsAccess ? { docsAccess: channelConfig.docsAccess } : {},
9850
- ...channelConfig.memoryPrompt ? { memoryPrompt: channelConfig.memoryPrompt } : {}
9889
+ ...channelConfig.memoryPrompt ? { memoryPrompt: channelConfig.memoryPrompt } : {},
9890
+ ...channelConfig.disableAutoMemory ? { disableAutoMemory: true } : {}
9851
9891
  },
9852
9892
  channelConfig.claudeConfigDir,
9853
9893
  sessionId,
@@ -10377,9 +10417,9 @@ function readHead(absPath) {
10377
10417
  }
10378
10418
  }
10379
10419
  function extractTitle(absPath, kind) {
10380
- if (kind === "url" || kind === "excalidraw") return basename5(absPath);
10420
+ if (kind === "url" || kind === "excalidraw") return basename6(absPath);
10381
10421
  const head = readHead(absPath);
10382
- if (!head) return basename5(absPath);
10422
+ if (!head) return basename6(absPath);
10383
10423
  if (kind === "md") {
10384
10424
  const m = head.match(/^#{1,3}\s+(.+?)\s*$/m);
10385
10425
  if (m) return m[1].replace(/[*_`]/g, "").trim();
@@ -10387,7 +10427,7 @@ function extractTitle(absPath, kind) {
10387
10427
  const t = head.match(/<title[^>]*>([^<]+)<\/title>/i) ?? head.match(/<h1[^>]*>([^<]+)<\/h1>/i);
10388
10428
  if (t) return t[1].trim();
10389
10429
  }
10390
- return basename5(absPath);
10430
+ return basename6(absPath);
10391
10431
  }
10392
10432
  function resolveDirPath(root, rel) {
10393
10433
  if (rel.includes("\0")) return null;
@@ -10419,7 +10459,7 @@ function probeDir(absDir, showHidden) {
10419
10459
  return false;
10420
10460
  }
10421
10461
  if (!showHidden && entry.name.startsWith(".")) continue;
10422
- const abs = join17(dir, entry.name);
10462
+ const abs = join18(dir, entry.name);
10423
10463
  const kind = entryKind(entry, abs);
10424
10464
  if (kind === "dir") {
10425
10465
  if (SKIP_DIRS.has(entry.name)) hasOther = true;
@@ -10439,14 +10479,14 @@ function probeDir(absDir, showHidden) {
10439
10479
  }
10440
10480
  function readGitBranch(dir) {
10441
10481
  try {
10442
- let gitDir = join17(dir, ".git");
10482
+ let gitDir = join18(dir, ".git");
10443
10483
  if (statSync5(gitDir).isFile()) {
10444
10484
  const pointer = readFileSync11(gitDir, "utf8").trim();
10445
10485
  const match = pointer.match(/^gitdir:\s*(.+)$/);
10446
10486
  if (!match) return void 0;
10447
10487
  gitDir = resolve5(dir, match[1]);
10448
10488
  }
10449
- const head = readFileSync11(join17(gitDir, "HEAD"), "utf8").trim();
10489
+ const head = readFileSync11(join18(gitDir, "HEAD"), "utf8").trim();
10450
10490
  const branchMatch = head.match(/^ref:\s*refs\/heads\/(.+)$/);
10451
10491
  if (branchMatch) return branchMatch[1];
10452
10492
  return /^[0-9a-f]{7,40}$/i.test(head) ? head.slice(0, 7) : void 0;
@@ -10468,14 +10508,14 @@ function listDocLevel(root, relDir = "", sort = "newest", showHidden = false) {
10468
10508
  for (const entry of entries2) {
10469
10509
  if (dirs.length + docs.length >= MAX_ENTRIES) break;
10470
10510
  if (!showHidden && entry.name.startsWith(".")) continue;
10471
- const abs = join17(absDir, entry.name);
10511
+ const abs = join18(absDir, entry.name);
10472
10512
  const path = relative(root, abs).split(sep).join("/");
10473
10513
  const kind = entryKind(entry, abs);
10474
10514
  if (kind === "dir") {
10475
10515
  if (SKIP_DIRS.has(entry.name)) continue;
10476
10516
  const probe3 = probeDir(abs, showHidden);
10477
10517
  if (!probe3.hasDocs && probe3.hasOther) continue;
10478
- const isRepo = existsSync17(join17(abs, ".git"));
10518
+ const isRepo = existsSync17(join18(abs, ".git"));
10479
10519
  dirs.push({
10480
10520
  path,
10481
10521
  name: entry.name,
@@ -10511,7 +10551,7 @@ function flatDocs(root, {
10511
10551
  for (const entry of entries2) {
10512
10552
  if (hits.length >= MAX_FLAT_DOCS) return;
10513
10553
  if (!showHidden && entry.name.startsWith(".")) continue;
10514
- const abs = join17(dir, entry.name);
10554
+ const abs = join18(dir, entry.name);
10515
10555
  const kind = entryKind(entry, abs);
10516
10556
  if (kind === "dir") {
10517
10557
  if (!SKIP_DIRS.has(entry.name)) walk(abs, depth + 1);
@@ -10575,7 +10615,7 @@ function resolveDownloadPath(root, rel) {
10575
10615
  if (!rel || rel.includes("\0")) return null;
10576
10616
  const abs = resolve5(root, rel);
10577
10617
  if (abs !== root && !abs.startsWith(root + sep)) return null;
10578
- if (!isListableFile(basename5(abs))) return null;
10618
+ if (!isListableFile(basename6(abs))) return null;
10579
10619
  const contentType = MEDIA_EXTENSIONS[extname(abs).toLowerCase()] ?? "application/octet-stream";
10580
10620
  return { abs, contentType };
10581
10621
  }
@@ -10591,7 +10631,7 @@ function uniqueName(absDir, name) {
10591
10631
  let candidate = name;
10592
10632
  for (let n = 1; n < 1e3; n++) {
10593
10633
  try {
10594
- statSync5(join17(absDir, candidate));
10634
+ statSync5(join18(absDir, candidate));
10595
10635
  } catch {
10596
10636
  return candidate;
10597
10637
  }
@@ -10613,7 +10653,7 @@ function saveUploadedFile(root, relDir, name, data) {
10613
10653
  if (!(ext in DOC_EXTENSIONS) && !ASSET_LIST_EXTENSIONS.has(ext)) return { status: "bad-type" };
10614
10654
  if (data.byteLength > MAX_UPLOAD_BYTES) return { status: "too-large" };
10615
10655
  const final = uniqueName(absDir, safe);
10616
- const abs = join17(absDir, final);
10656
+ const abs = join18(absDir, final);
10617
10657
  writeFileSync7(abs, data);
10618
10658
  return { status: "ok", path: relative(root, abs).split(sep).join("/"), name: final };
10619
10659
  }
@@ -10627,7 +10667,7 @@ function createDocFolder(root, relDir, name) {
10627
10667
  }
10628
10668
  const safe = sanitizeUploadName(name);
10629
10669
  if (!safe) return { status: "bad-name" };
10630
- const abs = join17(absDir, safe);
10670
+ const abs = join18(absDir, safe);
10631
10671
  try {
10632
10672
  statSync5(abs);
10633
10673
  return { status: "exists" };
@@ -10650,7 +10690,7 @@ function createDocFile(root, relDir, name, content) {
10650
10690
  if (!(ext in DOC_EXTENSIONS) && !(ext in CODE_EXTENSIONS)) return { status: "bad-name" };
10651
10691
  if (SKIP_FILES.has(safe)) return { status: "bad-name" };
10652
10692
  if (Buffer.byteLength(content, "utf8") > MAX_CONTENT_BYTES) return { status: "too-large" };
10653
- const abs = join17(absDir, safe);
10693
+ const abs = join18(absDir, safe);
10654
10694
  try {
10655
10695
  writeFileSync7(abs, content, { encoding: "utf8", flag: "wx" });
10656
10696
  } catch (err) {
@@ -10673,7 +10713,7 @@ function moveDocEntry(root, from, to) {
10673
10713
  if (!isDir2 && !stat.isFile()) return { status: "not-found" };
10674
10714
  const absTo = resolve5(root, to);
10675
10715
  if (!absTo.startsWith(root + sep)) return { status: "bad-target" };
10676
- const name = sanitizeUploadName(basename5(absTo));
10716
+ const name = sanitizeUploadName(basename6(absTo));
10677
10717
  if (!name) return { status: "bad-target" };
10678
10718
  if (!isDir2) {
10679
10719
  const ext = extname(name).toLowerCase();
@@ -10681,19 +10721,19 @@ function moveDocEntry(root, from, to) {
10681
10721
  return { status: "bad-target" };
10682
10722
  }
10683
10723
  }
10684
- const absToDir = dirname4(absTo);
10724
+ const absToDir = dirname5(absTo);
10685
10725
  if (resolveDirPath(root, relative(root, absToDir)) === null) return { status: "bad-target" };
10686
10726
  try {
10687
10727
  if (!statSync5(absToDir).isDirectory()) return { status: "bad-target" };
10688
10728
  } catch {
10689
10729
  return { status: "bad-target" };
10690
10730
  }
10691
- const finalAbs = join17(absToDir, name);
10731
+ const finalAbs = join18(absToDir, name);
10692
10732
  if (isDir2 && (finalAbs === absFrom || finalAbs.startsWith(absFrom + sep))) {
10693
10733
  return { status: "into-self" };
10694
10734
  }
10695
10735
  try {
10696
- if (realpathSync2(finalAbs) !== realpathSync2(absFrom)) return { status: "exists" };
10736
+ if (realpathSync3(finalAbs) !== realpathSync3(absFrom)) return { status: "exists" };
10697
10737
  } catch {
10698
10738
  }
10699
10739
  renameSync(absFrom, finalAbs);
@@ -10753,7 +10793,7 @@ function createDocsRouter() {
10753
10793
  const data = readFileSync11(resolved2.abs);
10754
10794
  const headers = { "Content-Type": resolved2.contentType };
10755
10795
  if (download) {
10756
- const filename = basename5(resolved2.abs).replace(/"/g, "");
10796
+ const filename = basename6(resolved2.abs).replace(/"/g, "");
10757
10797
  headers["Content-Disposition"] = `attachment; filename="${filename}"`;
10758
10798
  }
10759
10799
  return c.body(new Uint8Array(data), 200, headers);
@@ -10952,7 +10992,7 @@ function createDocsRouter() {
10952
10992
  // by; only docs get a parsed title.
10953
10993
  kind: kind ?? "code",
10954
10994
  lang: kind ? void 0 : CODE_EXTENSIONS[ext],
10955
- title: kind ? extractTitle(abs, kind) : basename5(abs),
10995
+ title: kind ? extractTitle(abs, kind) : basename6(abs),
10956
10996
  mtime: stat.mtime.toISOString(),
10957
10997
  tooLarge: tooLarge || void 0,
10958
10998
  content: tooLarge ? "" : readFileSync11(abs, "utf8")
@@ -11195,7 +11235,7 @@ function relay(agent, pathOf) {
11195
11235
 
11196
11236
  // src/dashboard/skills-routes.ts
11197
11237
  import { existsSync as existsSync19, statSync as statSync7 } from "fs";
11198
- import { dirname as dirname5 } from "path";
11238
+ import { dirname as dirname6 } from "path";
11199
11239
  import { Hono as Hono12 } from "hono";
11200
11240
 
11201
11241
  // src/dashboard/skill-mirror.ts
@@ -11320,7 +11360,7 @@ function workspaceScope() {
11320
11360
  return {
11321
11361
  dir: workspaceSkillsDir(claudeConfigDir),
11322
11362
  // `~/.claude` itself, which exists wherever the CLI has ever run.
11323
- root: dirname5(workspaceSkillsDir(claudeConfigDir)),
11363
+ root: dirname6(workspaceSkillsDir(claudeConfigDir)),
11324
11364
  cwd,
11325
11365
  claudeConfigDir,
11326
11366
  // Only plugin skills. Project skills belong to a specific channel's cwd, so
@@ -11450,7 +11490,7 @@ function mirrorBackend(agent) {
11450
11490
  }
11451
11491
  }
11452
11492
  return {
11453
- dir: own[0] ? dirname5(dirname5(own[0].path)) : "",
11493
+ dir: own[0] ? dirname6(dirname6(own[0].path)) : "",
11454
11494
  skills: own.map(({ name, description, mtime }) => ({ name, description, mtime })),
11455
11495
  inherited: inherited.sort(byName)
11456
11496
  };
@@ -11540,7 +11580,7 @@ function registerMirroredSkillRoutes(api, agent) {
11540
11580
  import { execFileSync as execFileSync2 } from "child_process";
11541
11581
  import { existsSync as existsSync20 } from "fs";
11542
11582
  import { homedir as homedir8 } from "os";
11543
- import { join as join18, resolve as resolve6 } from "path";
11583
+ import { join as join19, resolve as resolve6 } from "path";
11544
11584
  var PROVIDER_LABELS = {
11545
11585
  claude: "Claude Code",
11546
11586
  codex: "Codex"
@@ -11558,7 +11598,7 @@ function binaryOnPath(bin) {
11558
11598
  function claudeAuthAvailable() {
11559
11599
  if (profileEnv("CLAUDE_CODE_OAUTH_TOKEN")?.trim()) return true;
11560
11600
  const configDir2 = profileClaudeConfigDir() || resolve6(homedir8(), ".claude");
11561
- if (existsSync20(join18(configDir2, ".credentials.json"))) return true;
11601
+ if (existsSync20(join19(configDir2, ".credentials.json"))) return true;
11562
11602
  if (process.platform !== "darwin") return false;
11563
11603
  try {
11564
11604
  execFileSync2("security", ["find-generic-password", "-s", "Claude Code-credentials"], {
@@ -11701,7 +11741,7 @@ function registerHostRoutes(api) {
11701
11741
  const errors = c.req.query("error") === "true" || c.req.query("error") === "1";
11702
11742
  const limit = Math.min(Number(c.req.query("limit")) || 200, 2e3);
11703
11743
  const filename = errors ? "custie-error.log" : "custie.log";
11704
- const file = join19(paths.LOG_DIR, filename);
11744
+ const file = join20(paths.LOG_DIR, filename);
11705
11745
  const exists = existsSync21(file);
11706
11746
  return c.json({
11707
11747
  file,
@@ -14790,6 +14830,12 @@ var requireChannelVisible = async (c, next) => {
14790
14830
  c.set("memoryChannelId", channel.id);
14791
14831
  await next();
14792
14832
  };
14833
+ var requireAgentMemory = async (c, next) => {
14834
+ if (!await isFeatureEnabled(c, "agent-memory")) {
14835
+ return c.json({ error: "feature not enabled" }, 403);
14836
+ }
14837
+ await next();
14838
+ };
14793
14839
  function createMemoriesRouter() {
14794
14840
  const router = new Hono27();
14795
14841
  for (const path of [
@@ -14798,7 +14844,7 @@ function createMemoriesRouter() {
14798
14844
  "/:id/memory-events",
14799
14845
  "/:id/memory-events/*"
14800
14846
  ]) {
14801
- router.use(path, requireChannelVisible, requireDocsAccess);
14847
+ router.use(path, requireAgentMemory, requireChannelVisible, requireDocsAccess);
14802
14848
  }
14803
14849
  router.get("/:id/memories", async (c) => {
14804
14850
  return c.json({ memories: await listChannelMemories(c.get("memoryChannelId")) });
@@ -15449,9 +15495,9 @@ import { WebSocket, WebSocketServer } from "ws";
15449
15495
  // src/dashboard/host-identity.ts
15450
15496
  import { createPrivateKey as createPrivateKey2, createPublicKey as createPublicKey2, generateKeyPairSync as generateKeyPairSync2 } from "crypto";
15451
15497
  import { existsSync as existsSync24, mkdirSync as mkdirSync9, readFileSync as readFileSync13, writeFileSync as writeFileSync8 } from "fs";
15452
- import { dirname as dirname6, join as join20 } from "path";
15498
+ import { dirname as dirname7, join as join21 } from "path";
15453
15499
  function hostPrivateKeyPath() {
15454
- return process.env["FLYSPACE_HOST_KEY_PATH"] || join20(paths.BASE_CONFIG_DIR, "host.key");
15500
+ return process.env["FLYSPACE_HOST_KEY_PATH"] || join21(paths.BASE_CONFIG_DIR, "host.key");
15455
15501
  }
15456
15502
  function loadHostPrivateKey(path = hostPrivateKeyPath()) {
15457
15503
  if (!existsSync24(path)) {
@@ -15476,9 +15522,9 @@ function loadHostPublicKey() {
15476
15522
  import { execFileSync as execFileSync3 } from "child_process";
15477
15523
  import { randomBytes as randomBytes5 } from "crypto";
15478
15524
  import { mkdirSync as mkdirSync10, readFileSync as readFileSync14, rmSync as rmSync6, writeFileSync as writeFileSync9 } from "fs";
15479
- import { join as join21 } from "path";
15525
+ import { join as join22 } from "path";
15480
15526
  function hostLockPath() {
15481
- return join21(paths.BASE_DATA_DIR, "host.lock");
15527
+ return join22(paths.BASE_DATA_DIR, "host.lock");
15482
15528
  }
15483
15529
  function isLiveFlyspace(pid) {
15484
15530
  try {
@@ -17499,7 +17545,7 @@ function startHostStatusBroadcast() {
17499
17545
 
17500
17546
  // src/dashboard/server.ts
17501
17547
  var DEFAULT_DASHBOARD_PORT = 4747;
17502
- var WEB_DIST = join22(paths.PACKAGE_ROOT, "web", "dist");
17548
+ var WEB_DIST = join23(paths.PACKAGE_ROOT, "web", "dist");
17503
17549
  var DEFAULT_DASHBOARD_HOST = "127.0.0.1";
17504
17550
  async function findFreePort(start, host = DEFAULT_DASHBOARD_HOST, attempts = 50) {
17505
17551
  for (let port = start; port < start + attempts; port++) {
@@ -17573,14 +17619,14 @@ async function startDashboardServer(preferredPort = DEFAULT_DASHBOARD_PORT, host
17573
17619
  } else {
17574
17620
  app.route("/share", createPublicShareAssetRouter(WEB_DIST));
17575
17621
  app.route("/", createAppIconRouter());
17576
- if (existsSync26(WEB_DIST) || existsSync26(join22(paths.PACKAGE_ROOT, "web", "package.json"))) {
17622
+ if (existsSync26(WEB_DIST) || existsSync26(join23(paths.PACKAGE_ROOT, "web", "package.json"))) {
17577
17623
  app.use("/*", serveStatic({ root: WEB_DIST }));
17578
17624
  }
17579
17625
  app.get("/assets/*", (c) => c.text("stale asset \u2014 reload for the current build", 404));
17580
- const spaFallback = serveStatic({ path: join22(WEB_DIST, "index.html") });
17626
+ const spaFallback = serveStatic({ path: join23(WEB_DIST, "index.html") });
17581
17627
  app.get("*", async (c, next) => {
17582
- if (!existsSync26(join22(WEB_DIST, "index.html"))) {
17583
- const isCheckout = existsSync26(join22(paths.PACKAGE_ROOT, "web", "package.json"));
17628
+ if (!existsSync26(join23(WEB_DIST, "index.html"))) {
17629
+ const isCheckout = existsSync26(join23(paths.PACKAGE_ROOT, "web", "package.json"));
17584
17630
  return c.text(
17585
17631
  isCheckout ? `Workspace UI build missing (${WEB_DIST}).
17586
17632
  Run \`pnpm --dir web build\` (or \`pnpm --dir web dev\`).
@@ -17635,7 +17681,7 @@ function watchServices() {
17635
17681
 
17636
17682
  // src/slack/image-uploader.ts
17637
17683
  import { readFile } from "fs/promises";
17638
- import { basename as basename6 } from "path";
17684
+ import { basename as basename7 } from "path";
17639
17685
  import sharp6 from "sharp";
17640
17686
  var MAX_WIDTH = 800;
17641
17687
  async function uploadImage(client2, { channel, filePath, threadTs, text }) {
@@ -17644,7 +17690,7 @@ async function uploadImage(client2, { channel, filePath, threadTs, text }) {
17644
17690
  const base = {
17645
17691
  channel_id: channel,
17646
17692
  file: resized,
17647
- filename: basename6(filePath),
17693
+ filename: basename7(filePath),
17648
17694
  ...text ? { initial_comment: text } : {}
17649
17695
  };
17650
17696
  const result = await client2.filesUploadV2(threadTs ? { ...base, thread_ts: threadTs } : base);
@@ -19083,7 +19129,7 @@ async function runMcpCmd(args) {
19083
19129
  import { spawn as spawn6, spawnSync } from "child_process";
19084
19130
  import { existsSync as existsSync28 } from "fs";
19085
19131
  import { platform as platform7 } from "os";
19086
- import { join as join23 } from "path";
19132
+ import { join as join24 } from "path";
19087
19133
  function flagValue(args, name) {
19088
19134
  const eq = args.find((a) => a.startsWith(`--${name}=`));
19089
19135
  if (eq) return eq.slice(`--${name}=`.length);
@@ -19098,8 +19144,8 @@ function openBrowser2(url) {
19098
19144
  }
19099
19145
  }
19100
19146
  function ensureWebBuild() {
19101
- if (existsSync28(join23(paths.PACKAGE_ROOT, "web", "dist", "index.html"))) return;
19102
- if (!existsSync28(join23(paths.PACKAGE_ROOT, "web", "package.json"))) return;
19147
+ if (existsSync28(join24(paths.PACKAGE_ROOT, "web", "dist", "index.html"))) return;
19148
+ if (!existsSync28(join24(paths.PACKAGE_ROOT, "web", "package.json"))) return;
19103
19149
  console.log(" web/dist missing \u2014 building the dashboard UI (pnpm --dir web build)...");
19104
19150
  const result = spawnSync("pnpm", ["--dir", "web", "build"], {
19105
19151
  cwd: paths.PACKAGE_ROOT,
@@ -19458,7 +19504,7 @@ async function main() {
19458
19504
  break;
19459
19505
  case "-v":
19460
19506
  case "--version":
19461
- printRaw("0.1.9");
19507
+ printRaw("0.1.10");
19462
19508
  break;
19463
19509
  case "-h":
19464
19510
  case "--help":
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startServer
4
- } from "./chunk-JG6LNX5D.js";
4
+ } from "./chunk-UYLVSUD6.js";
5
5
  import "./chunk-ZBMYF5LX.js";
6
6
  export {
7
7
  startServer
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flyspace-cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "AI-native headless community OS",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "private": false,