@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.
- package/dist/index.js +186 -63
- 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]
|