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.
- package/dist/{chunk-JG6LNX5D.js → chunk-UYLVSUD6.js} +4 -0
- package/dist/cli.js +144 -98
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -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-
|
|
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
|
|
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 ?
|
|
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
|
-
|
|
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(
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
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:
|
|
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.
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
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.
|
|
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
|
|
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 =
|
|
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
|
|
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() ||
|
|
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
|
|
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
|
|
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
|
|
4867
|
+
import { join as join12 } from "path";
|
|
4844
4868
|
import sharp from "sharp";
|
|
4845
4869
|
var PLATE = "#0A0A0F";
|
|
4846
|
-
var MARK_FILE =
|
|
4847
|
-
var MARK_SVG_FILE =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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
|
|
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(
|
|
8260
|
-
const path =
|
|
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
|
|
8317
|
+
import { basename as basename5, join as join16 } from "path";
|
|
8284
8318
|
import yaml from "js-yaml";
|
|
8285
8319
|
function defaultConfigDir() {
|
|
8286
|
-
return
|
|
8320
|
+
return join16(homedir6(), ".claude");
|
|
8287
8321
|
}
|
|
8288
8322
|
function expandHome(p) {
|
|
8289
8323
|
if (p === "~") return homedir6();
|
|
8290
|
-
if (p.startsWith("~/")) return
|
|
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 =
|
|
8354
|
+
const path = join16(root, file);
|
|
8321
8355
|
const fm = parseFrontmatter(path);
|
|
8322
|
-
const name = fm.name?.trim() ||
|
|
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(
|
|
8330
|
-
...collectFrom(
|
|
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
|
|
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 =
|
|
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
|
-
|
|
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
|
|
10420
|
+
if (kind === "url" || kind === "excalidraw") return basename6(absPath);
|
|
10381
10421
|
const head = readHead(absPath);
|
|
10382
|
-
if (!head) return
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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 (
|
|
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 =
|
|
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) :
|
|
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
|
|
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:
|
|
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] ?
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
15498
|
+
import { dirname as dirname7, join as join21 } from "path";
|
|
15453
15499
|
function hostPrivateKeyPath() {
|
|
15454
|
-
return process.env["FLYSPACE_HOST_KEY_PATH"] ||
|
|
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
|
|
15525
|
+
import { join as join22 } from "path";
|
|
15480
15526
|
function hostLockPath() {
|
|
15481
|
-
return
|
|
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 =
|
|
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(
|
|
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:
|
|
17626
|
+
const spaFallback = serveStatic({ path: join23(WEB_DIST, "index.html") });
|
|
17581
17627
|
app.get("*", async (c, next) => {
|
|
17582
|
-
if (!existsSync26(
|
|
17583
|
-
const isCheckout = existsSync26(
|
|
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
|
|
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:
|
|
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
|
|
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(
|
|
19102
|
-
if (!existsSync28(
|
|
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.
|
|
19507
|
+
printRaw("0.1.10");
|
|
19462
19508
|
break;
|
|
19463
19509
|
case "-h":
|
|
19464
19510
|
case "--help":
|
package/dist/index.js
CHANGED