@lotics/cli 0.172.0 → 0.174.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/src/cli.js CHANGED
@@ -45696,7 +45696,7 @@ function resultSideEffects(result) {
45696
45696
  }
45697
45697
 
45698
45698
  // src/version.ts
45699
- var VERSION = "0.172.0";
45699
+ var VERSION = "0.174.0";
45700
45700
 
45701
45701
  // src/timezone.ts
45702
45702
  function machineTimezone() {
@@ -48393,7 +48393,7 @@ function walk(node, visit) {
48393
48393
  }
48394
48394
  }
48395
48395
 
48396
- // src/generate_app_fields.ts
48396
+ // ../shared/src/generate_app_fields.ts
48397
48397
  var HEADER = `// Auto-generated by 'lotics app codegen' and 'lotics app pull'.
48398
48398
  // DO NOT EDIT \u2014 regenerated from the workspace schema.
48399
48399
  //
@@ -48511,6 +48511,17 @@ export type AppFields = typeof F;
48511
48511
  export type AppOptions = typeof OPT;
48512
48512
  `;
48513
48513
  }
48514
+ function codegenTableIds(queries, allowlist) {
48515
+ const ids = new Set(allowlist);
48516
+ for (const declaration of Object.values(queries)) {
48517
+ for (const id of collectQueryTableIds(declaration.ast)) ids.add(id);
48518
+ }
48519
+ return [...ids];
48520
+ }
48521
+ function readCodegenTablesAllowlist(pkg) {
48522
+ const tables = pkg?.lotics?.codegen?.tables;
48523
+ return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
48524
+ }
48514
48525
 
48515
48526
  // src/app_workflow_check.ts
48516
48527
  import fs7 from "node:fs";
@@ -71970,18 +71981,13 @@ function writeAppDts(projectDir, manifest) {
71970
71981
  ensureAppVitestSetup(projectDir);
71971
71982
  return written.map(([file2]) => file2);
71972
71983
  }
71973
- function readCodegenTablesAllowlist(projectDir) {
71974
- const pkg = JSON.parse(fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8"));
71975
- const tables = pkg.lotics?.codegen?.tables;
71976
- return Array.isArray(tables) ? tables.filter((t) => typeof t === "string") : [];
71977
- }
71978
71984
  function resolveCodegenTableIds(projectDir, queries) {
71979
- const ids = /* @__PURE__ */ new Set();
71980
- for (const decl of Object.values(queries)) {
71981
- for (const id of collectQueryTableIds(decl.ast)) ids.add(id);
71985
+ let manifest = null;
71986
+ try {
71987
+ manifest = JSON.parse(fs8.readFileSync(path9.join(projectDir, "package.json"), "utf-8"));
71988
+ } catch {
71982
71989
  }
71983
- for (const id of readCodegenTablesAllowlist(projectDir)) ids.add(id);
71984
- return [...ids];
71990
+ return codegenTableIds(queries, readCodegenTablesAllowlist(manifest));
71985
71991
  }
71986
71992
  function writeAppFields(projectDir, tables) {
71987
71993
  const dotLotics = path9.join(projectDir, ".lotics");
@@ -74023,15 +74029,19 @@ function reportKnowledgeWarnings(warnings) {
74023
74029
  answering from nowhere. Create them with those names, or edit the agent.`
74024
74030
  );
74025
74031
  }
74032
+ function instantiateBody(args) {
74033
+ return {
74034
+ ...args.noSampleData === true ? { no_sample_data: true } : {},
74035
+ ...args.adopt === true ? { adopt: true } : {},
74036
+ build_on_server: true
74037
+ };
74038
+ }
74026
74039
  async function starterInit(client, args) {
74027
74040
  const starter = await client.getPackage(args.starter_id);
74028
74041
  note(
74029
74042
  `Copying ${starter.name}${starter.is_official ? " (official)" : ""} into this workspace\u2026`
74030
74043
  );
74031
- const result = await client.instantiateStarter(args.starter_id, {
74032
- ...args.noSampleData === true ? { no_sample_data: true } : {},
74033
- ...args.adopt === true ? { adopt: true } : {}
74034
- });
74044
+ const result = await client.instantiateStarter(args.starter_id, instantiateBody(args));
74035
74045
  const tables = Object.keys(result.binding.entities ?? {}).sort();
74036
74046
  const knowledgeDocs = Object.keys(result.binding.knowledge ?? {}).sort();
74037
74047
  const templates = Object.keys(result.binding.templates ?? {}).sort();
@@ -74094,19 +74104,42 @@ Done \u2014 these are yours now, with no link back to the starter.`);
74094
74104
  stamp: { id: null, number: null },
74095
74105
  kept
74096
74106
  });
74107
+ const serverDeployed = result.deployed ?? null;
74097
74108
  if (starter.owned_by_caller !== true) {
74098
74109
  warn(
74099
- `
74110
+ serverDeployed !== null ? `
74111
+ Built ${starter.name} on Lotics \u2014 its package scripts and vite config are the
74112
+ publisher's code, run in an isolated container rather than on your machine.${starter.is_official ? " Lotics reviewed this starter." : ""}` : `
74100
74113
  Building ${starter.name} \u2014 this runs its build on your machine (its package scripts
74101
74114
  and vite config are the publisher's code, executed as you).${starter.is_official ? " Lotics reviewed this starter." : ""}`
74102
74115
  );
74103
- } else {
74116
+ } else if (serverDeployed === null) {
74104
74117
  note(`Building and deploying\u2026`);
74105
74118
  }
74106
- await appDeploy(client, {
74107
- projectDir: targetPath,
74108
- message: `Copied from starter ${starter.name}`
74109
- });
74119
+ const resumeDir = path10.relative(process.cwd(), targetPath) || ".";
74120
+ try {
74121
+ if (serverDeployed !== null) {
74122
+ note(`Deployed v${serverDeployed.version_number} \u2014 built on Lotics, no Node needed here.`);
74123
+ } else {
74124
+ await appDeploy(client, {
74125
+ projectDir: targetPath,
74126
+ message: `Copied from starter ${starter.name}`
74127
+ });
74128
+ }
74129
+ } catch (error52) {
74130
+ const reason = error52 instanceof Error ? error52.message : String(error52);
74131
+ throw new Error(
74132
+ `${reason}
74133
+
74134
+ The copy itself is DONE and nothing needs repeating: the tables, the sample
74135
+ records and the project all landed. Only the deploy is left.
74136
+
74137
+ Finish it: cd ${resumeDir} && lotics app deploy -m "Copied from starter ${starter.name}"
74138
+
74139
+ Do NOT re-run the copy \u2014 it would adopt the tables this one just created and
74140
+ insert the sample records again.`
74141
+ );
74142
+ }
74110
74143
  let signInUrl = null;
74111
74144
  try {
74112
74145
  const link = await client.login({
@@ -403,11 +403,25 @@ export declare class LoticsClient {
403
403
  version?: number;
404
404
  no_sample_data?: boolean;
405
405
  adopt?: boolean;
406
+ /** Ask the server to build and deploy the copy, so this machine needs no Node. */
407
+ build_on_server?: boolean;
406
408
  }): Promise<{
407
409
  app_id: string | null;
408
410
  starter_id: string;
409
411
  version: number;
410
412
  bundle_url: string | null;
413
+ /**
414
+ * The version the SERVER deployed, when it did.
415
+ *
416
+ * Optional in this type on purpose: a server that predates the field omits
417
+ * it entirely, and it is absent rather than null. Callers must treat "not
418
+ * there" and "null" alike and build locally — assuming the request was
419
+ * honoured would report success over an app nobody built.
420
+ */
421
+ deployed?: {
422
+ version_id: string;
423
+ version_number: number;
424
+ } | null;
411
425
  binding: Record<string, Record<string, string>>;
412
426
  sample_record_ids: Record<string, string[]>;
413
427
  knowledge_warnings: {
@@ -206,6 +206,17 @@ lotics app check # every pre-flight a deploy runs, without b
206
206
  lotics app deploy -m "<what changed + why>"
207
207
  ```
208
208
 
209
+ **A green suite says nothing about how the screen LOOKS**, and that half has its own pass:
210
+ `lotics docs reviewing` — render it, look at it, then measure what the look is telling you. Run it
211
+ before the deploy, not as an audit someone schedules after a complaint.
212
+
213
+ Every check above reads the SOURCE; none of them renders it. So the entire class of defect that
214
+ lives in the pixels — wrong form for the subject, a treatment that contradicts what an element
215
+ means, a surface that measures clean and still tells the reader nothing — passes all of them
216
+ silently, and arrives later as "it looks bad", which is a report about a cause the reporter cannot
217
+ name. That is what the review is for, and why it belongs here rather than in whoever remembers to
218
+ ask for it.
219
+
209
220
  `-m` is optional; the deploy derives a message from what it pushed. Write one when the *why* is
210
221
  worth keeping.
211
222
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/cli",
3
- "version": "0.172.0",
3
+ "version": "0.174.0",
4
4
  "description": "Lotics SDK and CLI for AI agents",
5
5
  "type": "module",
6
6
  "bin": {