@floless/app 0.12.1 → 0.12.3
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/floless-server.cjs +45 -25
- package/dist/web/aware.js +31 -1
- package/package.json +1 -1
package/dist/floless-server.cjs
CHANGED
|
@@ -43012,7 +43012,7 @@ var require_static = __commonJS({
|
|
|
43012
43012
|
"use strict";
|
|
43013
43013
|
var path = require("node:path");
|
|
43014
43014
|
var { fileURLToPath: fileURLToPath4 } = require("node:url");
|
|
43015
|
-
var { statSync:
|
|
43015
|
+
var { statSync: statSync8 } = require("node:fs");
|
|
43016
43016
|
var { glob } = require_commonjs6();
|
|
43017
43017
|
var fp = require_plugin2();
|
|
43018
43018
|
var send = require_send2();
|
|
@@ -43375,7 +43375,7 @@ var require_static = __commonJS({
|
|
|
43375
43375
|
}
|
|
43376
43376
|
let pathStat;
|
|
43377
43377
|
try {
|
|
43378
|
-
pathStat =
|
|
43378
|
+
pathStat = statSync8(rootPath);
|
|
43379
43379
|
} catch (e) {
|
|
43380
43380
|
if (e.code === "ENOENT") {
|
|
43381
43381
|
fastify.log.warn(`"root" path "${rootPath}" must exist`);
|
|
@@ -43399,7 +43399,7 @@ var require_static = __commonJS({
|
|
|
43399
43399
|
return indexFiles.find((filename) => {
|
|
43400
43400
|
const p = path.join(root, pathname, filename);
|
|
43401
43401
|
try {
|
|
43402
|
-
const stats =
|
|
43402
|
+
const stats = statSync8(p);
|
|
43403
43403
|
return !stats.isDirectory();
|
|
43404
43404
|
} catch {
|
|
43405
43405
|
return false;
|
|
@@ -50828,7 +50828,7 @@ var import_node_readline2 = require("node:readline");
|
|
|
50828
50828
|
// index.ts
|
|
50829
50829
|
var import_node_url3 = require("node:url");
|
|
50830
50830
|
var import_node_path20 = require("node:path");
|
|
50831
|
-
var
|
|
50831
|
+
var import_node_os14 = require("node:os");
|
|
50832
50832
|
var import_node_fs21 = require("node:fs");
|
|
50833
50833
|
var import_node_child_process6 = require("node:child_process");
|
|
50834
50834
|
|
|
@@ -52609,7 +52609,7 @@ function appVersion() {
|
|
|
52609
52609
|
return resolveVersion({
|
|
52610
52610
|
isSea: isSea2(),
|
|
52611
52611
|
sqVersionXml: readSqVersionXml(),
|
|
52612
|
-
define: true ? "0.12.
|
|
52612
|
+
define: true ? "0.12.3" : void 0,
|
|
52613
52613
|
pkgVersion: readPkgVersion()
|
|
52614
52614
|
});
|
|
52615
52615
|
}
|
|
@@ -52619,7 +52619,7 @@ function resolveChannel(s) {
|
|
|
52619
52619
|
return "dev";
|
|
52620
52620
|
}
|
|
52621
52621
|
function appChannel() {
|
|
52622
|
-
return resolveChannel({ isSea: isSea2(), define: true ? "0.12.
|
|
52622
|
+
return resolveChannel({ isSea: isSea2(), define: true ? "0.12.3" : void 0 });
|
|
52623
52623
|
}
|
|
52624
52624
|
|
|
52625
52625
|
// oauth-presets.ts
|
|
@@ -54039,29 +54039,48 @@ var import_node_path15 = require("node:path");
|
|
|
54039
54039
|
|
|
54040
54040
|
// post-update-marker.mjs
|
|
54041
54041
|
var import_node_fs16 = require("node:fs");
|
|
54042
|
+
var import_node_os11 = require("node:os");
|
|
54042
54043
|
var import_node_path14 = require("node:path");
|
|
54044
|
+
var FRESH_MS = 12e4;
|
|
54043
54045
|
function markerPath() {
|
|
54044
54046
|
const override = (process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim();
|
|
54045
54047
|
if (override) return override;
|
|
54046
|
-
|
|
54048
|
+
const root = process.env.FLOLESS_HOME ?? (0, import_node_path14.join)((0, import_node_os11.homedir)(), ".floless");
|
|
54049
|
+
return (0, import_node_path14.join)(root, ".post-update");
|
|
54047
54050
|
}
|
|
54048
|
-
function
|
|
54051
|
+
function legacyMarkerPath() {
|
|
54052
|
+
if ((process.env.FLOLESS_POST_UPDATE_MARKER ?? "").trim()) return null;
|
|
54049
54053
|
try {
|
|
54050
|
-
(0,
|
|
54051
|
-
return true;
|
|
54054
|
+
return (0, import_node_path14.join)((0, import_node_path14.dirname)((0, import_node_path14.dirname)(process.execPath)), ".floless-post-update");
|
|
54052
54055
|
} catch {
|
|
54053
|
-
return
|
|
54056
|
+
return null;
|
|
54057
|
+
}
|
|
54058
|
+
}
|
|
54059
|
+
function writePostUpdateMarker() {
|
|
54060
|
+
let wrote = false;
|
|
54061
|
+
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
54062
|
+
if (!p) continue;
|
|
54063
|
+
try {
|
|
54064
|
+
(0, import_node_fs16.writeFileSync)(p, (/* @__PURE__ */ new Date()).toISOString());
|
|
54065
|
+
wrote = true;
|
|
54066
|
+
} catch {
|
|
54067
|
+
}
|
|
54054
54068
|
}
|
|
54069
|
+
return wrote;
|
|
54055
54070
|
}
|
|
54056
54071
|
function consumePostUpdateMarker() {
|
|
54057
|
-
|
|
54058
|
-
|
|
54059
|
-
if (!
|
|
54060
|
-
|
|
54061
|
-
|
|
54062
|
-
|
|
54063
|
-
|
|
54072
|
+
let fresh = false;
|
|
54073
|
+
for (const p of [markerPath(), legacyMarkerPath()]) {
|
|
54074
|
+
if (!p) continue;
|
|
54075
|
+
try {
|
|
54076
|
+
if (!(0, import_node_fs16.existsSync)(p)) continue;
|
|
54077
|
+
const ageMs = Date.now() - (0, import_node_fs16.statSync)(p).mtimeMs;
|
|
54078
|
+
(0, import_node_fs16.rmSync)(p, { force: true });
|
|
54079
|
+
if (ageMs < FRESH_MS) fresh = true;
|
|
54080
|
+
} catch {
|
|
54081
|
+
}
|
|
54064
54082
|
}
|
|
54083
|
+
return fresh;
|
|
54065
54084
|
}
|
|
54066
54085
|
|
|
54067
54086
|
// updater.ts
|
|
@@ -54877,7 +54896,7 @@ function awareUpgradeBlockReason(s) {
|
|
|
54877
54896
|
|
|
54878
54897
|
// skill-sync.ts
|
|
54879
54898
|
var import_node_fs19 = require("node:fs");
|
|
54880
|
-
var
|
|
54899
|
+
var import_node_os12 = require("node:os");
|
|
54881
54900
|
var import_node_path17 = require("node:path");
|
|
54882
54901
|
var import_node_url2 = require("node:url");
|
|
54883
54902
|
var import_yaml5 = __toESM(require_dist6(), 1);
|
|
@@ -54917,7 +54936,7 @@ function targetConfigDirs() {
|
|
|
54917
54936
|
if (override) {
|
|
54918
54937
|
return override.split(";").map((d) => d.trim()).filter(Boolean).map((dir) => ({ runtime: "custom", dir }));
|
|
54919
54938
|
}
|
|
54920
|
-
const home = (0,
|
|
54939
|
+
const home = (0, import_node_os12.homedir)();
|
|
54921
54940
|
return [
|
|
54922
54941
|
{ runtime: "claude", dir: (0, import_node_path17.join)(home, ".claude") },
|
|
54923
54942
|
{ runtime: "codex", dir: (0, import_node_path17.join)(home, ".codex") },
|
|
@@ -55016,7 +55035,7 @@ function syncSkills() {
|
|
|
55016
55035
|
}
|
|
55017
55036
|
|
|
55018
55037
|
// watch.ts
|
|
55019
|
-
var
|
|
55038
|
+
var import_node_os13 = require("node:os");
|
|
55020
55039
|
var import_node_path19 = require("node:path");
|
|
55021
55040
|
var import_node_fs20 = require("node:fs");
|
|
55022
55041
|
|
|
@@ -56729,7 +56748,7 @@ function underDir(path, dir) {
|
|
|
56729
56748
|
return p === d || p.startsWith(d + import_node_path19.sep);
|
|
56730
56749
|
}
|
|
56731
56750
|
function startWatcher() {
|
|
56732
|
-
const awareDir = process.env.AWARE_HOME ?? (0, import_node_path19.join)((0,
|
|
56751
|
+
const awareDir = process.env.AWARE_HOME ?? (0, import_node_path19.join)((0, import_node_os13.homedir)(), ".aware");
|
|
56733
56752
|
const credentialsDir = (0, import_node_path19.join)(awareDir, "credentials");
|
|
56734
56753
|
if (!(0, import_node_fs20.existsSync)(credentialsDir)) {
|
|
56735
56754
|
try {
|
|
@@ -57162,7 +57181,7 @@ async function startServer() {
|
|
|
57162
57181
|
}
|
|
57163
57182
|
const inputs = appData.inputs.map((i) => ({ name: i.name, type: i.type }));
|
|
57164
57183
|
const baked = bakeFloSource(appData.source.text, inputs);
|
|
57165
|
-
const tmpRoot = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0,
|
|
57184
|
+
const tmpRoot = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0, import_node_os14.tmpdir)(), "floless-bake-"));
|
|
57166
57185
|
const backupDir = (0, import_node_path20.join)(tmpRoot, `${id}-backup`);
|
|
57167
57186
|
const bakeDir = (0, import_node_path20.join)(tmpRoot, id);
|
|
57168
57187
|
(0, import_node_fs21.cpSync)(appDir(id), backupDir, { recursive: true });
|
|
@@ -57200,7 +57219,7 @@ async function startServer() {
|
|
|
57200
57219
|
if (appInstalled) (0, import_node_fs21.rmSync)(tmpRoot, { recursive: true, force: true });
|
|
57201
57220
|
}
|
|
57202
57221
|
});
|
|
57203
|
-
const graftAgentsDir = () => (0, import_node_path20.join)((0,
|
|
57222
|
+
const graftAgentsDir = () => (0, import_node_path20.join)((0, import_node_os14.homedir)(), ".aware", "agents");
|
|
57204
57223
|
app.post("/api/graft/match", async (req, reply) => {
|
|
57205
57224
|
const { glob } = req.body ?? {};
|
|
57206
57225
|
if (!glob) return reply.status(400).send({ ok: false, error: "glob required" });
|
|
@@ -57217,7 +57236,7 @@ async function startServer() {
|
|
|
57217
57236
|
if (!sourceKind || !sourceRef) {
|
|
57218
57237
|
return reply.status(400).send({ ok: false, error: "sourceKind and sourceRef required" });
|
|
57219
57238
|
}
|
|
57220
|
-
const tempHome = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0,
|
|
57239
|
+
const tempHome = (0, import_node_fs21.mkdtempSync)((0, import_node_path20.join)((0, import_node_os14.tmpdir)(), "floless-graft-"));
|
|
57221
57240
|
let result;
|
|
57222
57241
|
try {
|
|
57223
57242
|
result = await aware.build({
|
|
@@ -57745,6 +57764,7 @@ async function main() {
|
|
|
57745
57764
|
const realExe = resolveRealInstallExe(process.execPath);
|
|
57746
57765
|
registerProtocol(realExe);
|
|
57747
57766
|
registerAutostart(realExe);
|
|
57767
|
+
if (veloHook === "--veloapp-updated") writePostUpdateMarker();
|
|
57748
57768
|
} else if (veloHook === "--veloapp-uninstall") {
|
|
57749
57769
|
unregisterProtocol();
|
|
57750
57770
|
unregisterAutostart();
|
package/dist/web/aware.js
CHANGED
|
@@ -791,11 +791,22 @@
|
|
|
791
791
|
const saveItem = document.querySelector('.menu-item[data-action="save"]');
|
|
792
792
|
if (saveItem) saveItem.classList.toggle('menu-item-dirty', dirty);
|
|
793
793
|
}
|
|
794
|
+
// Set while WE programmatically reload to adopt a self-update (#37) — an in-place build
|
|
795
|
+
// adoption is not the user navigating away, so it must NOT trigger the unsaved-changes
|
|
796
|
+
// prompt below (that would strand the tab behind a modal). The reload path persists the
|
|
797
|
+
// inputs first, so nothing is lost.
|
|
798
|
+
let selfUpdating = false;
|
|
794
799
|
// Refresh/close guard: unsaved input values live only in memory, so warn before
|
|
795
800
|
// the page unloads while dirty (the browser shows its own generic confirm).
|
|
796
801
|
window.addEventListener('beforeunload', (e) => {
|
|
797
|
-
if (isInputsDirty(currentId)) { e.preventDefault(); e.returnValue = ''; }
|
|
802
|
+
if (!selfUpdating && isInputsDirty(currentId)) { e.preventDefault(); e.returnValue = ''; }
|
|
798
803
|
});
|
|
804
|
+
// Persist the active app's inputs to localStorage (the new build restores them on load).
|
|
805
|
+
// Used before a self-update reload so an in-place adoption never drops unsaved edits.
|
|
806
|
+
function persistCurrentInputs() {
|
|
807
|
+
if (!currentId) return;
|
|
808
|
+
try { localStorage.setItem(lsInputsKey(currentId), JSON.stringify(appInputValues.get(currentId) || {})); } catch { /* private mode / quota */ }
|
|
809
|
+
}
|
|
799
810
|
|
|
800
811
|
function seedAppInputs(app) {
|
|
801
812
|
if (app && Array.isArray(app.inputs) && app.inputs.length) {
|
|
@@ -2613,6 +2624,7 @@
|
|
|
2613
2624
|
}
|
|
2614
2625
|
}
|
|
2615
2626
|
let shownVersion = false;
|
|
2627
|
+
let loadedAppVersion = null; // the build this tab is running against (first health wins)
|
|
2616
2628
|
function startHealthPoll() {
|
|
2617
2629
|
const tick = async () => {
|
|
2618
2630
|
let ok = false;
|
|
@@ -2634,6 +2646,24 @@
|
|
|
2634
2646
|
if (h && h.webBase) webBase = h.webBase;
|
|
2635
2647
|
const av = document.getElementById('app-version');
|
|
2636
2648
|
if (av && h && h.appVersion && !shownVersion) { av.textContent = 'FloLess ' + h.appVersion; shownVersion = true; }
|
|
2649
|
+
// Adopt a self-update IN PLACE (#37): this tab loaded build X, but the server now
|
|
2650
|
+
// reports build Y — a self-update swapped the build under us. Reload so the tab runs
|
|
2651
|
+
// the NEW build's web assets (and a fresh footer + what's-new) instead of being
|
|
2652
|
+
// stranded on the old build's UI — stuck "Updating…", a frozen version, version skew.
|
|
2653
|
+
// This is what makes the post-update tab genuinely "reusable": the existing tab
|
|
2654
|
+
// becomes the new-version tab. Only fires on a real version change (first health sets
|
|
2655
|
+
// the baseline), so normal restarts / same-version polls never reload.
|
|
2656
|
+
if (h && h.appVersion) {
|
|
2657
|
+
if (loadedAppVersion === null) loadedAppVersion = h.appVersion;
|
|
2658
|
+
else if (h.appVersion !== loadedAppVersion) {
|
|
2659
|
+
// Persist unsaved inputs and suppress the beforeunload prompt (this is an
|
|
2660
|
+
// in-place build adoption, not the user leaving) before reloading.
|
|
2661
|
+
selfUpdating = true;
|
|
2662
|
+
persistCurrentInputs();
|
|
2663
|
+
location.reload();
|
|
2664
|
+
return;
|
|
2665
|
+
}
|
|
2666
|
+
}
|
|
2637
2667
|
// After the build version is stamped, reveal the relaunch-surviving what's-new
|
|
2638
2668
|
// panel iff this is the build we just self-updated into (guarded to once).
|
|
2639
2669
|
maybeShowWhatsNew();
|