@overaihq/cli 0.5.0 → 0.6.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/README.md CHANGED
@@ -24,7 +24,7 @@ overai clone <workspaceId> # materialize resources and WORKSPACE.md
24
24
  # ...edit files...
25
25
  overai status # local edits + remote drift
26
26
  overai diff # what changed
27
- overai review # validation + best-practice review packet
27
+ overai review # local checks + authenticated TypeScript lint + guides
28
28
  overai report bug "<details>" # report broken or unexplained behavior
29
29
  overai report feature "<details>" # request a missing platform capability
30
30
  overai push -m "why" # create new versions (not live yet)
package/dist/index.js CHANGED
@@ -34764,7 +34764,8 @@ var workflow = `# CLI editing workflow
34764
34764
  each nested workspace you need separately.
34765
34765
  2. Edit files. The id in each filename is authoritative; slugs are cosmetic.
34766
34766
  3. \`overai status\` / \`overai diff\` \u2014 review what changed.
34767
- 4. \`overai review\` \u2014 validation + these guides; fix findings first.
34767
+ 4. \`overai review\` \u2014 local checks, authenticated TypeScript lint against the
34768
+ live workspace, and these guides; fix findings first.
34768
34769
  5. \`overai push -m "why"\` \u2014 creates NEW versions (not live). Fast-forward
34769
34770
  only: if the resource moved remotely, pull, re-apply, retry. Write commit
34770
34771
  messages like PR titles \u2014 they're the version history.
@@ -34802,11 +34803,11 @@ var runBestPractices = (args) => {
34802
34803
  );
34803
34804
  };
34804
34805
  var runReview = async () => {
34805
- const root = findWorkspaceRoot();
34806
- const manifest = readManifest(root);
34806
+ const { root, manifest } = openClone();
34807
34807
  const findings2 = [];
34808
34808
  const touchedTypes = /* @__PURE__ */ new Set();
34809
34809
  const changed = [];
34810
+ const lintTargets = [];
34810
34811
  for (const [id, resource] of Object.entries(manifest.resources)) {
34811
34812
  const { state, changedFiles } = localState(root, resource);
34812
34813
  if (state !== "modified") continue;
@@ -34853,6 +34854,37 @@ var runReview = async () => {
34853
34854
  }
34854
34855
  }
34855
34856
  }
34857
+ if (resource.type === "webPage") {
34858
+ changedFiles.filter((relPath) => relPath.endsWith(".tsx")).forEach((relPath) => {
34859
+ const code = readWorkingFile(root, relPath);
34860
+ if (code != null) {
34861
+ lintTargets.push({ label: relPath, code, surface: "webPage" });
34862
+ }
34863
+ });
34864
+ }
34865
+ if (resource.type === "function") {
34866
+ const codeFile = resource.files.find((path) => path.endsWith(".ts"));
34867
+ const metaFile = resource.files.find(
34868
+ (path) => path.endsWith(".meta.json")
34869
+ );
34870
+ const code = codeFile == null ? null : readWorkingFile(root, codeFile);
34871
+ const meta = metaFile == null ? null : readWorkingFile(root, metaFile);
34872
+ if (codeFile != null && code != null) {
34873
+ const parsedMeta = (() => {
34874
+ try {
34875
+ return JSON.parse(meta ?? "null");
34876
+ } catch {
34877
+ return null;
34878
+ }
34879
+ })();
34880
+ lintTargets.push({
34881
+ label: codeFile,
34882
+ code,
34883
+ surface: "function",
34884
+ functionOutputSchema: parsedMeta != null && typeof parsedMeta === "object" && "outputSchema" in parsedMeta && typeof parsedMeta.outputSchema === "string" ? parsedMeta.outputSchema : void 0
34885
+ });
34886
+ }
34887
+ }
34856
34888
  if (resource.type === "automation") {
34857
34889
  const docFile = resource.files.find((f) => f.endsWith(".json"));
34858
34890
  const raw2 = docFile == null ? null : readWorkingFile(root, docFile);
@@ -34864,6 +34896,25 @@ var runReview = async () => {
34864
34896
  (f) => `${docFile} elements.${f}`
34865
34897
  )
34866
34898
  );
34899
+ const nodes = Array.isArray(doc.elements) ? [...doc.elements] : [];
34900
+ for (const node of nodes) {
34901
+ if (node == null || typeof node !== "object") continue;
34902
+ const nodeRecord = node;
34903
+ if (Array.isArray(nodeRecord.elements)) {
34904
+ nodes.push(...nodeRecord.elements);
34905
+ }
34906
+ const inputs = nodeRecord.inputs;
34907
+ if (nodeRecord.nodeTypeId !== "TYPESCRIPT_CODE" || inputs == null || typeof inputs !== "object") {
34908
+ continue;
34909
+ }
34910
+ const code = inputs.code;
34911
+ if (typeof code !== "string") continue;
34912
+ lintTargets.push({
34913
+ label: `${docFile} ${typeof nodeRecord.variableId === "string" ? nodeRecord.variableId : "unknown node"}`,
34914
+ code,
34915
+ surface: "automationCode"
34916
+ });
34917
+ }
34867
34918
  } catch {
34868
34919
  }
34869
34920
  }
@@ -34873,6 +34924,47 @@ var runReview = async () => {
34873
34924
  process.stdout.write("Nothing modified locally \u2014 nothing to review.\n");
34874
34925
  return;
34875
34926
  }
34927
+ for (const target of lintTargets) {
34928
+ try {
34929
+ const response = await v2Fetch("/v2/architect/lint", {
34930
+ method: "POST",
34931
+ headers: { "Content-Type": "application/json" },
34932
+ body: JSON.stringify({
34933
+ code: target.code,
34934
+ surface: target.surface,
34935
+ workspaceId: manifest.workspaceId,
34936
+ functionOutputSchema: target.functionOutputSchema
34937
+ })
34938
+ });
34939
+ const responseText = await response.text();
34940
+ if (!response.ok) {
34941
+ throw new Error(
34942
+ `${target.label}: HTTP ${String(response.status)}${responseText ? ` \u2014 ${responseText}` : ""}`
34943
+ );
34944
+ }
34945
+ const parsed = lintResponseSchema.safeParse(
34946
+ (() => {
34947
+ try {
34948
+ return JSON.parse(responseText);
34949
+ } catch {
34950
+ return null;
34951
+ }
34952
+ })()
34953
+ );
34954
+ if (!parsed.success) {
34955
+ throw new Error(`${target.label}: invalid response from lint service`);
34956
+ }
34957
+ findings2.push(
34958
+ ...parsed.data.diagnostics.map(
34959
+ (diagnostic) => `${target.label}:${String(diagnostic.line)}:${String(diagnostic.column)}: ${diagnostic.severity}: ${diagnostic.message}${diagnostic.ruleId == null ? "" : ` (${diagnostic.ruleId})`}`
34960
+ )
34961
+ );
34962
+ } catch (error) {
34963
+ findings2.push(
34964
+ `${target.label}: remote lint could not run \u2014 ${error instanceof Error ? error.message : String(error)}`
34965
+ );
34966
+ }
34967
+ }
34876
34968
  const guides = ["workflow", ...touchedTypes].map((t) => t === "webPage" || t === "printablePage" ? "pages" : t).map((t) => t === "automation" ? "automations" : t).map((t) => t === "function" ? "functions" : t);
34877
34969
  const guideDocs = [...new Set(guides)].map((t) => BEST_PRACTICES[t]).filter((d) => d != null);
34878
34970
  process.stdout.write(
@@ -35540,7 +35632,7 @@ Workspace sync (edit resources as local files):
35540
35632
  overai open [filter | id] Open a resource (or the workspace) in the webapp
35541
35633
  overai dev <filter> [--port N] [--open]
35542
35634
  Live-preview a web page from local files
35543
- overai review Validation + best-practice review packet
35635
+ overai review Local checks + authenticated TypeScript lint + guides
35544
35636
  overai best-practices [topic] Print bundled guides
35545
35637
  overai report bug|feature "<details>"
35546
35638
  Send product feedback (use - for stdin)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overaihq/cli",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Create, edit, deploy, and run OverAI workspace resources from the command line",
5
5
  "type": "module",
6
6
  "homepage": "https://overai.com",
@@ -30,7 +30,7 @@
30
30
  "lint": "echo 'Run lint from the root of the repo'",
31
31
  "ts-check": "tsc --noEmit",
32
32
  "build": "tsup",
33
- "build:watch": "tsc -w",
33
+ "build:watch": "tsup --watch",
34
34
  "start": "node dist/index.js",
35
35
  "test": "vitest",
36
36
  "test:localhost": "vitest --run --config vitest.localhost.config.js"