@lotics/cli 0.66.0 → 0.67.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.
- package/dist/app_commands.js +48 -19
- package/dist/src/cli.js +42 -19
- package/package.json +2 -2
package/dist/app_commands.js
CHANGED
|
@@ -911,7 +911,16 @@ args) {
|
|
|
911
911
|
});
|
|
912
912
|
console.error(`Deployed v${result.version_number} (${result.version_id})`);
|
|
913
913
|
console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
914
|
-
|
|
914
|
+
// One post-deploy getApp feeds both advisory nudges (branding, unbound
|
|
915
|
+
// aliases). Deploy already succeeded — a failed check must not mask that.
|
|
916
|
+
try {
|
|
917
|
+
const app = await client.getApp(meta.app_id);
|
|
918
|
+
warnIfUnbranded(app);
|
|
919
|
+
warnIfUnboundAliases(app, meta.workflows ?? {}, meta.agents ?? {});
|
|
920
|
+
}
|
|
921
|
+
catch (err) {
|
|
922
|
+
console.error(`(skipped post-deploy checks: ${err.message})`);
|
|
923
|
+
}
|
|
915
924
|
}
|
|
916
925
|
catch (err) {
|
|
917
926
|
const e = err;
|
|
@@ -935,24 +944,44 @@ args) {
|
|
|
935
944
|
* generic tile in the launcher. Branding is set via `update_app` (the single
|
|
936
945
|
* setter) — this only reminds; it never fails the deploy.
|
|
937
946
|
*/
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
947
|
+
function warnIfUnbranded(app) {
|
|
948
|
+
const missing = [];
|
|
949
|
+
if (!app.icon)
|
|
950
|
+
missing.push("icon");
|
|
951
|
+
if (!app.theme?.color)
|
|
952
|
+
missing.push("color");
|
|
953
|
+
if (missing.length === 0)
|
|
954
|
+
return;
|
|
955
|
+
console.error(`\n⚠ This app has no ${missing.join(" or ")} set — it shows a generic tile in the launcher.\n` +
|
|
956
|
+
` Set it: lotics run update_app '{"app_id":"${app.id}","icon":"<lucide-name>","theme":{"color":"blue"}}'\n` +
|
|
957
|
+
` Find an icon: lotics run search_app_icons '{"query":"<word>"}'`);
|
|
958
|
+
}
|
|
959
|
+
/**
|
|
960
|
+
* Non-blocking nudge after a successful deploy: catch manifest workflow/agent aliases
|
|
961
|
+
* that are NOT bound on the server. Deploy ships code + queries only — it never binds
|
|
962
|
+
* workflows/agents (`set_app_workflow` / `set_app_agent` own `apps.workflows`/`apps.agents`;
|
|
963
|
+
* the manifest maps are a pulled reflection). So an alias hand-added to `lotics.workflows`
|
|
964
|
+
* / `lotics.agents` (or bound then removed) compiles + deploys clean and only throws when
|
|
965
|
+
* the app first calls `useWorkflow` / `useAgentRun`. Surface that divergence HERE — at
|
|
966
|
+
* deploy time — instead of at the user's first click. Advisory only; never fails the deploy.
|
|
967
|
+
*/
|
|
968
|
+
function warnIfUnboundAliases(app, declaredWorkflows, declaredAgents) {
|
|
969
|
+
const boundWorkflows = new Set(Object.keys(app.workflows ?? {}));
|
|
970
|
+
const boundAgents = new Set(Object.keys(app.agents ?? {}));
|
|
971
|
+
const unboundWorkflows = Object.keys(declaredWorkflows).filter((a) => !boundWorkflows.has(a));
|
|
972
|
+
const unboundAgents = Object.keys(declaredAgents).filter((a) => !boundAgents.has(a));
|
|
973
|
+
if (unboundWorkflows.length === 0 && unboundAgents.length === 0)
|
|
974
|
+
return;
|
|
975
|
+
const lines = [
|
|
976
|
+
"\n⚠ The manifest declares aliases that are NOT bound on the server. Deploy ships code +",
|
|
977
|
+
" queries only — it does NOT bind workflows/agents, so the app will throw \"has no … alias\"",
|
|
978
|
+
" the first time it calls them. Bind each one:",
|
|
979
|
+
];
|
|
980
|
+
for (const alias of unboundWorkflows)
|
|
981
|
+
lines.push(` • workflow "${alias}" → lotics app workflow set ${alias}`);
|
|
982
|
+
for (const alias of unboundAgents)
|
|
983
|
+
lines.push(` • agent "${alias}" → bind with set_app_agent (lotics run set_app_agent …)`);
|
|
984
|
+
console.error(lines.join("\n"));
|
|
956
985
|
}
|
|
957
986
|
/**
|
|
958
987
|
* `lotics app dev [path] [--port=5174] [--vite-port=5173]`
|
package/dist/src/cli.js
CHANGED
|
@@ -32758,7 +32758,13 @@ async function appDeploy(client, args) {
|
|
|
32758
32758
|
});
|
|
32759
32759
|
console.error(`Deployed v${result.version_number} (${result.version_id})`);
|
|
32760
32760
|
console.error(`Bundle size: ${(result.bundle_size_bytes / 1024).toFixed(1)} KB`);
|
|
32761
|
-
|
|
32761
|
+
try {
|
|
32762
|
+
const app = await client.getApp(meta.app_id);
|
|
32763
|
+
warnIfUnbranded(app);
|
|
32764
|
+
warnIfUnboundAliases(app, meta.workflows ?? {}, meta.agents ?? {});
|
|
32765
|
+
} catch (err2) {
|
|
32766
|
+
console.error(`(skipped post-deploy checks: ${err2.message})`);
|
|
32767
|
+
}
|
|
32762
32768
|
} catch (err2) {
|
|
32763
32769
|
const e = err2;
|
|
32764
32770
|
if (e.code === "VERSION_CONFLICT") {
|
|
@@ -32774,22 +32780,32 @@ async function appDeploy(client, args) {
|
|
|
32774
32780
|
if (fs4.existsSync(tmpDist)) fs4.unlinkSync(tmpDist);
|
|
32775
32781
|
}
|
|
32776
32782
|
}
|
|
32777
|
-
|
|
32778
|
-
|
|
32779
|
-
|
|
32780
|
-
|
|
32781
|
-
|
|
32782
|
-
|
|
32783
|
-
|
|
32784
|
-
console.error(
|
|
32785
|
-
`
|
|
32783
|
+
function warnIfUnbranded(app) {
|
|
32784
|
+
const missing = [];
|
|
32785
|
+
if (!app.icon) missing.push("icon");
|
|
32786
|
+
if (!app.theme?.color) missing.push("color");
|
|
32787
|
+
if (missing.length === 0) return;
|
|
32788
|
+
console.error(
|
|
32789
|
+
`
|
|
32786
32790
|
\u26A0 This app has no ${missing.join(" or ")} set \u2014 it shows a generic tile in the launcher.
|
|
32787
|
-
Set it: lotics run update_app '{"app_id":"${
|
|
32791
|
+
Set it: lotics run update_app '{"app_id":"${app.id}","icon":"<lucide-name>","theme":{"color":"blue"}}'
|
|
32788
32792
|
Find an icon: lotics run search_app_icons '{"query":"<word>"}'`
|
|
32789
|
-
|
|
32790
|
-
|
|
32791
|
-
|
|
32792
|
-
}
|
|
32793
|
+
);
|
|
32794
|
+
}
|
|
32795
|
+
function warnIfUnboundAliases(app, declaredWorkflows, declaredAgents) {
|
|
32796
|
+
const boundWorkflows = new Set(Object.keys(app.workflows ?? {}));
|
|
32797
|
+
const boundAgents = new Set(Object.keys(app.agents ?? {}));
|
|
32798
|
+
const unboundWorkflows = Object.keys(declaredWorkflows).filter((a) => !boundWorkflows.has(a));
|
|
32799
|
+
const unboundAgents = Object.keys(declaredAgents).filter((a) => !boundAgents.has(a));
|
|
32800
|
+
if (unboundWorkflows.length === 0 && unboundAgents.length === 0) return;
|
|
32801
|
+
const lines = [
|
|
32802
|
+
"\n\u26A0 The manifest declares aliases that are NOT bound on the server. Deploy ships code +",
|
|
32803
|
+
' queries only \u2014 it does NOT bind workflows/agents, so the app will throw "has no \u2026 alias"',
|
|
32804
|
+
" the first time it calls them. Bind each one:"
|
|
32805
|
+
];
|
|
32806
|
+
for (const alias of unboundWorkflows) lines.push(` \u2022 workflow "${alias}" \u2192 lotics app workflow set ${alias}`);
|
|
32807
|
+
for (const alias of unboundAgents) lines.push(` \u2022 agent "${alias}" \u2192 bind with set_app_agent (lotics run set_app_agent \u2026)`);
|
|
32808
|
+
console.error(lines.join("\n"));
|
|
32793
32809
|
}
|
|
32794
32810
|
async function appDev(client, args) {
|
|
32795
32811
|
const projectDir = path5.resolve(args.projectDir ?? process.cwd());
|
|
@@ -42716,6 +42732,7 @@ function readCfbStreams(bytes) {
|
|
|
42716
42732
|
throw new Error("Unsupported .xls: invalid OLE2 sector size");
|
|
42717
42733
|
}
|
|
42718
42734
|
const sectorOffset = (n) => sectorSize * (n + 1);
|
|
42735
|
+
const maxSectors = Math.ceil(bytes.length / sectorSize) + 1;
|
|
42719
42736
|
const difat = [];
|
|
42720
42737
|
for (let i2 = 0; i2 < 109; i2++) {
|
|
42721
42738
|
const v = u32(76 + i2 * 4);
|
|
@@ -42723,7 +42740,9 @@ function readCfbStreams(bytes) {
|
|
|
42723
42740
|
}
|
|
42724
42741
|
let ds = firstDifatSector;
|
|
42725
42742
|
const entriesPerSector = sectorSize / 4;
|
|
42726
|
-
|
|
42743
|
+
const seenDifat = /* @__PURE__ */ new Set();
|
|
42744
|
+
while (ds !== ENDOFCHAIN && ds !== FREESECT && ds < maxSectors && !seenDifat.has(ds)) {
|
|
42745
|
+
seenDifat.add(ds);
|
|
42727
42746
|
const base = sectorOffset(ds);
|
|
42728
42747
|
for (let i2 = 0; i2 < entriesPerSector - 1; i2++) {
|
|
42729
42748
|
const v = u32(base + i2 * 4);
|
|
@@ -42733,14 +42752,18 @@ function readCfbStreams(bytes) {
|
|
|
42733
42752
|
}
|
|
42734
42753
|
const fat = [];
|
|
42735
42754
|
for (const fatSector of difat) {
|
|
42755
|
+
if (fat.length >= maxSectors) break;
|
|
42756
|
+
if (fatSector >= maxSectors) continue;
|
|
42736
42757
|
const base = sectorOffset(fatSector);
|
|
42737
|
-
for (let i2 = 0; i2 < entriesPerSector
|
|
42758
|
+
for (let i2 = 0; i2 < entriesPerSector && fat.length < maxSectors; i2++) {
|
|
42759
|
+
fat.push(u32(base + i2 * 4));
|
|
42760
|
+
}
|
|
42738
42761
|
}
|
|
42739
42762
|
const readChain = (src, start, size, ss, offOf, chain) => {
|
|
42740
|
-
const
|
|
42763
|
+
const maxSectors2 = Math.floor(src.length / ss) + 2;
|
|
42741
42764
|
const parts = [];
|
|
42742
42765
|
let s = start;
|
|
42743
|
-
for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard <
|
|
42766
|
+
for (let guard = 0; s !== ENDOFCHAIN && s !== FREESECT && s < chain.length && guard < maxSectors2; guard++) {
|
|
42744
42767
|
const o = offOf(s);
|
|
42745
42768
|
parts.push(src.subarray(o, o + ss));
|
|
42746
42769
|
s = chain[s];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lotics/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.67.0",
|
|
4
4
|
"description": "Lotics SDK and CLI for AI agents",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@types/node": "^22.15.21",
|
|
27
27
|
"esbuild": "^0.28.1",
|
|
28
28
|
"typescript": "^6.0.3",
|
|
29
|
-
"vitest": "^4.1.
|
|
29
|
+
"vitest": "^4.1.9"
|
|
30
30
|
},
|
|
31
31
|
"keywords": [
|
|
32
32
|
"lotics",
|