@fml-inc/fml 0.3.0 → 0.5.0

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.
@@ -1,8 +1,6 @@
1
1
  import {
2
- SYNC_PID_FILE,
3
- isDaemonRunning,
4
2
  panopticonExec
5
- } from "./chunk-MUKYS4IB.js";
3
+ } from "./chunk-YH5ROR7G.js";
6
4
 
7
5
  // src/commands/daemon.ts
8
6
  function parsePanopticonRunning() {
@@ -10,9 +8,6 @@ function parsePanopticonRunning() {
10
8
  const serverLine = result.stdout.split("\n").find((l) => l.startsWith("Server:"));
11
9
  return result.ok && /running/i.test(serverLine ?? "");
12
10
  }
13
- function isSyncRunning() {
14
- return isDaemonRunning(SYNC_PID_FILE);
15
- }
16
11
  async function handleStart() {
17
12
  const startResult = panopticonExec("start");
18
13
  console.log(
@@ -23,11 +18,24 @@ function handleStop() {
23
18
  const stopResult = panopticonExec("stop");
24
19
  console.log(stopResult.stdout.trim() || "Panopticon stopped");
25
20
  }
21
+ function handleSyncStart() {
22
+ const result = panopticonExec("sync", "enable");
23
+ console.log(
24
+ result.stdout.trim() || (result.ok ? "Sync enabled" : "Failed to enable sync")
25
+ );
26
+ }
27
+ function handleSyncStop() {
28
+ const result = panopticonExec("sync", "disable");
29
+ console.log(
30
+ result.stdout.trim() || (result.ok ? "Sync disabled" : "Failed to disable sync")
31
+ );
32
+ }
26
33
 
27
34
  export {
28
35
  parsePanopticonRunning,
29
- isSyncRunning,
30
36
  handleStart,
31
- handleStop
37
+ handleStop,
38
+ handleSyncStart,
39
+ handleSyncStop
32
40
  };
33
- //# sourceMappingURL=chunk-CFPXJT5Q.js.map
41
+ //# sourceMappingURL=chunk-ZFUJ5ZQP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/daemon.ts"],"sourcesContent":["import { panopticonExec } from \"../daemon-utils.js\";\n\n// ── Status helpers (used by doctor, status) ─────────────────────────────────\n\nexport function parsePanopticonRunning(): boolean {\n const result = panopticonExec(\"status\");\n const serverLine = result.stdout\n .split(\"\\n\")\n .find((l) => l.startsWith(\"Server:\"));\n return result.ok && /running/i.test(serverLine ?? \"\");\n}\n\n// ── Panopticon server start / stop (used by CLI, env restart, install, MCP) ──\n\nexport async function handleStart(): Promise<void> {\n const startResult = panopticonExec(\"start\");\n console.log(\n startResult.stdout.trim() ||\n (startResult.ok ? \"Panopticon started\" : \"Failed to start panopticon\"),\n );\n}\n\nexport function handleStop(): void {\n const stopResult = panopticonExec(\"stop\");\n console.log(stopResult.stdout.trim() || \"Panopticon stopped\");\n}\n\n// ── Sync start / stop (used by `fml sync start|stop`) ───────────────────────\n// Sync runs inside the panopticon server; these toggle the persisted\n// sync-enabled flag via panopticon, independent of the server lifecycle.\n\nexport function handleSyncStart(): void {\n const result = panopticonExec(\"sync\", \"enable\");\n console.log(\n result.stdout.trim() ||\n (result.ok ? \"Sync enabled\" : \"Failed to enable sync\"),\n );\n}\n\nexport function handleSyncStop(): void {\n const result = panopticonExec(\"sync\", \"disable\");\n console.log(\n result.stdout.trim() ||\n (result.ok ? \"Sync disabled\" : \"Failed to disable sync\"),\n );\n}\n"],"mappings":";;;;;AAIO,SAAS,yBAAkC;AAChD,QAAM,SAAS,eAAe,QAAQ;AACtC,QAAM,aAAa,OAAO,OACvB,MAAM,IAAI,EACV,KAAK,CAAC,MAAM,EAAE,WAAW,SAAS,CAAC;AACtC,SAAO,OAAO,MAAM,WAAW,KAAK,cAAc,EAAE;AACtD;AAIA,eAAsB,cAA6B;AACjD,QAAM,cAAc,eAAe,OAAO;AAC1C,UAAQ;AAAA,IACN,YAAY,OAAO,KAAK,MACrB,YAAY,KAAK,uBAAuB;AAAA,EAC7C;AACF;AAEO,SAAS,aAAmB;AACjC,QAAM,aAAa,eAAe,MAAM;AACxC,UAAQ,IAAI,WAAW,OAAO,KAAK,KAAK,oBAAoB;AAC9D;AAMO,SAAS,kBAAwB;AACtC,QAAM,SAAS,eAAe,QAAQ,QAAQ;AAC9C,UAAQ;AAAA,IACN,OAAO,OAAO,KAAK,MAChB,OAAO,KAAK,iBAAiB;AAAA,EAClC;AACF;AAEO,SAAS,iBAAuB;AACrC,QAAM,SAAS,eAAe,QAAQ,SAAS;AAC/C,UAAQ;AAAA,IACN,OAAO,OAAO,KAAK,MAChB,OAAO,KAAK,kBAAkB;AAAA,EACnC;AACF;","names":[]}
package/dist/cli.js CHANGED
@@ -1,17 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- createApiClient,
4
- ensureNativeModules,
3
+ createFmlClient,
5
4
  getAuthenticatedClient
6
- } from "./chunk-BOREGHA6.js";
5
+ } from "./chunk-OI562MUP.js";
7
6
  import {
8
7
  CONVEX_URL,
9
8
  DEFAULT_SYNC_URL,
10
9
  DEFAULT_TARGET_NAME,
10
+ FML_DATA_DIR,
11
+ FML_LOG_DIR,
11
12
  Sentry,
12
13
  WORKOS_API_URL,
13
14
  WORKOS_AUTH_URL,
14
15
  authStorePath,
16
+ envConfigExists,
15
17
  getActiveEnv,
16
18
  getSelectedOrg,
17
19
  getSiteUrl,
@@ -22,21 +24,19 @@ import {
22
24
  setSelectedOrg,
23
25
  writeEnvConfig,
24
26
  writeTokens
25
- } from "./chunk-CUBBYHH7.js";
27
+ } from "./chunk-5BHBYQ2F.js";
26
28
  import {
27
29
  handleStart,
28
30
  handleStop,
31
+ handleSyncStart,
32
+ handleSyncStop,
29
33
  parsePanopticonRunning
30
- } from "./chunk-CFPXJT5Q.js";
34
+ } from "./chunk-ZFUJ5ZQP.js";
31
35
  import {
32
36
  execBinSync,
33
37
  panopticonExec,
34
38
  resolveBin
35
- } from "./chunk-MUKYS4IB.js";
36
- import {
37
- FML_DATA_DIR,
38
- FML_LOG_DIR
39
- } from "./chunk-4YEAQJPF.js";
39
+ } from "./chunk-YH5ROR7G.js";
40
40
  import "./chunk-PZ5AY32C.js";
41
41
 
42
42
  // src/cli.ts
@@ -220,7 +220,7 @@ async function handleDoctor(opts) {
220
220
  const spinner = startSpinner("API");
221
221
  if (token) {
222
222
  try {
223
- const result = await createApiClient(token).callBackend("ping", {});
223
+ const result = await createFmlClient(token).callBackend("ping", {});
224
224
  if (result.ok) {
225
225
  pushAndReport(
226
226
  {
@@ -366,15 +366,17 @@ function writeJsonFile(filePath, data) {
366
366
  fs.writeFileSync(filePath, `${JSON.stringify(data, null, 2)}
367
367
  `);
368
368
  }
369
- async function handleInstall() {
369
+ async function handleInstall(opts = {}) {
370
+ const force = opts.force ?? false;
370
371
  const pluginRoot = getPluginRoot();
371
- console.log("Installing fml...\n");
372
+ console.log(`Installing fml${force ? " (--force)" : ""}...
373
+ `);
372
374
  console.log("[1/5] Setting up panopticon...");
373
- const { resolvePanopticonBin } = await import("./daemon-utils-CJO4XVJQ.js");
375
+ const { resolvePanopticonBin } = await import("./daemon-utils-OODBIYB7.js");
374
376
  let freshInstall = false;
375
377
  const bin = resolvePanopticonBin();
376
- let needsInstall = !bin;
377
- if (bin) {
378
+ let needsInstall = !bin || force;
379
+ if (bin && !force) {
378
380
  const MIN_PANOPTICON = "0.2.2";
379
381
  const vResult = panopticonExec("--version", { timeout: 5e3 });
380
382
  const installed = vResult.ok ? vResult.stdout.trim().split("+")[0] : "0.0.0";
@@ -529,7 +531,9 @@ async function handleInstall() {
529
531
  );
530
532
  }
531
533
  }
532
- writeEnvConfig({ active: DEFAULT_TARGET_NAME });
534
+ if (!envConfigExists()) {
535
+ writeEnvConfig({ active: DEFAULT_TARGET_NAME });
536
+ }
533
537
  console.log("");
534
538
  printBanner();
535
539
  console.log("Done! Start a new coding session to activate.\n");
@@ -701,7 +705,7 @@ function handleUninstall(opts) {
701
705
  // src/commands/update.ts
702
706
  import { execSync as execSync2 } from "child_process";
703
707
  async function handleUpdate() {
704
- const currentVersion = true ? "0.3.0+3bdd3b3" : "unknown";
708
+ const currentVersion = true ? "0.5.0+738a81c" : "unknown";
705
709
  console.log(`Current: ${currentVersion}`);
706
710
  console.log("Updating via npm...\n");
707
711
  try {
@@ -712,7 +716,7 @@ async function handleUpdate() {
712
716
  timeout: 12e4,
713
717
  env
714
718
  });
715
- console.log("\nUpdated. Run `fml install --skip-build` to reconfigure.");
719
+ console.log("\nUpdated. Run `fml install --force` to reconfigure.");
716
720
  } catch (err) {
717
721
  Sentry.captureException(err);
718
722
  const msg = err instanceof Error ? err.stderr?.toString() ?? err.message : String(err);
@@ -732,11 +736,12 @@ import {
732
736
  import crypto from "crypto";
733
737
  import http from "http";
734
738
  async function fetchWorkosClientId() {
735
- const { ConvexHttpClient } = await import("convex/browser");
736
- const client = new ConvexHttpClient(CONVEX_URL);
737
- const ref = "public_config:getAuthConfig";
738
- const result = await client.query(ref, {});
739
- return result.workosClientId;
739
+ const response = await fetch(`${getSiteUrl()}/api/auth/config`);
740
+ const data = await response.json();
741
+ if (!response.ok || data.ok === false || !data.workosClientId) {
742
+ throw new Error(data.error ?? `HTTP ${response.status}`);
743
+ }
744
+ return data.workosClientId;
740
745
  }
741
746
  async function canOpenBrowser() {
742
747
  if (process.env.FML_DEVICE_FLOW === "1") return false;
@@ -993,15 +998,22 @@ async function linkGitHubIdentity() {
993
998
  if (fmlToken.startsWith("fml_st_")) {
994
999
  return;
995
1000
  }
996
- const { ConvexHttpClient } = await import("convex/browser");
997
- const client = new ConvexHttpClient(CONVEX_URL);
998
- client.setAuth(fmlToken);
999
- const ref = "user/panopticon:linkGitHubIdentity";
1000
- await client.mutation(ref, {
1001
- githubUsername: user.login,
1002
- githubId: user.id,
1003
- githubEmail: user.email ?? void 0
1001
+ const linkResponse = await fetch(`${getSiteUrl()}/api/auth/link-github-identity`, {
1002
+ method: "POST",
1003
+ headers: {
1004
+ "Content-Type": "application/json",
1005
+ Authorization: `Bearer ${fmlToken}`
1006
+ },
1007
+ body: JSON.stringify({
1008
+ githubUsername: user.login,
1009
+ githubId: user.id,
1010
+ githubEmail: user.email ?? void 0
1011
+ })
1004
1012
  });
1013
+ const linkResult = await linkResponse.json();
1014
+ if (!linkResponse.ok || linkResult.ok === false) {
1015
+ throw new Error(linkResult.error ?? `HTTP ${linkResponse.status}`);
1016
+ }
1005
1017
  console.log(`Linked GitHub account: ${user.login}`);
1006
1018
  } catch (err) {
1007
1019
  const msg = err instanceof Error ? err.message : String(err);
@@ -1048,10 +1060,11 @@ async function selectOrg() {
1048
1060
  try {
1049
1061
  const token = await getValidToken();
1050
1062
  if (!token) return;
1051
- const api = createApiClient(token);
1063
+ const api = createFmlClient(token);
1052
1064
  const orgs = await api.queryOrgs();
1053
1065
  if (orgs.length === 0) return;
1054
- const org = orgs[0];
1066
+ const current = getSelectedOrg();
1067
+ const org = current && orgs.find((o) => (o.slug ?? o.name) === current) || orgs[0];
1055
1068
  const slug = org.slug ?? org.name;
1056
1069
  setSelectedOrg(slug);
1057
1070
  console.log(`Selected org: ${org.name} (${slug})`);
@@ -1062,7 +1075,7 @@ async function handleLogin(opts) {
1062
1075
  const { name: envName } = getActiveEnv();
1063
1076
  const existingToken = await getValidToken();
1064
1077
  if (existingToken) {
1065
- const { readTokens: readTokens2 } = await import("./token-store-HOFFHNNN.js");
1078
+ const { readTokens: readTokens2 } = await import("./token-store-T2RNLXRM.js");
1066
1079
  const stored = readTokens2();
1067
1080
  console.log(
1068
1081
  `Already logged in as ${stored?.user.name} (${stored?.user.email}) on ${envName}.`
@@ -1114,7 +1127,7 @@ async function handleOrg(slug) {
1114
1127
  console.error("Not logged in. Run `fml login` first.");
1115
1128
  process.exit(1);
1116
1129
  }
1117
- const api = createApiClient(token);
1130
+ const api = createFmlClient(token);
1118
1131
  const orgs = await api.queryOrgs();
1119
1132
  if (orgs.length === 0) {
1120
1133
  console.error("No organizations found.");
@@ -1946,7 +1959,7 @@ async function handleConfigDetail(opts) {
1946
1959
  // src/commands/tools.ts
1947
1960
  import { readFileSync } from "fs";
1948
1961
  import path3 from "path";
1949
- var pluginVersion = true ? "0.3.0+3bdd3b3" : void 0;
1962
+ var pluginVersion = true ? "0.5.0+738a81c" : void 0;
1950
1963
  async function getApi() {
1951
1964
  const api = await getAuthenticatedClient();
1952
1965
  if (!api) {
@@ -2072,13 +2085,12 @@ async function handleToolsCall(name, opts) {
2072
2085
  }
2073
2086
 
2074
2087
  // src/cli.ts
2075
- ensureNativeModules();
2076
2088
  await initSentry();
2077
2089
  if (process.argv.length <= 2 || process.argv.includes("--help") || process.argv.includes("-h")) {
2078
2090
  printBanner();
2079
2091
  }
2080
2092
  var program = new Command().name("fml").description("FML agent tools for Claude Code").version(
2081
- true ? "0.3.0+3bdd3b3" : "dev"
2093
+ true ? "0.5.0+738a81c" : "dev"
2082
2094
  );
2083
2095
  var tools = program.command("tools", { hidden: true }).description("List all available CLI commands (including hidden agent tools)").action(() => {
2084
2096
  function formatCmd(cmd, prefix = "") {
@@ -2102,7 +2114,10 @@ var tools = program.command("tools", { hidden: true }).description("List all ava
2102
2114
  tools.command("list").description("List backend tools available via the dynamic catalog").option("--category <category>", "Filter by category").option("--json", "Output as JSON").action((opts) => handleToolsList(opts));
2103
2115
  tools.command("describe").description("Show description and input schema for a backend tool").argument("<name>", "Tool name (e.g. integration-github)").option("--json", "Output as JSON").action((name, opts) => handleToolsDescribe(name, opts));
2104
2116
  tools.command("call").description("Invoke a backend tool by name with JSON args").argument("<name>", "Tool name").option("--args <json>", "Args as a JSON string (defaults to {})").option("--file <path>", "Path to a JSON file containing args").action((name, opts) => handleToolsCall(name, opts));
2105
- program.command("install").description("Register plugin, hooks, and daemons").action(() => handleInstall());
2117
+ program.command("install").description("Register plugin, hooks, and daemons").option(
2118
+ "--force",
2119
+ "Reinstall even if already set up (upgrades panopticon, re-registers plugin)"
2120
+ ).action((opts) => handleInstall(opts));
2106
2121
  program.command("uninstall").description("Remove fml plugin, hooks, and optionally all data").option(
2107
2122
  "--target <target>",
2108
2123
  "Target CLI: claude, gemini, codex, claude-desktop, all"
@@ -2118,9 +2133,12 @@ program.command("env").description("Show or switch environment (dev/prod)").argu
2118
2133
  if (target) handleEnvSwitch(target);
2119
2134
  else handleEnvShow();
2120
2135
  });
2121
- program.command("start").description("Start panopticon server and sync").action(() => handleStart());
2122
- program.command("stop").description("Stop panopticon server and sync").action(() => handleStop());
2136
+ var panopticon = program.command("panopticon").description("Start or stop the panopticon server");
2137
+ panopticon.command("start").description("Start the panopticon server").action(() => handleStart());
2138
+ panopticon.command("stop").description("Stop the panopticon server").action(() => handleStop());
2123
2139
  var sync = program.command("sync").description("Manage sync configuration");
2140
+ sync.command("start").description("Start syncing to configured targets (enable sync)").action(() => handleSyncStart());
2141
+ sync.command("stop").description("Stop syncing (disable sync; leaves targets configured)").action(() => handleSyncStop());
2124
2142
  sync.command("setup").description("Configure sync targets (convenience shortcut)").action(() => handleSyncSetup());
2125
2143
  sync.command("list").description("List all sync targets").action(() => handleSyncList());
2126
2144
  sync.command("add").description("Add a sync target").argument("<name>", "Unique target name").argument("<url>", "OTLP HTTP endpoint URL").option("--token-cmd <cmd>", "Shell command that returns a bearer token").option("--token <token>", "Static bearer token").action(