@overaihq/cli 0.4.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.
Files changed (2) hide show
  1. package/dist/index.js +186 -63
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -26690,26 +26690,6 @@ var readValue = async (value, label) => {
26690
26690
  }
26691
26691
  };
26692
26692
 
26693
- // src/gql.ts
26694
- var gqlRequest = async (query, variables, options) => {
26695
- const res = await v2Fetch(
26696
- options?.v1 === true ? "/v1/graphql" : "/v2/graphql",
26697
- {
26698
- method: "POST",
26699
- headers: { "Content-Type": "application/json" },
26700
- body: JSON.stringify({ query, variables })
26701
- }
26702
- );
26703
- const body = await res.json().catch(() => null);
26704
- if (body?.errors != null && body.errors.length > 0) {
26705
- throw new Error(body.errors.map((e) => e.message).join("; "));
26706
- }
26707
- if (!res.ok || body?.data == null) {
26708
- throw new Error(`graphql failed (${String(res.status)})`);
26709
- }
26710
- return body.data;
26711
- };
26712
-
26713
26693
  // src/output.ts
26714
26694
  var resolveFormat = (explicit) => {
26715
26695
  if (explicit === "json" || explicit === "csv" || explicit === "table") {
@@ -26764,6 +26744,43 @@ var printResult = (data, format2) => {
26764
26744
  `);
26765
26745
  };
26766
26746
 
26747
+ // src/commands/agent.ts
26748
+ var runAgent = async (args) => {
26749
+ const [operation, id] = args;
26750
+ if (operation !== "generate" || id == null) throw new Error("Usage: overai agent generate <id> --message <text|@file|@->");
26751
+ const message = await readValue(flagValue(args, "--message", "-m"), "--message");
26752
+ if (message == null) throw new Error("Agent generate requires --message.");
26753
+ const { organizationId } = await getAccessToken();
26754
+ const response = await v2Fetch(`/v2/agents/${organizationId}/${id}/generate/text`, {
26755
+ method: "POST",
26756
+ headers: { "Content-Type": "application/json" },
26757
+ body: JSON.stringify({ message })
26758
+ });
26759
+ const body = await response.json().catch(() => null);
26760
+ if (!response.ok) throw new Error(body == null ? `Agent generate failed (${String(response.status)}).` : JSON.stringify(body));
26761
+ printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
26762
+ };
26763
+
26764
+ // src/gql.ts
26765
+ var gqlRequest = async (query, variables, options) => {
26766
+ const res = await v2Fetch(
26767
+ options?.v1 === true ? "/v1/graphql" : "/v2/graphql",
26768
+ {
26769
+ method: "POST",
26770
+ headers: { "Content-Type": "application/json" },
26771
+ body: JSON.stringify({ query, variables })
26772
+ }
26773
+ );
26774
+ const body = await res.json().catch(() => null);
26775
+ if (body?.errors != null && body.errors.length > 0) {
26776
+ throw new Error(body.errors.map((e) => e.message).join("; "));
26777
+ }
26778
+ if (!res.ok || body?.data == null) {
26779
+ throw new Error(`graphql failed (${String(res.status)})`);
26780
+ }
26781
+ return body.data;
26782
+ };
26783
+
26767
26784
  // src/commands/automation.ts
26768
26785
  var runRuns = async (automationId, args) => {
26769
26786
  const limit2 = Number(flagValue(args, "--limit") ?? 20);
@@ -26854,23 +26871,6 @@ var runAutomation = async (args) => {
26854
26871
  process.exitCode = 1;
26855
26872
  };
26856
26873
 
26857
- // src/commands/agent.ts
26858
- var runAgent = async (args) => {
26859
- const [operation, id] = args;
26860
- if (operation !== "generate" || id == null) throw new Error("Usage: overai agent generate <id> --message <text|@file|@->");
26861
- const message = await readValue(flagValue(args, "--message", "-m"), "--message");
26862
- if (message == null) throw new Error("Agent generate requires --message.");
26863
- const { organizationId } = await getAccessToken();
26864
- const response = await v2Fetch(`/v2/agents/${organizationId}/${id}/generate/text`, {
26865
- method: "POST",
26866
- headers: { "Content-Type": "application/json" },
26867
- body: JSON.stringify({ message })
26868
- });
26869
- const body = await response.json().catch(() => null);
26870
- if (!response.ok) throw new Error(body == null ? `Agent generate failed (${String(response.status)}).` : JSON.stringify(body));
26871
- printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
26872
- };
26873
-
26874
26874
  // src/workspace/manifest.ts
26875
26875
  import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
26876
26876
  import { dirname, join as join2, resolve } from "path";
@@ -33428,6 +33428,92 @@ import {
33428
33428
  writeFileSync as writeFileSync4
33429
33429
  } from "fs";
33430
33430
  import { join as join4, resolve as resolve3 } from "path";
33431
+
33432
+ // ../common/src/lint/schema.ts
33433
+ var lintSurfaceSchema = external_exports.enum([
33434
+ "webPage",
33435
+ // React/TSX page — gets rules-of-hooks
33436
+ "automationCode",
33437
+ // automation TS-code node (globals STATE/env/OUTPUT)
33438
+ "function"
33439
+ // Web-standard-runtime TS module (export default handler)
33440
+ ]);
33441
+ var lintDiagnosticSchema = external_exports.object({
33442
+ line: external_exports.number(),
33443
+ column: external_exports.number(),
33444
+ /** ESLint rule id, or null for a fatal parse error. */
33445
+ ruleId: external_exports.string().nullable(),
33446
+ message: external_exports.string(),
33447
+ severity: external_exports.enum(["error", "warning"])
33448
+ });
33449
+ var lintRequestSchema = external_exports.object({
33450
+ code: external_exports.string(),
33451
+ surface: lintSurfaceSchema,
33452
+ // The workspace the code is being authored in. Used to (a) authorize the
33453
+ // caller as a builder in that workspace and (b) resolve its real resources so
33454
+ // env id references are type-narrowed. A user token carries no workspace, so
33455
+ // this rides the request body.
33456
+ workspaceId: external_exports.string(),
33457
+ // The linted function's own declared output schema (function surface only),
33458
+ // enabling the handler return-vs-schema compliance check. Client-supplied
33459
+ // because the draft being linted lives in the editor, unsaved; advisory, so
33460
+ // nothing is trusted from it. '' or omitted skips the check.
33461
+ functionOutputSchema: external_exports.string().optional()
33462
+ });
33463
+ var lintResponseSchema = external_exports.object({
33464
+ diagnostics: external_exports.array(lintDiagnosticSchema)
33465
+ });
33466
+ var functionDeployImpactRequestSchema = external_exports.object({
33467
+ // Authorizes the builder-in-workspace gate, like the lint request.
33468
+ workspaceId: external_exports.string(),
33469
+ functionId: external_exports.string(),
33470
+ /** The saved version being deployed; its schema pair is read server-side. */
33471
+ versionNumber: external_exports.number().int()
33472
+ });
33473
+ var functionDeployDependentSchema = external_exports.object({
33474
+ kind: external_exports.enum(["webPage", "printablePage", "function", "automation"]),
33475
+ id: external_exports.string(),
33476
+ name: external_exports.string()
33477
+ });
33478
+ var functionDeployImpactResponseSchema = external_exports.object({
33479
+ /** True only when the contract is incompatible AND deployed callers exist. */
33480
+ breaking: external_exports.boolean(),
33481
+ /** Human-readable type mismatches, one per broken direction. */
33482
+ reasons: external_exports.array(external_exports.string()),
33483
+ /** Deployed resources whose code references this function's handle. */
33484
+ dependents: external_exports.array(functionDeployDependentSchema)
33485
+ });
33486
+
33487
+ // src/deployImpact.ts
33488
+ var NOT_BREAKING = {
33489
+ breaking: false,
33490
+ reasons: [],
33491
+ dependents: []
33492
+ };
33493
+ var fetchFunctionDeployImpact = async (workspaceId, functionId, versionNumber) => {
33494
+ try {
33495
+ const res = await v2Fetch("/v2/architect/functionDeployImpact", {
33496
+ method: "POST",
33497
+ headers: { "Content-Type": "application/json" },
33498
+ body: JSON.stringify({ workspaceId, functionId, versionNumber })
33499
+ });
33500
+ if (!res.ok) return NOT_BREAKING;
33501
+ const parsed = functionDeployImpactResponseSchema.safeParse(
33502
+ await res.json()
33503
+ );
33504
+ return parsed.success ? parsed.data : NOT_BREAKING;
33505
+ } catch {
33506
+ return NOT_BREAKING;
33507
+ }
33508
+ };
33509
+ var breakingDeployMessage = (name2, versionNumber, impact) => [
33510
+ `SKIP ${name2}: v${String(versionNumber)}'s declared input/output schemas are incompatible with deployed callers:`,
33511
+ ...impact.dependents.map((d) => ` ${d.name} (${d.kind}, ${d.id})`),
33512
+ ...impact.reasons.map((r) => ` ${r}`),
33513
+ `Fix the callers (or the schemas) first, or pass --allow-breaking to deploy anyway.`
33514
+ ].join("\n");
33515
+
33516
+ // src/commands/sync.ts
33431
33517
  var toManifestResource = (type, remote) => ({
33432
33518
  type,
33433
33519
  name: remote.name,
@@ -33665,6 +33751,7 @@ var runPush = async (args) => {
33665
33751
  const message = flagValue(args, "-m", "--message") ?? "Pushed via overai CLI";
33666
33752
  const deploy = args.includes("--deploy");
33667
33753
  const force = args.includes("--force");
33754
+ const allowBreaking = args.includes("--allow-breaking");
33668
33755
  const pathFilter = positionals(args)[0];
33669
33756
  let pushed = 0;
33670
33757
  for (const [id, resource] of resourcesMatching(manifest, pathFilter)) {
@@ -33709,6 +33796,20 @@ var runPush = async (args) => {
33709
33796
  `
33710
33797
  );
33711
33798
  if (deploy) {
33799
+ if (resource.type === "function" && !allowBreaking) {
33800
+ const impact = await fetchFunctionDeployImpact(
33801
+ manifest.workspaceId,
33802
+ id,
33803
+ versionNumber
33804
+ );
33805
+ if (impact.breaking) {
33806
+ process.stdout.write(
33807
+ `${breakingDeployMessage(resource.name, versionNumber, impact)}
33808
+ `
33809
+ );
33810
+ continue;
33811
+ }
33812
+ }
33712
33813
  await adapter.deploy(id, versionNumber);
33713
33814
  resource.deployedVersion = versionNumber;
33714
33815
  writeManifest(root, manifest);
@@ -33726,6 +33827,7 @@ var runPush = async (args) => {
33726
33827
  var runDeploy = async (args) => {
33727
33828
  const { root, manifest } = openClone();
33728
33829
  const pathFilter = positionals(args)[0];
33830
+ const allowBreaking = args.includes("--allow-breaking");
33729
33831
  const pending = resourcesMatching(manifest, pathFilter).filter(
33730
33832
  ([, r]) => r.deployedVersion !== r.baseVersion
33731
33833
  );
@@ -33749,6 +33851,20 @@ Pass a filter to deploy one, or --all to deploy everything.`
33749
33851
  );
33750
33852
  continue;
33751
33853
  }
33854
+ if (resource.type === "function" && !allowBreaking) {
33855
+ const impact = await fetchFunctionDeployImpact(
33856
+ manifest.workspaceId,
33857
+ id,
33858
+ resource.baseVersion
33859
+ );
33860
+ if (impact.breaking) {
33861
+ process.stdout.write(
33862
+ `${breakingDeployMessage(resource.name, resource.baseVersion, impact)}
33863
+ `
33864
+ );
33865
+ continue;
33866
+ }
33867
+ }
33752
33868
  await adapterFor(resource.type).deploy(id, resource.baseVersion);
33753
33869
  resource.deployedVersion = resource.baseVersion;
33754
33870
  writeManifest(root, manifest);
@@ -34146,30 +34262,6 @@ var runOpen = async (args) => {
34146
34262
  openBrowser(url);
34147
34263
  };
34148
34264
 
34149
- // src/commands/printablePage.ts
34150
- var runPrintablePage = async (args) => {
34151
- const [operation, id] = args;
34152
- if (operation !== "render" || id == null) throw new Error("Usage: overai printable-page render <id> [--search-params <json|@file>] [--timeout <ms>]");
34153
- const data = await gqlRequest(
34154
- `query CliPrintablePageWorkspace($id: String!) { printablePage(id: $id) { workspaceId } }`,
34155
- { id }
34156
- );
34157
- if (data.printablePage == null) throw new Error(`Printable page ${id} not found.`);
34158
- const searchParams = await readValue(flagValue(args, "--search-params"), "--search-params") ?? "{}";
34159
- JSON.parse(searchParams);
34160
- const { organizationId } = await getAccessToken();
34161
- const timeoutMs = Number(flagValue(args, "--timeout") ?? 6e4);
34162
- const response = await v2Fetch(`/v2/actions/${organizationId}/${data.printablePage.workspaceId}/run`, {
34163
- method: "POST",
34164
- headers: { "Content-Type": "application/json" },
34165
- body: JSON.stringify({ actionId: "PRINTABLE_PAGE_TO_PDF", inputs: { printablePageId: id, searchParams, includeDiagnostics: true } }),
34166
- signal: AbortSignal.timeout(timeoutMs)
34167
- });
34168
- const body = await response.json().catch(() => null);
34169
- if (!response.ok) throw new Error(JSON.stringify(body));
34170
- printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
34171
- };
34172
-
34173
34265
  // src/commands/org.ts
34174
34266
  var USER_ORGS_QUERY = `
34175
34267
  query UserOrganizations($identityId: String!) {
@@ -34235,6 +34327,30 @@ ${result.redirectUrl}
34235
34327
  `);
34236
34328
  };
34237
34329
 
34330
+ // src/commands/printablePage.ts
34331
+ var runPrintablePage = async (args) => {
34332
+ const [operation, id] = args;
34333
+ if (operation !== "render" || id == null) throw new Error("Usage: overai printable-page render <id> [--search-params <json|@file>] [--timeout <ms>]");
34334
+ const data = await gqlRequest(
34335
+ `query CliPrintablePageWorkspace($id: String!) { printablePage(id: $id) { workspaceId } }`,
34336
+ { id }
34337
+ );
34338
+ if (data.printablePage == null) throw new Error(`Printable page ${id} not found.`);
34339
+ const searchParams = await readValue(flagValue(args, "--search-params"), "--search-params") ?? "{}";
34340
+ JSON.parse(searchParams);
34341
+ const { organizationId } = await getAccessToken();
34342
+ const timeoutMs = Number(flagValue(args, "--timeout") ?? 6e4);
34343
+ const response = await v2Fetch(`/v2/actions/${organizationId}/${data.printablePage.workspaceId}/run`, {
34344
+ method: "POST",
34345
+ headers: { "Content-Type": "application/json" },
34346
+ body: JSON.stringify({ actionId: "PRINTABLE_PAGE_TO_PDF", inputs: { printablePageId: id, searchParams, includeDiagnostics: true } }),
34347
+ signal: AbortSignal.timeout(timeoutMs)
34348
+ });
34349
+ const body = await response.json().catch(() => null);
34350
+ if (!response.ok) throw new Error(JSON.stringify(body));
34351
+ printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
34352
+ };
34353
+
34238
34354
  // src/commands/update.ts
34239
34355
  import { spawnSync } from "child_process";
34240
34356
  import { existsSync as existsSync4, readFileSync as readFileSync8 } from "fs";
@@ -34629,6 +34745,10 @@ executionMemory MB).
34629
34745
  responds with \u2014 no request envelope) so env.FNxxx.call() is typed for
34630
34746
  callers: the deployed version's schemas become FunctionHandle<In, Out> in
34631
34747
  the editor and lint. Leave it "" when the response shape is unspecified.
34748
+ - That contract is checked at deploy time: \`overai deploy\` and
34749
+ \`overai push --deploy\` skip a function whose declared schema change is
34750
+ incompatible with deployed callers, printing the affected resources. Fix the
34751
+ callers (or the schemas) first, or pass \`--allow-breaking\` to deploy anyway.
34632
34752
  - Verify with \`overai fn <id> --input k=v\` (invokes the DEPLOYED version;
34633
34753
  add \`--method\`/\`--path\` to exercise one route of a router) and
34634
34754
  \`overai fn logs <id>\` / \`--execution <FEX id>\` for status, timing, logs,
@@ -35410,9 +35530,12 @@ Workspace sync (edit resources as local files):
35410
35530
  overai outline <filter>[@ref] Top-level declarations with their line
35411
35531
  ranges and doc comments
35412
35532
  overai pull Fast-forward clean resources to remote
35413
- overai push [filter] -m <msg> [--deploy] [--force]
35533
+ overai push [filter] -m <msg> [--deploy] [--force] [--allow-breaking]
35414
35534
  Create new versions from local edits
35415
- overai deploy [filter | --all] Point deployed versions at pushed ones
35535
+ overai deploy [filter | --all] Point deployed versions at pushed ones;
35536
+ a function whose schema change breaks
35537
+ deployed callers is skipped unless
35538
+ --allow-breaking
35416
35539
  overai restore <filter | --all> Discard local edits (back to base)
35417
35540
  overai open [filter | id] Open a resource (or the workspace) in the webapp
35418
35541
  overai dev <filter> [--port N] [--open]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@overaihq/cli",
3
- "version": "0.4.0",
3
+ "version": "0.5.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",