@overaihq/cli 0.14.11 → 0.14.13
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 +6 -0
- package/dist/index.js +1286 -823
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -52345,6 +52345,317 @@ var exchangeSessionToken = (baseUrl, refreshToken, destinationOrgId) => unauthen
|
|
|
52345
52345
|
destinationOrgId
|
|
52346
52346
|
});
|
|
52347
52347
|
|
|
52348
|
+
// ../sdk/src/error.ts
|
|
52349
|
+
var OverAIError = class extends Error {
|
|
52350
|
+
/** HTTP status; 200 for a GraphQL errors-array failure. */
|
|
52351
|
+
status;
|
|
52352
|
+
/** URL pathname of the request, "" when unknown. */
|
|
52353
|
+
path;
|
|
52354
|
+
/** Parsed JSON body, the raw string when not JSON, or null. */
|
|
52355
|
+
body;
|
|
52356
|
+
/** The org the request ran as, when known. */
|
|
52357
|
+
organizationId;
|
|
52358
|
+
/** GraphQL errors array, when that is the cause. */
|
|
52359
|
+
errors;
|
|
52360
|
+
constructor(message, fields) {
|
|
52361
|
+
super(message);
|
|
52362
|
+
this.status = fields.status;
|
|
52363
|
+
this.path = fields.path;
|
|
52364
|
+
this.body = fields.body;
|
|
52365
|
+
this.organizationId = fields.organizationId;
|
|
52366
|
+
if (fields.errors != null) this.errors = fields.errors;
|
|
52367
|
+
}
|
|
52368
|
+
};
|
|
52369
|
+
var responsePath = (res) => {
|
|
52370
|
+
try {
|
|
52371
|
+
return new URL(res.url).pathname;
|
|
52372
|
+
} catch {
|
|
52373
|
+
return "";
|
|
52374
|
+
}
|
|
52375
|
+
};
|
|
52376
|
+
var STATUS_TEXT = {
|
|
52377
|
+
400: "Bad Request",
|
|
52378
|
+
401: "Unauthorized",
|
|
52379
|
+
403: "Forbidden",
|
|
52380
|
+
404: "Not Found",
|
|
52381
|
+
409: "Conflict",
|
|
52382
|
+
413: "Payload Too Large",
|
|
52383
|
+
429: "Too Many Requests",
|
|
52384
|
+
500: "Internal Server Error",
|
|
52385
|
+
503: "Service Unavailable"
|
|
52386
|
+
};
|
|
52387
|
+
var apiError = (label, res, rawBody, organizationId) => {
|
|
52388
|
+
const body = (() => {
|
|
52389
|
+
try {
|
|
52390
|
+
return JSON.parse(rawBody);
|
|
52391
|
+
} catch {
|
|
52392
|
+
return rawBody;
|
|
52393
|
+
}
|
|
52394
|
+
})();
|
|
52395
|
+
const structured = typeof body === "object" && body != null ? body : null;
|
|
52396
|
+
const field = structured?.error ?? structured?.message;
|
|
52397
|
+
const claimed = (typeof field === "string" ? field : rawBody).trim().slice(0, 500);
|
|
52398
|
+
const reason = claimed.length === 0 || claimed === "Error" || claimed === "null" || claimed === "undefined" || claimed.toLowerCase() === STATUS_TEXT[res.status]?.toLowerCase() ? null : claimed;
|
|
52399
|
+
const path = responsePath(res);
|
|
52400
|
+
const fields = { status: res.status, path, body, organizationId };
|
|
52401
|
+
if (reason != null) return new OverAIError(reason, fields);
|
|
52402
|
+
return new OverAIError(
|
|
52403
|
+
`${label}: HTTP ${String(res.status)}, no reason given by the server.${path === "" ? "" : `
|
|
52404
|
+
${path}`}${organizationId == null ? "" : `
|
|
52405
|
+
Asked as org ${organizationId}.`}`,
|
|
52406
|
+
fields
|
|
52407
|
+
);
|
|
52408
|
+
};
|
|
52409
|
+
|
|
52410
|
+
// ../sdk/src/agentRun.ts
|
|
52411
|
+
var agentRun = (client, id) => {
|
|
52412
|
+
const deployedVersionNumber = async () => {
|
|
52413
|
+
const deployed = await client.graphql(
|
|
52414
|
+
`query SdkAgentDeployedVersion($id: String!) {
|
|
52415
|
+
agentDeployedVersions(condition: { agentId: $id }) { nodes { versionNumber } }
|
|
52416
|
+
}`,
|
|
52417
|
+
{ id }
|
|
52418
|
+
);
|
|
52419
|
+
const versionNumber = deployed.agentDeployedVersions?.nodes[0]?.versionNumber;
|
|
52420
|
+
if (versionNumber == null) {
|
|
52421
|
+
throw new Error(
|
|
52422
|
+
`Agent ${id} has no deployed version; pass --version <n> to inspect a saved one.`
|
|
52423
|
+
);
|
|
52424
|
+
}
|
|
52425
|
+
return versionNumber;
|
|
52426
|
+
};
|
|
52427
|
+
return {
|
|
52428
|
+
generate: async (message) => {
|
|
52429
|
+
const organizationId = await client.organizationId();
|
|
52430
|
+
const res = await client.fetch(
|
|
52431
|
+
`/v2/agents/${organizationId}/${id}/generate/text`,
|
|
52432
|
+
{
|
|
52433
|
+
method: "POST",
|
|
52434
|
+
headers: { "Content-Type": "application/json" },
|
|
52435
|
+
body: JSON.stringify({ message })
|
|
52436
|
+
}
|
|
52437
|
+
);
|
|
52438
|
+
const raw2 = await res.text();
|
|
52439
|
+
if (!res.ok) throw apiError("agent generate", res, raw2, organizationId);
|
|
52440
|
+
return JSON.parse(raw2);
|
|
52441
|
+
},
|
|
52442
|
+
/*
|
|
52443
|
+
* What an agent can actually do is spread over five bindings and a model,
|
|
52444
|
+
* and nothing in the product shows it in one place.
|
|
52445
|
+
*/
|
|
52446
|
+
tools: async (ref = "deployed") => {
|
|
52447
|
+
const version2 = typeof ref === "number" ? ref : ref === "latest" ? (await client.agent(id).head()).latestVersion : await deployedVersionNumber();
|
|
52448
|
+
const data = await client.graphql(
|
|
52449
|
+
`query SdkAgentTools($id: String!, $version: Int!) {
|
|
52450
|
+
agent(id: $id) {
|
|
52451
|
+
name
|
|
52452
|
+
agentVersions(first: 1, condition: { versionNumber: $version }) {
|
|
52453
|
+
nodes {
|
|
52454
|
+
versionNumber
|
|
52455
|
+
model
|
|
52456
|
+
agentVersionFunctionsByAgentIdAndVersionNumber(orderBy: [FUNCTION_ID_ASC]) {
|
|
52457
|
+
nodes { functionId function { name } }
|
|
52458
|
+
}
|
|
52459
|
+
agentVersionTableSpacesByAgentIdAndVersionNumber(orderBy: [TABLE_SPACE_ID_ASC]) {
|
|
52460
|
+
nodes { tableSpaceId accessMode }
|
|
52461
|
+
}
|
|
52462
|
+
agentVersionAgentsByAgentIdAndVersionNumber(orderBy: [ATTACHED_AGENT_ID_ASC]) {
|
|
52463
|
+
nodes { attachedAgentId }
|
|
52464
|
+
}
|
|
52465
|
+
agentVersionKnowledgeBasesByAgentIdAndVersionNumber(orderBy: [KNOWLEDGE_BASE_ID_ASC]) {
|
|
52466
|
+
nodes { knowledgeBaseId }
|
|
52467
|
+
}
|
|
52468
|
+
agentVersionBuiltinToolSetsByAgentIdAndVersionNumber(orderBy: [TOOL_SET_ASC]) {
|
|
52469
|
+
nodes { toolSet }
|
|
52470
|
+
}
|
|
52471
|
+
}
|
|
52472
|
+
}
|
|
52473
|
+
}
|
|
52474
|
+
}`,
|
|
52475
|
+
{ id, version: version2 }
|
|
52476
|
+
);
|
|
52477
|
+
if (data.agent == null) throw new Error(`Agent ${id} not found.`);
|
|
52478
|
+
const agentVersion = data.agent.agentVersions.nodes[0];
|
|
52479
|
+
if (agentVersion == null) {
|
|
52480
|
+
throw new Error(`Agent ${id} has no version ${String(version2)}.`);
|
|
52481
|
+
}
|
|
52482
|
+
return {
|
|
52483
|
+
agent: data.agent.name,
|
|
52484
|
+
version: agentVersion.versionNumber,
|
|
52485
|
+
model: agentVersion.model,
|
|
52486
|
+
tools: [
|
|
52487
|
+
...agentVersion.agentVersionFunctionsByAgentIdAndVersionNumber.nodes.map(
|
|
52488
|
+
(link) => ({
|
|
52489
|
+
kind: "function",
|
|
52490
|
+
name: link.function?.name ?? link.functionId,
|
|
52491
|
+
detail: link.functionId
|
|
52492
|
+
})
|
|
52493
|
+
),
|
|
52494
|
+
...agentVersion.agentVersionTableSpacesByAgentIdAndVersionNumber.nodes.map(
|
|
52495
|
+
(link) => ({
|
|
52496
|
+
kind: "table space",
|
|
52497
|
+
name: link.tableSpaceId,
|
|
52498
|
+
detail: link.accessMode
|
|
52499
|
+
})
|
|
52500
|
+
),
|
|
52501
|
+
...agentVersion.agentVersionAgentsByAgentIdAndVersionNumber.nodes.map(
|
|
52502
|
+
(link) => ({
|
|
52503
|
+
kind: "sub-agent",
|
|
52504
|
+
name: link.attachedAgentId,
|
|
52505
|
+
detail: ""
|
|
52506
|
+
})
|
|
52507
|
+
),
|
|
52508
|
+
...agentVersion.agentVersionKnowledgeBasesByAgentIdAndVersionNumber.nodes.map(
|
|
52509
|
+
(link) => ({
|
|
52510
|
+
kind: "knowledge base",
|
|
52511
|
+
name: link.knowledgeBaseId,
|
|
52512
|
+
detail: ""
|
|
52513
|
+
})
|
|
52514
|
+
),
|
|
52515
|
+
...agentVersion.agentVersionBuiltinToolSetsByAgentIdAndVersionNumber.nodes.map(
|
|
52516
|
+
(link) => ({
|
|
52517
|
+
kind: "built-in",
|
|
52518
|
+
name: link.toolSet,
|
|
52519
|
+
detail: ""
|
|
52520
|
+
})
|
|
52521
|
+
)
|
|
52522
|
+
]
|
|
52523
|
+
};
|
|
52524
|
+
},
|
|
52525
|
+
/* A caller that wants a second turn must create the conversation first — as the webapp does. */
|
|
52526
|
+
createConversation: async (title) => {
|
|
52527
|
+
const versionNumber = await deployedVersionNumber();
|
|
52528
|
+
const created = await client.graphql(
|
|
52529
|
+
`mutation SdkCreateAgentConversation($input: CreateAgentConversationInput!) {
|
|
52530
|
+
createAgentConversation(input: $input) { agentConversation { id } }
|
|
52531
|
+
}`,
|
|
52532
|
+
{
|
|
52533
|
+
input: {
|
|
52534
|
+
agentConversation: {
|
|
52535
|
+
agentId: id,
|
|
52536
|
+
versionNumber,
|
|
52537
|
+
title: title.length > 50 ? `${title.slice(0, 47)}...` : title
|
|
52538
|
+
}
|
|
52539
|
+
}
|
|
52540
|
+
}
|
|
52541
|
+
);
|
|
52542
|
+
const conversationId = created.createAgentConversation?.agentConversation?.id;
|
|
52543
|
+
if (conversationId == null)
|
|
52544
|
+
throw new Error("Failed to create a conversation.");
|
|
52545
|
+
return conversationId;
|
|
52546
|
+
},
|
|
52547
|
+
chat: async (messages, options) => {
|
|
52548
|
+
const organizationId = await client.organizationId();
|
|
52549
|
+
const res = await client.fetch(`/v2/agents/${organizationId}/${id}`, {
|
|
52550
|
+
method: "POST",
|
|
52551
|
+
headers: { "Content-Type": "application/json" },
|
|
52552
|
+
body: JSON.stringify({
|
|
52553
|
+
messages,
|
|
52554
|
+
conversationId: options.conversationId
|
|
52555
|
+
})
|
|
52556
|
+
});
|
|
52557
|
+
if (!res.ok)
|
|
52558
|
+
throw apiError("agent chat", res, await res.text(), organizationId);
|
|
52559
|
+
return res;
|
|
52560
|
+
}
|
|
52561
|
+
};
|
|
52562
|
+
};
|
|
52563
|
+
var agentStreamEvents = (response) => {
|
|
52564
|
+
const parse4 = (line) => {
|
|
52565
|
+
if (!line.startsWith("data: ")) return null;
|
|
52566
|
+
const payload = line.slice(6);
|
|
52567
|
+
if (payload === "[DONE]") return "done";
|
|
52568
|
+
const event = (() => {
|
|
52569
|
+
try {
|
|
52570
|
+
return JSON.parse(payload);
|
|
52571
|
+
} catch {
|
|
52572
|
+
return null;
|
|
52573
|
+
}
|
|
52574
|
+
})();
|
|
52575
|
+
if (event?.type === "text-delta" && event.delta != null)
|
|
52576
|
+
return { type: "text-delta", delta: event.delta };
|
|
52577
|
+
if (event?.type === "error")
|
|
52578
|
+
return event.errorText == null ? { type: "error" } : { type: "error", errorText: event.errorText };
|
|
52579
|
+
return null;
|
|
52580
|
+
};
|
|
52581
|
+
return (async function* () {
|
|
52582
|
+
const body = response.body;
|
|
52583
|
+
if (body == null) return;
|
|
52584
|
+
const decoder = new TextDecoder();
|
|
52585
|
+
const reader = body.getReader();
|
|
52586
|
+
let buffer = "";
|
|
52587
|
+
for (; ; ) {
|
|
52588
|
+
const { value, done } = await reader.read();
|
|
52589
|
+
if (done) break;
|
|
52590
|
+
buffer += decoder.decode(value, { stream: true });
|
|
52591
|
+
const lines = buffer.split("\n");
|
|
52592
|
+
buffer = lines.pop() ?? "";
|
|
52593
|
+
for (const line of lines) {
|
|
52594
|
+
const event = parse4(line);
|
|
52595
|
+
if (event === "done") return;
|
|
52596
|
+
if (event != null) yield event;
|
|
52597
|
+
}
|
|
52598
|
+
}
|
|
52599
|
+
const last2 = parse4(buffer + decoder.decode());
|
|
52600
|
+
if (last2 != null && last2 !== "done") yield last2;
|
|
52601
|
+
})();
|
|
52602
|
+
};
|
|
52603
|
+
|
|
52604
|
+
// ../sdk/src/automationRun.ts
|
|
52605
|
+
var automationRunApi = (client, id) => ({
|
|
52606
|
+
run: async (inputs) => {
|
|
52607
|
+
const organizationId = await client.organizationId();
|
|
52608
|
+
const res = await client.fetch(
|
|
52609
|
+
`/v2/automations/${organizationId}/${id}/run`,
|
|
52610
|
+
{
|
|
52611
|
+
method: "POST",
|
|
52612
|
+
headers: { "Content-Type": "application/json" },
|
|
52613
|
+
body: JSON.stringify(inputs ?? {})
|
|
52614
|
+
}
|
|
52615
|
+
);
|
|
52616
|
+
const raw2 = await res.text();
|
|
52617
|
+
if (!res.ok) throw apiError("automation run", res, raw2, organizationId);
|
|
52618
|
+
return JSON.parse(raw2);
|
|
52619
|
+
},
|
|
52620
|
+
/*
|
|
52621
|
+
* The v2 condition filters only by automationId; status filters apply
|
|
52622
|
+
* here (the condition type has no errored/isCancelled fields), so a
|
|
52623
|
+
* filtered read over-fetches to still fill the limit.
|
|
52624
|
+
*/
|
|
52625
|
+
runs: async (options) => {
|
|
52626
|
+
const limit2 = options?.limit ?? 20;
|
|
52627
|
+
const filtered = options?.failed === true || options?.running === true;
|
|
52628
|
+
const data = await client.graphql(
|
|
52629
|
+
`query SdkAutomationRuns($automationId: String!, $first: Int!) {
|
|
52630
|
+
automationRuns(condition: { automationId: $automationId }, orderBy: [STARTED_AT_DESC], first: $first) {
|
|
52631
|
+
nodes { id startedAt endedAt errored isCancelled manuallyTriggered version { num } }
|
|
52632
|
+
}
|
|
52633
|
+
}`,
|
|
52634
|
+
{ automationId: id, first: filtered ? limit2 * 5 : limit2 }
|
|
52635
|
+
);
|
|
52636
|
+
return data.automationRuns.nodes.filter((r) => options?.failed !== true || r.errored).filter(
|
|
52637
|
+
(r) => options?.running !== true || r.endedAt == null && !r.isCancelled
|
|
52638
|
+
).slice(0, limit2).map((r) => ({
|
|
52639
|
+
id: r.id,
|
|
52640
|
+
version: r.version?.num,
|
|
52641
|
+
startedAt: r.startedAt,
|
|
52642
|
+
endedAt: r.endedAt,
|
|
52643
|
+
status: r.errored ? "errored" : r.isCancelled ? "cancelled" : r.endedAt == null ? "running" : "ok",
|
|
52644
|
+
manual: r.manuallyTriggered
|
|
52645
|
+
}));
|
|
52646
|
+
}
|
|
52647
|
+
});
|
|
52648
|
+
var automationRunState = async (client, runId) => {
|
|
52649
|
+
const data = await client.graphql(
|
|
52650
|
+
`query SdkAutomationRunState($id: String!) {
|
|
52651
|
+
automationRun(id: $id) { state }
|
|
52652
|
+
}`,
|
|
52653
|
+
{ id: runId }
|
|
52654
|
+
);
|
|
52655
|
+
if (data.automationRun == null) throw new Error(`Run ${runId} not found.`);
|
|
52656
|
+
return data.automationRun.state ?? {};
|
|
52657
|
+
};
|
|
52658
|
+
|
|
52348
52659
|
// ../common/src/agent.ts
|
|
52349
52660
|
var agentVersionConfigSchema = external_exports.object({
|
|
52350
52661
|
systemPrompt: external_exports.string(),
|
|
@@ -58547,6 +58858,81 @@ var createDataFile = async (client, input2) => {
|
|
|
58547
58858
|
return { id };
|
|
58548
58859
|
};
|
|
58549
58860
|
|
|
58861
|
+
// ../sdk/src/dataFiles.ts
|
|
58862
|
+
var dataFileResource = (client, id) => ({
|
|
58863
|
+
read: async () => {
|
|
58864
|
+
const organizationId = await client.organizationId();
|
|
58865
|
+
const res = await client.fetch(`/v2/data-files/${organizationId}/${id}`, {
|
|
58866
|
+
redirect: "follow"
|
|
58867
|
+
});
|
|
58868
|
+
if (!res.ok)
|
|
58869
|
+
throw apiError(
|
|
58870
|
+
"data-file download",
|
|
58871
|
+
res,
|
|
58872
|
+
await res.text(),
|
|
58873
|
+
organizationId
|
|
58874
|
+
);
|
|
58875
|
+
return res;
|
|
58876
|
+
},
|
|
58877
|
+
head: async (options) => {
|
|
58878
|
+
const organizationId = await client.organizationId();
|
|
58879
|
+
const res = await client.fetch(
|
|
58880
|
+
`/v2/data-files/${organizationId}/${id}/head?numLines=${String(options?.lines ?? 50)}`,
|
|
58881
|
+
{ redirect: "follow" }
|
|
58882
|
+
);
|
|
58883
|
+
if (!res.ok)
|
|
58884
|
+
throw apiError("data-file head", res, await res.text(), organizationId);
|
|
58885
|
+
return res;
|
|
58886
|
+
},
|
|
58887
|
+
upload: async (content, options) => {
|
|
58888
|
+
const url2 = await client.trpc("dataFiles.getDataFileUploadUrl", {
|
|
58889
|
+
dataFileId: id,
|
|
58890
|
+
fileSize: content.size,
|
|
58891
|
+
message: options?.message ?? ""
|
|
58892
|
+
});
|
|
58893
|
+
const res = await fetch(url2, { method: "PUT", body: content });
|
|
58894
|
+
if (!res.ok)
|
|
58895
|
+
throw apiError(
|
|
58896
|
+
"data-file upload",
|
|
58897
|
+
res,
|
|
58898
|
+
await res.text(),
|
|
58899
|
+
await client.organizationId()
|
|
58900
|
+
);
|
|
58901
|
+
}
|
|
58902
|
+
});
|
|
58903
|
+
|
|
58904
|
+
// ../sdk/src/dataStreams.ts
|
|
58905
|
+
var dataStreamResource = (client, id) => ({
|
|
58906
|
+
append: async (records) => {
|
|
58907
|
+
const organizationId = await client.organizationId();
|
|
58908
|
+
const res = await client.fetch(`/v1/data-streams/${organizationId}/${id}`, {
|
|
58909
|
+
method: "POST",
|
|
58910
|
+
headers: { "Content-Type": "application/json" },
|
|
58911
|
+
body: JSON.stringify({
|
|
58912
|
+
data: Array.isArray(records) ? records : [records]
|
|
58913
|
+
})
|
|
58914
|
+
});
|
|
58915
|
+
const raw2 = await res.text();
|
|
58916
|
+
if (!res.ok) throw apiError("data-stream append", res, raw2, organizationId);
|
|
58917
|
+
return JSON.parse(raw2);
|
|
58918
|
+
},
|
|
58919
|
+
query: async (options) => {
|
|
58920
|
+
const organizationId = await client.organizationId();
|
|
58921
|
+
const search2 = new URLSearchParams({
|
|
58922
|
+
startAt: options.startAt,
|
|
58923
|
+
endAt: options.endAt,
|
|
58924
|
+
query: options.query ?? ""
|
|
58925
|
+
});
|
|
58926
|
+
if (options.limit != null) search2.set("limit", String(options.limit));
|
|
58927
|
+
const res = await client.fetch(
|
|
58928
|
+
`/v1/data-streams/${organizationId}/${id}?${search2.toString()}`
|
|
58929
|
+
);
|
|
58930
|
+
const raw2 = await res.text();
|
|
58931
|
+
if (!res.ok) throw apiError("data-stream query", res, raw2, organizationId);
|
|
58932
|
+
return JSON.parse(raw2);
|
|
58933
|
+
}
|
|
58934
|
+
});
|
|
58935
|
+
|
|
58550
58936
|
// ../../node_modules/.pnpm/diff@9.0.0/node_modules/diff/libesm/diff/base.js
|
|
58551
58937
|
var Diff = class {
|
|
58552
58938
|
diff(oldStr, newStr, options = {}) {
|
|
@@ -60392,67 +60778,106 @@ var functionResource = (client, id) => {
|
|
|
60392
60778
|
};
|
|
60393
60779
|
};
|
|
60394
60780
|
|
|
60395
|
-
// ../sdk/src/
|
|
60396
|
-
var
|
|
60397
|
-
|
|
60398
|
-
|
|
60399
|
-
|
|
60400
|
-
|
|
60401
|
-
|
|
60402
|
-
|
|
60403
|
-
|
|
60404
|
-
|
|
60405
|
-
|
|
60406
|
-
|
|
60407
|
-
|
|
60408
|
-
|
|
60409
|
-
|
|
60410
|
-
|
|
60411
|
-
|
|
60412
|
-
|
|
60413
|
-
|
|
60414
|
-
|
|
60415
|
-
|
|
60416
|
-
|
|
60417
|
-
|
|
60418
|
-
|
|
60419
|
-
|
|
60420
|
-
|
|
60781
|
+
// ../sdk/src/functionRun.ts
|
|
60782
|
+
var functionRun = (client, id) => ({
|
|
60783
|
+
/*
|
|
60784
|
+
* Mirrors `env.FNxxx.call` (common-server envProxy `__callFunction`), so a
|
|
60785
|
+
* caller moving between the sandbox and the SDK keeps one mental model.
|
|
60786
|
+
*/
|
|
60787
|
+
call: async (init) => {
|
|
60788
|
+
const { path: rawPath = "", query = {}, body, ...rest } = init ?? {};
|
|
60789
|
+
const queryStart = rawPath.indexOf("?");
|
|
60790
|
+
const pathOnly = queryStart === -1 ? rawPath : rawPath.slice(0, queryStart);
|
|
60791
|
+
const subPath = pathOnly === "" || pathOnly.startsWith("/") ? pathOnly : `/${pathOnly}`;
|
|
60792
|
+
const params = new URLSearchParams(
|
|
60793
|
+
queryStart === -1 ? "" : rawPath.slice(queryStart + 1)
|
|
60794
|
+
);
|
|
60795
|
+
Object.entries(query).forEach(([name2, value]) => {
|
|
60796
|
+
params.set(name2, value);
|
|
60797
|
+
});
|
|
60798
|
+
const search2 = params.toString();
|
|
60799
|
+
const headers = new Headers(rest.headers);
|
|
60800
|
+
const isNativeBody = typeof body === "string" || body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams || body instanceof ArrayBuffer || ArrayBuffer.isView(body) || body instanceof ReadableStream;
|
|
60801
|
+
if (body != null && !isNativeBody && !headers.has("Content-Type"))
|
|
60802
|
+
headers.set("Content-Type", "application/json");
|
|
60803
|
+
return client.fetch(
|
|
60804
|
+
`/v2/functions/${await client.organizationId()}/${id}${subPath}${search2 === "" ? "" : `?${search2}`}`,
|
|
60805
|
+
{
|
|
60806
|
+
...rest,
|
|
60807
|
+
method: rest.method ?? "POST",
|
|
60808
|
+
headers,
|
|
60809
|
+
body: body == null ? void 0 : isNativeBody ? body : JSON.stringify(body)
|
|
60810
|
+
}
|
|
60811
|
+
);
|
|
60812
|
+
},
|
|
60813
|
+
executions: async (options) => (await client.graphql(
|
|
60814
|
+
`query SdkFunctionExecutions($functionId: String!, $first: Int!) {
|
|
60815
|
+
functionExecutions(condition: { functionId: $functionId }, orderBy: [CREATED_AT_DESC], first: $first) {
|
|
60816
|
+
nodes { id createdAt httpStatusCode executionTime requestMethod requestPath versionNumber }
|
|
60817
|
+
}
|
|
60818
|
+
}`,
|
|
60819
|
+
{ functionId: id, first: options?.limit ?? 20 }
|
|
60820
|
+
)).functionExecutions.nodes,
|
|
60821
|
+
// Logs and bodies live behind presigned S3 URLs (valid ~1h); they carry
|
|
60822
|
+
// their own auth, so they go through the global fetch with no token.
|
|
60823
|
+
execution: async (executionId) => {
|
|
60824
|
+
const data = await client.graphql(
|
|
60825
|
+
`query SdkFunctionExecution($functionId: String!, $id: String!) {
|
|
60826
|
+
functionExecutions(condition: { functionId: $functionId, id: $id }, first: 1) {
|
|
60827
|
+
nodes { id summary createdAt httpStatusCode executionTime versionNumber logsUrl inputBodyUrl outputBodyUrl }
|
|
60828
|
+
}
|
|
60829
|
+
}`,
|
|
60830
|
+
{ functionId: id, id: executionId }
|
|
60831
|
+
);
|
|
60832
|
+
const execution = data.functionExecutions.nodes[0];
|
|
60833
|
+
if (execution == null)
|
|
60834
|
+
throw new Error(`Execution ${executionId} not found.`);
|
|
60835
|
+
const [logs, input2, output2] = await Promise.all(
|
|
60836
|
+
[execution.logsUrl, execution.inputBodyUrl, execution.outputBodyUrl].map(
|
|
60837
|
+
async (url2) => url2 == null ? null : await fetch(url2).then((r) => r.ok ? r.text() : null)
|
|
60838
|
+
)
|
|
60839
|
+
);
|
|
60840
|
+
return {
|
|
60841
|
+
id: execution.id,
|
|
60842
|
+
createdAt: execution.createdAt,
|
|
60843
|
+
httpStatusCode: execution.httpStatusCode,
|
|
60844
|
+
executionTime: execution.executionTime,
|
|
60845
|
+
versionNumber: execution.versionNumber,
|
|
60846
|
+
summary: execution.summary,
|
|
60847
|
+
input: input2 ?? null,
|
|
60848
|
+
output: output2 ?? null,
|
|
60849
|
+
logs: logs ?? null
|
|
60850
|
+
};
|
|
60421
60851
|
}
|
|
60422
|
-
};
|
|
60423
|
-
|
|
60424
|
-
|
|
60425
|
-
|
|
60426
|
-
|
|
60427
|
-
|
|
60428
|
-
|
|
60429
|
-
|
|
60430
|
-
|
|
60431
|
-
|
|
60432
|
-
|
|
60433
|
-
|
|
60434
|
-
|
|
60435
|
-
|
|
60436
|
-
|
|
60437
|
-
|
|
60438
|
-
|
|
60439
|
-
|
|
60440
|
-
|
|
60441
|
-
|
|
60442
|
-
|
|
60443
|
-
|
|
60444
|
-
|
|
60445
|
-
|
|
60446
|
-
|
|
60447
|
-
|
|
60448
|
-
|
|
60449
|
-
|
|
60450
|
-
|
|
60451
|
-
${path}`}${organizationId == null ? "" : `
|
|
60452
|
-
Asked as org ${organizationId}.`}`,
|
|
60453
|
-
fields
|
|
60454
|
-
);
|
|
60455
|
-
};
|
|
60852
|
+
});
|
|
60853
|
+
|
|
60854
|
+
// ../sdk/src/integrations.ts
|
|
60855
|
+
var integrationResource = (client, id) => ({
|
|
60856
|
+
configure: async (value) => {
|
|
60857
|
+
await client.trpc("putIntegrationConfig", { id, value });
|
|
60858
|
+
},
|
|
60859
|
+
// Config reads are for inspection, not secret export; keep credentials out
|
|
60860
|
+
// of terminals, shell history captures, and agent transcripts.
|
|
60861
|
+
config: () => client.trpc("getMaskedIntegrationConfig", { id }),
|
|
60862
|
+
setSecret: async (key, value) => {
|
|
60863
|
+
await client.graphql(
|
|
60864
|
+
`mutation SdkSetIntegrationSecret($input: UpdateIntegrationConfigInput!) {
|
|
60865
|
+
updateIntegrationConfig(input: $input) { success }
|
|
60866
|
+
}`,
|
|
60867
|
+
{ input: { integrationId: id, partialConfig: { [key]: value } } }
|
|
60868
|
+
);
|
|
60869
|
+
},
|
|
60870
|
+
// The merge mutation stores a JSON null for `{key: null}`, so removal is its
|
|
60871
|
+
// own mutation server-side.
|
|
60872
|
+
unsetSecret: async (key) => {
|
|
60873
|
+
await client.graphql(
|
|
60874
|
+
`mutation SdkUnsetIntegrationSecret($input: DeleteIntegrationConfigKeyInput!) {
|
|
60875
|
+
deleteIntegrationConfigKey(input: $input) { success }
|
|
60876
|
+
}`,
|
|
60877
|
+
{ input: { integrationId: id, key } }
|
|
60878
|
+
);
|
|
60879
|
+
}
|
|
60880
|
+
});
|
|
60456
60881
|
|
|
60457
60882
|
// ../sdk/src/jwt.ts
|
|
60458
60883
|
var decodeJwtClaims = (token) => {
|
|
@@ -60470,6 +60895,112 @@ var decodeJwtClaims = (token) => {
|
|
|
60470
60895
|
}
|
|
60471
60896
|
};
|
|
60472
60897
|
|
|
60898
|
+
// ../sdk/src/knowledgeBases.ts
|
|
60899
|
+
var knowledgeBaseResource = (client, id) => ({
|
|
60900
|
+
upload: async (file2, name2) => {
|
|
60901
|
+
const organizationId = await client.organizationId();
|
|
60902
|
+
const formData = new FormData();
|
|
60903
|
+
formData.append("file", file2, name2);
|
|
60904
|
+
const res = await client.fetch(
|
|
60905
|
+
`/v2/knowledge-bases/${organizationId}/${id}/upload`,
|
|
60906
|
+
{ method: "POST", body: formData }
|
|
60907
|
+
);
|
|
60908
|
+
const raw2 = await res.text();
|
|
60909
|
+
if (!res.ok)
|
|
60910
|
+
throw apiError("knowledge-base upload", res, raw2, organizationId);
|
|
60911
|
+
return JSON.parse(raw2);
|
|
60912
|
+
},
|
|
60913
|
+
search: async (query, options) => {
|
|
60914
|
+
const organizationId = await client.organizationId();
|
|
60915
|
+
const res = await client.fetch(
|
|
60916
|
+
`/v2/knowledge-bases/${organizationId}/${id}/search`,
|
|
60917
|
+
{
|
|
60918
|
+
method: "POST",
|
|
60919
|
+
headers: { "Content-Type": "application/json" },
|
|
60920
|
+
body: JSON.stringify({
|
|
60921
|
+
query,
|
|
60922
|
+
...options?.limit != null ? { limit: options.limit } : {}
|
|
60923
|
+
})
|
|
60924
|
+
}
|
|
60925
|
+
);
|
|
60926
|
+
const raw2 = await res.text();
|
|
60927
|
+
if (!res.ok)
|
|
60928
|
+
throw apiError("knowledge-base search", res, raw2, organizationId);
|
|
60929
|
+
return JSON.parse(raw2);
|
|
60930
|
+
}
|
|
60931
|
+
});
|
|
60932
|
+
|
|
60933
|
+
// ../sdk/src/lint.ts
|
|
60934
|
+
var lint = async (client, input2) => {
|
|
60935
|
+
const res = await client.fetch("/v2/architect/lint", {
|
|
60936
|
+
method: "POST",
|
|
60937
|
+
headers: { "Content-Type": "application/json" },
|
|
60938
|
+
body: JSON.stringify(input2)
|
|
60939
|
+
});
|
|
60940
|
+
const raw2 = await res.text();
|
|
60941
|
+
if (!res.ok) throw apiError("lint", res, raw2, await client.organizationId());
|
|
60942
|
+
const parsed = lintResponseSchema.safeParse(
|
|
60943
|
+
(() => {
|
|
60944
|
+
try {
|
|
60945
|
+
return JSON.parse(raw2);
|
|
60946
|
+
} catch {
|
|
60947
|
+
return null;
|
|
60948
|
+
}
|
|
60949
|
+
})()
|
|
60950
|
+
);
|
|
60951
|
+
if (!parsed.success)
|
|
60952
|
+
throw new OverAIError("lint: invalid response from lint service", {
|
|
60953
|
+
status: res.status,
|
|
60954
|
+
path: responsePath(res),
|
|
60955
|
+
body: raw2,
|
|
60956
|
+
organizationId: await client.organizationId()
|
|
60957
|
+
});
|
|
60958
|
+
return parsed.data;
|
|
60959
|
+
};
|
|
60960
|
+
|
|
60961
|
+
// ../sdk/src/printablePageRender.ts
|
|
60962
|
+
var printablePageRender = (client, id) => ({
|
|
60963
|
+
render: async (options) => {
|
|
60964
|
+
const data = await client.graphql(
|
|
60965
|
+
`query SdkPrintablePageWorkspace($id: String!) { printablePage(id: $id) { workspaceId } }`,
|
|
60966
|
+
{ id }
|
|
60967
|
+
);
|
|
60968
|
+
if (data.printablePage == null)
|
|
60969
|
+
throw new Error(`Printable page ${id} not found.`);
|
|
60970
|
+
const organizationId = await client.organizationId();
|
|
60971
|
+
const res = await client.fetch(
|
|
60972
|
+
`/v2/actions/${organizationId}/${data.printablePage.workspaceId}/run`,
|
|
60973
|
+
{
|
|
60974
|
+
method: "POST",
|
|
60975
|
+
headers: { "Content-Type": "application/json" },
|
|
60976
|
+
body: JSON.stringify({
|
|
60977
|
+
actionId: "PRINTABLE_PAGE_TO_PDF",
|
|
60978
|
+
inputs: {
|
|
60979
|
+
printablePageId: id,
|
|
60980
|
+
searchParams: options?.searchParams ?? "{}",
|
|
60981
|
+
includeDiagnostics: true
|
|
60982
|
+
}
|
|
60983
|
+
}),
|
|
60984
|
+
signal: AbortSignal.timeout(options?.timeoutMs ?? 6e4)
|
|
60985
|
+
}
|
|
60986
|
+
);
|
|
60987
|
+
const raw2 = await res.text();
|
|
60988
|
+
if (!res.ok)
|
|
60989
|
+
throw apiError("printable-page render", res, raw2, organizationId);
|
|
60990
|
+
return JSON.parse(raw2);
|
|
60991
|
+
}
|
|
60992
|
+
});
|
|
60993
|
+
|
|
60994
|
+
// ../sdk/src/report.ts
|
|
60995
|
+
var report = async (client, kind, details, options) => {
|
|
60996
|
+
await client.trpc("architectIssues.report", {
|
|
60997
|
+
feedbackType: kind,
|
|
60998
|
+
detailedBugReport: details,
|
|
60999
|
+
source: options?.source ?? "cli",
|
|
61000
|
+
cliContext: options?.cliContext
|
|
61001
|
+
});
|
|
61002
|
+
};
|
|
61003
|
+
|
|
60473
61004
|
// ../common/src/random/index.ts
|
|
60474
61005
|
var UNMISTAKABLE_CHARS = "0123456789abcdefghjkmnpqrstvwxyz";
|
|
60475
61006
|
var nanoid4 = customAlphabet(UNMISTAKABLE_CHARS, 12);
|
|
@@ -60514,6 +61045,7 @@ var ID_PREFIXES = {
|
|
|
60514
61045
|
automation_email_alert: { prefix: "aes", body: 10 },
|
|
60515
61046
|
automation_error_alert_queue: { prefix: "aeaq", body: 10 },
|
|
60516
61047
|
billing_period: { prefix: "bpd", body: 12 },
|
|
61048
|
+
billing_term: { prefix: "btm", body: 12 },
|
|
60517
61049
|
browser_automation: { prefix: "bra", body: 10 },
|
|
60518
61050
|
browser_automation_run: { prefix: "brr", body: 20 },
|
|
60519
61051
|
browser_session_usage: { prefix: "bsu", body: 12 },
|
|
@@ -60785,6 +61317,301 @@ var genericResource = (client, id) => {
|
|
|
60785
61317
|
};
|
|
60786
61318
|
};
|
|
60787
61319
|
|
|
61320
|
+
// ../sdk/src/runners.ts
|
|
61321
|
+
var runnerCollection = (client) => ({
|
|
61322
|
+
/*
|
|
61323
|
+
* Two steps, same as the webapp: createMachineIdentity mints the identity
|
|
61324
|
+
* and binds it to the active org atomically — a plain createIdentity cannot
|
|
61325
|
+
* RETURN a row not yet in the caller's org — then the runner is created in
|
|
61326
|
+
* the workspace.
|
|
61327
|
+
*/
|
|
61328
|
+
create: async (input2) => {
|
|
61329
|
+
const identityResult = await client.graphql(
|
|
61330
|
+
`mutation SdkCreateMachineIdentity($name: String!) {
|
|
61331
|
+
createMachineIdentity(input: { name: $name }) {
|
|
61332
|
+
identity { id }
|
|
61333
|
+
}
|
|
61334
|
+
}`,
|
|
61335
|
+
{ name: input2.name ?? "Action Runner" }
|
|
61336
|
+
);
|
|
61337
|
+
const identityId = identityResult.createMachineIdentity?.identity?.id;
|
|
61338
|
+
if (identityId == null)
|
|
61339
|
+
throw new Error("Failed to create machine identity");
|
|
61340
|
+
const runnerResult = await client.graphql(
|
|
61341
|
+
`mutation SdkCreateActionRunner($identityId: String!, $workspaceId: String!) {
|
|
61342
|
+
createActionRunner(
|
|
61343
|
+
input: { actionRunner: { identityId: $identityId, workspaceId: $workspaceId } }
|
|
61344
|
+
) { actionRunner { id } }
|
|
61345
|
+
}`,
|
|
61346
|
+
{ identityId, workspaceId: input2.workspaceId }
|
|
61347
|
+
);
|
|
61348
|
+
const actionRunnerId = runnerResult.createActionRunner?.actionRunner?.id;
|
|
61349
|
+
if (actionRunnerId == null)
|
|
61350
|
+
throw new Error("Failed to create action runner");
|
|
61351
|
+
return { actionRunnerId, identityId };
|
|
61352
|
+
},
|
|
61353
|
+
// An explicit null in a PostGraphile condition means IS NULL, so the key is
|
|
61354
|
+
// left out when no workspace is given and the whole org lists.
|
|
61355
|
+
list: async (options) => {
|
|
61356
|
+
const data = await client.graphql(
|
|
61357
|
+
`query SdkRunnerList($condition: ActionRunnerCondition!, $first: Int!) {
|
|
61358
|
+
actionRunners(condition: $condition, first: $first) {
|
|
61359
|
+
nodes { id identity { name } workspaceId isCloud isArchived createdAt }
|
|
61360
|
+
}
|
|
61361
|
+
}`,
|
|
61362
|
+
{
|
|
61363
|
+
condition: options?.workspaceId == null ? {} : { workspaceId: options.workspaceId },
|
|
61364
|
+
first: options?.limit ?? 50
|
|
61365
|
+
}
|
|
61366
|
+
);
|
|
61367
|
+
return data.actionRunners.nodes.map((r) => ({
|
|
61368
|
+
id: r.id,
|
|
61369
|
+
name: r.identity?.name ?? null,
|
|
61370
|
+
workspaceId: r.workspaceId,
|
|
61371
|
+
kind: r.isCloud ? "cloud" : "self-hosted",
|
|
61372
|
+
archived: r.isArchived,
|
|
61373
|
+
createdAt: r.createdAt
|
|
61374
|
+
}));
|
|
61375
|
+
}
|
|
61376
|
+
});
|
|
61377
|
+
var runnerResource = (client, id) => {
|
|
61378
|
+
const enqueueAction = async (actionId, inputs) => {
|
|
61379
|
+
const organizationId = await client.organizationId();
|
|
61380
|
+
const data = await client.graphql(
|
|
61381
|
+
`query SdkResolveRunner($id: String!) {
|
|
61382
|
+
actionRunners(condition: { id: $id }, first: 1) { nodes { workspaceId } }
|
|
61383
|
+
}`,
|
|
61384
|
+
{ id }
|
|
61385
|
+
);
|
|
61386
|
+
const workspaceId = data.actionRunners.nodes[0]?.workspaceId;
|
|
61387
|
+
if (workspaceId == null) {
|
|
61388
|
+
throw new Error(
|
|
61389
|
+
`Unknown runner ${id} (or it has no workspace). Try: overai runner list`
|
|
61390
|
+
);
|
|
61391
|
+
}
|
|
61392
|
+
const res = await client.fetch(
|
|
61393
|
+
`/v2/actions/${organizationId}/${workspaceId}/run`,
|
|
61394
|
+
{
|
|
61395
|
+
method: "POST",
|
|
61396
|
+
headers: { "Content-Type": "application/json" },
|
|
61397
|
+
body: JSON.stringify({ actionId, inputs, actionRunnerId: id })
|
|
61398
|
+
}
|
|
61399
|
+
);
|
|
61400
|
+
const raw2 = await res.text();
|
|
61401
|
+
if (!res.ok) throw apiError("runner run", res, raw2, organizationId);
|
|
61402
|
+
return JSON.parse(raw2);
|
|
61403
|
+
};
|
|
61404
|
+
return {
|
|
61405
|
+
token: async (options) => {
|
|
61406
|
+
const result = await client.graphql(
|
|
61407
|
+
`mutation SdkCreateActionRunnerToken($actionRunnerId: String!, $note: String) {
|
|
61408
|
+
createActionRunnerToken(
|
|
61409
|
+
input: { actionRunnerId: $actionRunnerId, note: $note }
|
|
61410
|
+
) { result }
|
|
61411
|
+
}`,
|
|
61412
|
+
{ actionRunnerId: id, note: options?.note ?? "cli" }
|
|
61413
|
+
);
|
|
61414
|
+
const secret = result.createActionRunnerToken?.result;
|
|
61415
|
+
if (secret == null) throw new Error("Failed to mint runner token");
|
|
61416
|
+
return secret;
|
|
61417
|
+
},
|
|
61418
|
+
run: (input2) => enqueueAction("RUNNER_RUN_COMMAND", {
|
|
61419
|
+
actionRunnerId: id,
|
|
61420
|
+
interpreter: input2.interpreter ?? "shell",
|
|
61421
|
+
code: input2.code
|
|
61422
|
+
}),
|
|
61423
|
+
upload: (path) => enqueueAction("RUNNER_UPLOAD_FILE", {
|
|
61424
|
+
actionRunnerId: id,
|
|
61425
|
+
filePath: path
|
|
61426
|
+
})
|
|
61427
|
+
};
|
|
61428
|
+
};
|
|
61429
|
+
|
|
61430
|
+
// ../sdk/src/storage.ts
|
|
61431
|
+
var storageApi = (client) => ({
|
|
61432
|
+
upload: async (file2, options) => {
|
|
61433
|
+
const organizationId = await client.organizationId();
|
|
61434
|
+
const query = options.randomPrefix === false ? "?disableRandomPrefix=true" : "";
|
|
61435
|
+
const res = await client.fetch(
|
|
61436
|
+
`/v2/storage/${organizationId}/stream${query}`,
|
|
61437
|
+
{
|
|
61438
|
+
method: "POST",
|
|
61439
|
+
headers: {
|
|
61440
|
+
"Content-Type": "application/octet-stream",
|
|
61441
|
+
"x-file-name": options.name
|
|
61442
|
+
},
|
|
61443
|
+
body: file2
|
|
61444
|
+
}
|
|
61445
|
+
);
|
|
61446
|
+
if (!res.ok)
|
|
61447
|
+
throw apiError("storage upload", res, await res.text(), organizationId);
|
|
61448
|
+
const { path } = await res.json();
|
|
61449
|
+
const key = path.startsWith(`${organizationId}/`) ? path.slice(organizationId.length + 1) : path;
|
|
61450
|
+
return { key, path };
|
|
61451
|
+
},
|
|
61452
|
+
download: async (key) => {
|
|
61453
|
+
const organizationId = await client.organizationId();
|
|
61454
|
+
const res = await client.fetch(
|
|
61455
|
+
`/v2/storage/${organizationId}/${encodeURIComponent(key)}`,
|
|
61456
|
+
{ redirect: "follow" }
|
|
61457
|
+
);
|
|
61458
|
+
if (!res.ok)
|
|
61459
|
+
throw apiError("storage download", res, await res.text(), organizationId);
|
|
61460
|
+
return res;
|
|
61461
|
+
},
|
|
61462
|
+
exists: async (key) => {
|
|
61463
|
+
const organizationId = await client.organizationId();
|
|
61464
|
+
const res = await client.fetch(
|
|
61465
|
+
`/v2/storage/${organizationId}/${encodeURIComponent(key)}/exists`
|
|
61466
|
+
);
|
|
61467
|
+
if (res.status === 404) return null;
|
|
61468
|
+
if (!res.ok)
|
|
61469
|
+
throw apiError("storage exists", res, await res.text(), organizationId);
|
|
61470
|
+
return await res.json();
|
|
61471
|
+
},
|
|
61472
|
+
head: async (key, options) => {
|
|
61473
|
+
const organizationId = await client.organizationId();
|
|
61474
|
+
const res = await client.fetch(
|
|
61475
|
+
`/v2/storage/${organizationId}/${encodeURIComponent(key)}/head?numLines=${String(options?.lines ?? 50)}`
|
|
61476
|
+
);
|
|
61477
|
+
const raw2 = await res.text();
|
|
61478
|
+
if (!res.ok) throw apiError("storage head", res, raw2, organizationId);
|
|
61479
|
+
return raw2;
|
|
61480
|
+
},
|
|
61481
|
+
presign: async (key, options) => {
|
|
61482
|
+
const organizationId = await client.organizationId();
|
|
61483
|
+
const res = await client.fetch(
|
|
61484
|
+
`/v2/storage/${organizationId}/${encodeURIComponent(key)}/presign?expiresIn=${String(options?.expiresIn ?? 60 * 60 * 24 * 7)}`
|
|
61485
|
+
);
|
|
61486
|
+
const raw2 = await res.text();
|
|
61487
|
+
if (!res.ok) throw apiError("storage presign", res, raw2, organizationId);
|
|
61488
|
+
return raw2.trim();
|
|
61489
|
+
}
|
|
61490
|
+
});
|
|
61491
|
+
|
|
61492
|
+
// ../sdk/src/tableSpaceRun.ts
|
|
61493
|
+
var clusterInfo = async (client) => {
|
|
61494
|
+
const res = await client.fetch("/v2/cluster-info");
|
|
61495
|
+
const raw2 = await res.text();
|
|
61496
|
+
if (!res.ok)
|
|
61497
|
+
throw apiError("cluster-info", res, raw2, await client.organizationId());
|
|
61498
|
+
return JSON.parse(raw2);
|
|
61499
|
+
};
|
|
61500
|
+
var connectionString = async (client, tableSpaceId, secret) => {
|
|
61501
|
+
const { postgres } = await clusterInfo(client);
|
|
61502
|
+
return `postgresql://overai:${encodeURIComponent(secret)}@${postgres.host}:${String(postgres.port)}/${tableSpaceId}?sslmode=${postgres.sslMode}${postgres.sslMode === "verify-full" ? "&sslrootcert=system" : ""}`;
|
|
61503
|
+
};
|
|
61504
|
+
var tableSpaceResource = (client, id) => ({
|
|
61505
|
+
/*
|
|
61506
|
+
* The controlled /run endpoint (our auth + audit). `params` switches to the
|
|
61507
|
+
* parameterized `unsafe` shape so identifiers stay injection-safe;
|
|
61508
|
+
* ignoreCamelCase keeps real column names.
|
|
61509
|
+
*/
|
|
61510
|
+
sql: async (query, options) => {
|
|
61511
|
+
const organizationId = await client.organizationId();
|
|
61512
|
+
const res = await client.fetch(
|
|
61513
|
+
`/v2/table-spaces/${organizationId}/${id}/run`,
|
|
61514
|
+
{
|
|
61515
|
+
method: "POST",
|
|
61516
|
+
headers: { "Content-Type": "application/json" },
|
|
61517
|
+
body: JSON.stringify(
|
|
61518
|
+
options?.params == null ? { query, ignoreCamelCase: true } : { unsafe: { query, params: options.params } }
|
|
61519
|
+
)
|
|
61520
|
+
}
|
|
61521
|
+
);
|
|
61522
|
+
const raw2 = await res.text();
|
|
61523
|
+
const body = (() => {
|
|
61524
|
+
try {
|
|
61525
|
+
return JSON.parse(raw2);
|
|
61526
|
+
} catch {
|
|
61527
|
+
return null;
|
|
61528
|
+
}
|
|
61529
|
+
})();
|
|
61530
|
+
if (!res.ok || body?.ok === false)
|
|
61531
|
+
throw apiError("sql", res, raw2, organizationId);
|
|
61532
|
+
return {
|
|
61533
|
+
rows: body?.rows ?? [],
|
|
61534
|
+
rowCount: body?.rowCount ?? 0,
|
|
61535
|
+
resultSetCount: body?.resultSetCount ?? 1,
|
|
61536
|
+
durationMs: body?.durationMs ?? 0
|
|
61537
|
+
};
|
|
61538
|
+
},
|
|
61539
|
+
credentials: {
|
|
61540
|
+
create: async (input2) => {
|
|
61541
|
+
const data = await client.graphql(
|
|
61542
|
+
`mutation SdkCreateTableSpaceCredential($tableSpaceId: String!, $name: String!, $validUntil: Datetime) {
|
|
61543
|
+
createTableSpaceCredential(input: { tableSpaceId: $tableSpaceId, name: $name, validUntil: $validUntil }) { result }
|
|
61544
|
+
}`,
|
|
61545
|
+
{
|
|
61546
|
+
tableSpaceId: id,
|
|
61547
|
+
name: input2.name,
|
|
61548
|
+
validUntil: input2.validUntil?.toISOString() ?? null
|
|
61549
|
+
}
|
|
61550
|
+
);
|
|
61551
|
+
const result = data.createTableSpaceCredential?.result;
|
|
61552
|
+
if (!result) throw new Error("The server did not return a credential");
|
|
61553
|
+
return {
|
|
61554
|
+
id: result.id,
|
|
61555
|
+
secret: result.secret,
|
|
61556
|
+
connectionString: await connectionString(client, id, result.secret)
|
|
61557
|
+
};
|
|
61558
|
+
},
|
|
61559
|
+
list: async () => (await client.graphql(
|
|
61560
|
+
`query SdkTableSpaceCredentials($tableSpaceId: String!) {
|
|
61561
|
+
tableSpaceCredentials(condition: { tableSpaceId: $tableSpaceId }) {
|
|
61562
|
+
nodes { id name validUntil lastUsedAt createdAt }
|
|
61563
|
+
}
|
|
61564
|
+
}`,
|
|
61565
|
+
{ tableSpaceId: id }
|
|
61566
|
+
)).tableSpaceCredentials?.nodes ?? []
|
|
61567
|
+
}
|
|
61568
|
+
});
|
|
61569
|
+
var tableSpaceCredentialResource = (client, credentialId) => {
|
|
61570
|
+
const tableSpaceId = async () => {
|
|
61571
|
+
const data = await client.graphql(
|
|
61572
|
+
`query SdkTableSpaceCredential($id: String!) {
|
|
61573
|
+
tableSpaceCredential(id: $id) { tableSpaceId }
|
|
61574
|
+
}`,
|
|
61575
|
+
{ id: credentialId }
|
|
61576
|
+
);
|
|
61577
|
+
if (!data.tableSpaceCredential)
|
|
61578
|
+
throw new Error("Credential not found or you lack access to it");
|
|
61579
|
+
return data.tableSpaceCredential.tableSpaceId;
|
|
61580
|
+
};
|
|
61581
|
+
return {
|
|
61582
|
+
rotate: async () => {
|
|
61583
|
+
const resolvedTableSpaceId = await tableSpaceId();
|
|
61584
|
+
const data = await client.graphql(
|
|
61585
|
+
`mutation SdkRotateTableSpaceCredential($credentialId: String!) {
|
|
61586
|
+
rotateTableSpaceCredential(input: { credentialId: $credentialId }) { result }
|
|
61587
|
+
}`,
|
|
61588
|
+
{ credentialId }
|
|
61589
|
+
);
|
|
61590
|
+
const secret = data.rotateTableSpaceCredential?.result;
|
|
61591
|
+
if (!secret) throw new Error("The server did not return a credential");
|
|
61592
|
+
return {
|
|
61593
|
+
secret,
|
|
61594
|
+
connectionString: await connectionString(
|
|
61595
|
+
client,
|
|
61596
|
+
resolvedTableSpaceId,
|
|
61597
|
+
secret
|
|
61598
|
+
)
|
|
61599
|
+
};
|
|
61600
|
+
},
|
|
61601
|
+
revoke: async () => {
|
|
61602
|
+
await tableSpaceId();
|
|
61603
|
+
await client.graphql(
|
|
61604
|
+
`mutation SdkRevokeTableSpaceCredential($id: String!, $validUntil: Datetime!) {
|
|
61605
|
+
updateTableSpaceCredential(input: { id: $id, patch: { validUntil: $validUntil } }) {
|
|
61606
|
+
tableSpaceCredential { id }
|
|
61607
|
+
}
|
|
61608
|
+
}`,
|
|
61609
|
+
{ id: credentialId, validUntil: (/* @__PURE__ */ new Date()).toISOString() }
|
|
61610
|
+
);
|
|
61611
|
+
}
|
|
61612
|
+
};
|
|
61613
|
+
};
|
|
61614
|
+
|
|
60788
61615
|
// ../sdk/src/tokens.ts
|
|
60789
61616
|
var exchangeSchema = external_exports.object({ token: external_exports.string(), expiresIn: external_exports.number() });
|
|
60790
61617
|
var staticToken = (jwt2) => () => jwt2;
|
|
@@ -60885,6 +61712,17 @@ var OverAIClient = class {
|
|
|
60885
61712
|
headers.set("Authorization", `Bearer ${token}`);
|
|
60886
61713
|
return fetch(`${this.baseUrl}${path}`, { ...init, headers });
|
|
60887
61714
|
}
|
|
61715
|
+
/** The bearer the next request would send. For hosts that build their own requests, like `createEnv`. */
|
|
61716
|
+
token() {
|
|
61717
|
+
return Promise.resolve(this.#token());
|
|
61718
|
+
}
|
|
61719
|
+
/** The org the token source's JWT names; every org-scoped REST path takes it. */
|
|
61720
|
+
async organizationId() {
|
|
61721
|
+
const org = (this.#claims ?? decodeJwtClaims(await this.#token())).org;
|
|
61722
|
+
if (org == null || org === "")
|
|
61723
|
+
throw new Error("The token carries no organization claim.");
|
|
61724
|
+
return org;
|
|
61725
|
+
}
|
|
60888
61726
|
/**
|
|
60889
61727
|
* POST /v2/graphql. Throws with the server's error messages — callers (and
|
|
60890
61728
|
* agents driving them) need the actual reason, not a status code.
|
|
@@ -60971,21 +61809,68 @@ var OverAIClient = class {
|
|
|
60971
61809
|
create: (input2) => createDataFile(this, input2)
|
|
60972
61810
|
};
|
|
60973
61811
|
workspaces = workspaceCollection(this);
|
|
61812
|
+
runners = runnerCollection(this);
|
|
61813
|
+
storage = storageApi(this);
|
|
60974
61814
|
/** Its `deploy` checks deployed callers first; see `FunctionResource`. */
|
|
60975
61815
|
fn(id) {
|
|
60976
|
-
return functionResource(this, id);
|
|
61816
|
+
return { ...functionResource(this, id), ...functionRun(this, id) };
|
|
60977
61817
|
}
|
|
60978
61818
|
page(id) {
|
|
60979
61819
|
return codeResource(webPageSource(this), id);
|
|
60980
61820
|
}
|
|
60981
61821
|
printablePage(id) {
|
|
60982
|
-
return
|
|
61822
|
+
return {
|
|
61823
|
+
...codeResource(printablePageSource(this), id),
|
|
61824
|
+
...printablePageRender(this, id)
|
|
61825
|
+
};
|
|
60983
61826
|
}
|
|
60984
61827
|
automation(id) {
|
|
60985
|
-
return
|
|
61828
|
+
return {
|
|
61829
|
+
...versionedResource(automationSource(this), id),
|
|
61830
|
+
...automationRunApi(this, id)
|
|
61831
|
+
};
|
|
60986
61832
|
}
|
|
60987
61833
|
agent(id) {
|
|
60988
|
-
return
|
|
61834
|
+
return {
|
|
61835
|
+
...versionedResource(agentSource(this), id),
|
|
61836
|
+
...agentRun(this, id)
|
|
61837
|
+
};
|
|
61838
|
+
}
|
|
61839
|
+
/** A run addresses no automation, so its state is read by run id alone. */
|
|
61840
|
+
automationRunState(runId) {
|
|
61841
|
+
return automationRunState(this, runId);
|
|
61842
|
+
}
|
|
61843
|
+
tableSpace(id) {
|
|
61844
|
+
return tableSpaceResource(this, id);
|
|
61845
|
+
}
|
|
61846
|
+
tableSpaceCredential(credentialId) {
|
|
61847
|
+
return tableSpaceCredentialResource(this, credentialId);
|
|
61848
|
+
}
|
|
61849
|
+
dataFile(id) {
|
|
61850
|
+
return dataFileResource(this, id);
|
|
61851
|
+
}
|
|
61852
|
+
dataStream(id) {
|
|
61853
|
+
return dataStreamResource(this, id);
|
|
61854
|
+
}
|
|
61855
|
+
knowledgeBase(id) {
|
|
61856
|
+
return knowledgeBaseResource(this, id);
|
|
61857
|
+
}
|
|
61858
|
+
integration(id) {
|
|
61859
|
+
return integrationResource(this, id);
|
|
61860
|
+
}
|
|
61861
|
+
runner(id) {
|
|
61862
|
+
return runnerResource(this, id);
|
|
61863
|
+
}
|
|
61864
|
+
clusterInfo() {
|
|
61865
|
+
return clusterInfo(this);
|
|
61866
|
+
}
|
|
61867
|
+
/** The platform's authenticated lint, which knows the workspace's resources. */
|
|
61868
|
+
lint(input2) {
|
|
61869
|
+
return lint(this, input2);
|
|
61870
|
+
}
|
|
61871
|
+
/** Files a bug report or feature request with OverAI. */
|
|
61872
|
+
report(kind, details, options) {
|
|
61873
|
+
return report(this, kind, details, options);
|
|
60989
61874
|
}
|
|
60990
61875
|
workspace(id) {
|
|
60991
61876
|
return workspaceResource(this, id);
|
|
@@ -61279,7 +62164,6 @@ var cliClient = () => createClient({
|
|
|
61279
62164
|
baseUrl: apiBaseUrl(),
|
|
61280
62165
|
token: async () => (await getAccessToken()).token
|
|
61281
62166
|
});
|
|
61282
|
-
var v2Fetch = async (path, init) => cliClient().fetch(path, init);
|
|
61283
62167
|
var v2Error = (label, res, rawBody) => withOrgHint(apiError(label, res, rawBody, scopedOrgId()));
|
|
61284
62168
|
var ORG_HINT = "\n If it lives in another org, name that org: overai --org <ref> ... (`overai org list` shows them, `overai org alias` your shorthands).";
|
|
61285
62169
|
var withOrgHint = (error62) => {
|
|
@@ -61287,7 +62171,6 @@ var withOrgHint = (error62) => {
|
|
|
61287
62171
|
error62.message = `${error62.message}${ORG_HINT}`;
|
|
61288
62172
|
return error62;
|
|
61289
62173
|
};
|
|
61290
|
-
var userTrpcMutation = async (procedure, input2) => cliClient().trpc(procedure, input2);
|
|
61291
62174
|
|
|
61292
62175
|
// src/args.ts
|
|
61293
62176
|
import { readFileSync as readFileSync3 } from "fs";
|
|
@@ -61321,6 +62204,15 @@ var flagValue = (args, ...names) => {
|
|
|
61321
62204
|
}
|
|
61322
62205
|
return void 0;
|
|
61323
62206
|
};
|
|
62207
|
+
function integerFlag(args, name2, fallback2) {
|
|
62208
|
+
const names = typeof name2 === "string" ? [name2] : [...name2];
|
|
62209
|
+
const raw2 = flagValue(args, ...names);
|
|
62210
|
+
if (raw2 == null) return fallback2;
|
|
62211
|
+
const value = Number(raw2);
|
|
62212
|
+
if (!Number.isInteger(value))
|
|
62213
|
+
throw new Error(`${names[0] ?? ""} must be a whole number.`);
|
|
62214
|
+
return value;
|
|
62215
|
+
}
|
|
61324
62216
|
var stdinClaimedBy = null;
|
|
61325
62217
|
var readStdin = async (claimant = "stdin") => {
|
|
61326
62218
|
if (stdinClaimedBy != null) {
|
|
@@ -61481,13 +62373,21 @@ var pinOrgFromClone = () => {
|
|
|
61481
62373
|
} catch {
|
|
61482
62374
|
}
|
|
61483
62375
|
};
|
|
62376
|
+
var IGNORE_FILES = [".ignore", ".gitignore"];
|
|
62377
|
+
var IGNORE_ALL = "*\n";
|
|
61484
62378
|
var writeManifest = (root, manifest) => {
|
|
61485
|
-
|
|
62379
|
+
const dir = join3(root, MANIFEST_DIR);
|
|
62380
|
+
mkdirSync2(dir, { recursive: true });
|
|
61486
62381
|
writeFileSync2(
|
|
61487
|
-
join3(
|
|
62382
|
+
join3(dir, MANIFEST_FILE),
|
|
61488
62383
|
`${JSON.stringify(manifest, null, 2)}
|
|
61489
62384
|
`
|
|
61490
62385
|
);
|
|
62386
|
+
for (const name2 of IGNORE_FILES) {
|
|
62387
|
+
const path = join3(dir, name2);
|
|
62388
|
+
if (!existsSync2(path) || readFileSync4(path, "utf8") !== IGNORE_ALL)
|
|
62389
|
+
writeFileSync2(path, IGNORE_ALL);
|
|
62390
|
+
}
|
|
61491
62391
|
};
|
|
61492
62392
|
var basePath = (root, relPath) => join3(root, MANIFEST_DIR, BASE_DIR, relPath);
|
|
61493
62393
|
var writeSynced = (root, relPath, content) => {
|
|
@@ -61834,17 +62734,6 @@ var whoami = (args = []) => {
|
|
|
61834
62734
|
|
|
61835
62735
|
// src/commands/agent.ts
|
|
61836
62736
|
import { createInterface } from "readline";
|
|
61837
|
-
|
|
61838
|
-
// src/gql.ts
|
|
61839
|
-
var gqlRequest = async (query, variables) => {
|
|
61840
|
-
try {
|
|
61841
|
-
return await cliClient().graphql(query, variables);
|
|
61842
|
-
} catch (error62) {
|
|
61843
|
-
throw withOrgHint(error62);
|
|
61844
|
-
}
|
|
61845
|
-
};
|
|
61846
|
-
|
|
61847
|
-
// src/commands/agent.ts
|
|
61848
62737
|
var USAGE = [
|
|
61849
62738
|
"Usage:",
|
|
61850
62739
|
" overai agent generate <id> --message <text|@file|@->",
|
|
@@ -61857,210 +62746,51 @@ var generate = async (args, id) => {
|
|
|
61857
62746
|
"--message"
|
|
61858
62747
|
);
|
|
61859
62748
|
if (message == null) throw new Error("Agent generate requires --message.");
|
|
61860
|
-
const { organizationId } = await getAccessToken();
|
|
61861
|
-
const response = await v2Fetch(
|
|
61862
|
-
`/v2/agents/${organizationId}/${id}/generate/text`,
|
|
61863
|
-
{
|
|
61864
|
-
method: "POST",
|
|
61865
|
-
headers: { "Content-Type": "application/json" },
|
|
61866
|
-
body: JSON.stringify({ message })
|
|
61867
|
-
}
|
|
61868
|
-
);
|
|
61869
|
-
const raw2 = await response.text();
|
|
61870
|
-
if (!response.ok) throw v2Error("agent generate", response, raw2);
|
|
61871
62749
|
printResult(
|
|
61872
|
-
|
|
62750
|
+
await cliClient().agent(id).generate(message),
|
|
61873
62751
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
61874
62752
|
);
|
|
61875
62753
|
};
|
|
61876
|
-
var deployedVersionNumber = async (id) => {
|
|
61877
|
-
const deployed = await gqlRequest(
|
|
61878
|
-
`query CliAgentDeployedVersion($id: String!) {
|
|
61879
|
-
agentDeployedVersions(condition: { agentId: $id }) { nodes { versionNumber } }
|
|
61880
|
-
}`,
|
|
61881
|
-
{ id }
|
|
61882
|
-
);
|
|
61883
|
-
const versionNumber = deployed.agentDeployedVersions?.nodes[0]?.versionNumber;
|
|
61884
|
-
if (versionNumber == null) {
|
|
61885
|
-
throw new Error(
|
|
61886
|
-
`Agent ${id} has no deployed version; pass --version <n> to inspect a saved one.`
|
|
61887
|
-
);
|
|
61888
|
-
}
|
|
61889
|
-
return versionNumber;
|
|
61890
|
-
};
|
|
61891
62754
|
var tools = async (args, id) => {
|
|
61892
|
-
const
|
|
61893
|
-
|
|
61894
|
-
throw new Error("--version must be an integer.");
|
|
61895
|
-
}
|
|
61896
|
-
const version2 = versionFlag == null ? await deployedVersionNumber(id) : Number(versionFlag);
|
|
61897
|
-
const data = await gqlRequest(
|
|
61898
|
-
`query CliAgentTools($id: String!, $version: Int!) {
|
|
61899
|
-
agent(id: $id) {
|
|
61900
|
-
name
|
|
61901
|
-
agentVersions(first: 1, condition: { versionNumber: $version }) {
|
|
61902
|
-
nodes {
|
|
61903
|
-
versionNumber
|
|
61904
|
-
model
|
|
61905
|
-
agentVersionFunctionsByAgentIdAndVersionNumber(orderBy: [FUNCTION_ID_ASC]) {
|
|
61906
|
-
nodes { functionId function { name } }
|
|
61907
|
-
}
|
|
61908
|
-
agentVersionTableSpacesByAgentIdAndVersionNumber(orderBy: [TABLE_SPACE_ID_ASC]) {
|
|
61909
|
-
nodes { tableSpaceId accessMode }
|
|
61910
|
-
}
|
|
61911
|
-
agentVersionAgentsByAgentIdAndVersionNumber(orderBy: [ATTACHED_AGENT_ID_ASC]) {
|
|
61912
|
-
nodes { attachedAgentId }
|
|
61913
|
-
}
|
|
61914
|
-
agentVersionKnowledgeBasesByAgentIdAndVersionNumber(orderBy: [KNOWLEDGE_BASE_ID_ASC]) {
|
|
61915
|
-
nodes { knowledgeBaseId }
|
|
61916
|
-
}
|
|
61917
|
-
agentVersionBuiltinToolSetsByAgentIdAndVersionNumber(orderBy: [TOOL_SET_ASC]) {
|
|
61918
|
-
nodes { toolSet }
|
|
61919
|
-
}
|
|
61920
|
-
}
|
|
61921
|
-
}
|
|
61922
|
-
}
|
|
61923
|
-
}`,
|
|
61924
|
-
{ id, version: version2 }
|
|
61925
|
-
);
|
|
61926
|
-
if (data.agent == null) throw new Error(`Agent ${id} not found.`);
|
|
61927
|
-
const agentVersion = data.agent.agentVersions.nodes[0];
|
|
61928
|
-
if (agentVersion == null) {
|
|
61929
|
-
throw new Error(`Agent ${id} has no version ${String(version2)}.`);
|
|
61930
|
-
}
|
|
61931
|
-
const rows = [
|
|
61932
|
-
...agentVersion.agentVersionFunctionsByAgentIdAndVersionNumber.nodes.map(
|
|
61933
|
-
(link) => ({
|
|
61934
|
-
kind: "function",
|
|
61935
|
-
name: link.function?.name ?? link.functionId,
|
|
61936
|
-
detail: link.functionId
|
|
61937
|
-
})
|
|
61938
|
-
),
|
|
61939
|
-
...agentVersion.agentVersionTableSpacesByAgentIdAndVersionNumber.nodes.map(
|
|
61940
|
-
(link) => ({
|
|
61941
|
-
kind: "table space",
|
|
61942
|
-
name: link.tableSpaceId,
|
|
61943
|
-
detail: link.accessMode
|
|
61944
|
-
})
|
|
61945
|
-
),
|
|
61946
|
-
...agentVersion.agentVersionAgentsByAgentIdAndVersionNumber.nodes.map(
|
|
61947
|
-
(link) => ({
|
|
61948
|
-
kind: "sub-agent",
|
|
61949
|
-
name: link.attachedAgentId,
|
|
61950
|
-
detail: ""
|
|
61951
|
-
})
|
|
61952
|
-
),
|
|
61953
|
-
...agentVersion.agentVersionKnowledgeBasesByAgentIdAndVersionNumber.nodes.map(
|
|
61954
|
-
(link) => ({
|
|
61955
|
-
kind: "knowledge base",
|
|
61956
|
-
name: link.knowledgeBaseId,
|
|
61957
|
-
detail: ""
|
|
61958
|
-
})
|
|
61959
|
-
),
|
|
61960
|
-
...agentVersion.agentVersionBuiltinToolSetsByAgentIdAndVersionNumber.nodes.map(
|
|
61961
|
-
(link) => ({ kind: "built-in", name: link.toolSet, detail: "" })
|
|
61962
|
-
)
|
|
61963
|
-
];
|
|
62755
|
+
const version2 = integerFlag(args, ["--version", "-v"]);
|
|
62756
|
+
const result = await cliClient().agent(id).tools(version2 ?? "deployed");
|
|
61964
62757
|
const format2 = resolveFormat(flagValue(args, "-o", "--output"));
|
|
61965
62758
|
if (format2 === "json") {
|
|
61966
|
-
printResult(
|
|
61967
|
-
{
|
|
61968
|
-
agent: data.agent.name,
|
|
61969
|
-
version: agentVersion.versionNumber,
|
|
61970
|
-
model: agentVersion.model,
|
|
61971
|
-
tools: rows
|
|
61972
|
-
},
|
|
61973
|
-
format2
|
|
61974
|
-
);
|
|
62759
|
+
printResult(result, format2);
|
|
61975
62760
|
return;
|
|
61976
62761
|
}
|
|
61977
62762
|
if (format2 === "table") {
|
|
61978
62763
|
process.stdout.write(
|
|
61979
|
-
`${
|
|
62764
|
+
`${result.agent} \xB7 version ${String(result.version)} \xB7 ${result.model}
|
|
61980
62765
|
`
|
|
61981
62766
|
);
|
|
61982
62767
|
}
|
|
61983
|
-
printResult(
|
|
62768
|
+
printResult(result.tools, format2);
|
|
61984
62769
|
};
|
|
61985
|
-
var
|
|
61986
|
-
|
|
61987
|
-
|
|
61988
|
-
|
|
61989
|
-
|
|
61990
|
-
|
|
61991
|
-
event
|
|
61992
|
-
|
|
61993
|
-
return;
|
|
61994
|
-
}
|
|
61995
|
-
if (event.type === "text-delta" && event.delta != null) {
|
|
61996
|
-
process.stdout.write(event.delta);
|
|
61997
|
-
}
|
|
61998
|
-
if (event.type === "error") {
|
|
61999
|
-
process.stderr.write(`
|
|
62770
|
+
var send = async (agent, message, conversationId) => {
|
|
62771
|
+
const response = await agent.chat(
|
|
62772
|
+
[{ role: "user", parts: [{ type: "text", text: message }] }],
|
|
62773
|
+
{ conversationId }
|
|
62774
|
+
);
|
|
62775
|
+
for await (const event of agentStreamEvents(response)) {
|
|
62776
|
+
if (event.type === "text-delta") process.stdout.write(event.delta);
|
|
62777
|
+
else process.stderr.write(`
|
|
62000
62778
|
${event.errorText ?? "agent turn failed"}
|
|
62001
62779
|
`);
|
|
62002
62780
|
}
|
|
62003
|
-
};
|
|
62004
|
-
var streamReply = async (response) => {
|
|
62005
|
-
const body = response.body;
|
|
62006
|
-
if (body == null) return;
|
|
62007
|
-
const decoder = new TextDecoder();
|
|
62008
|
-
let buffer = "";
|
|
62009
|
-
for await (const chunk of body) {
|
|
62010
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
62011
|
-
const lines = buffer.split("\n");
|
|
62012
|
-
buffer = lines.pop() ?? "";
|
|
62013
|
-
lines.forEach(printStreamLine);
|
|
62014
|
-
}
|
|
62015
|
-
printStreamLine(buffer + decoder.decode());
|
|
62016
|
-
};
|
|
62017
|
-
var send = async (organizationId, id, message, conversationId) => {
|
|
62018
|
-
const response = await v2Fetch(`/v2/agents/${organizationId}/${id}`, {
|
|
62019
|
-
method: "POST",
|
|
62020
|
-
headers: { "Content-Type": "application/json" },
|
|
62021
|
-
body: JSON.stringify({
|
|
62022
|
-
messages: [{ role: "user", parts: [{ type: "text", text: message }] }],
|
|
62023
|
-
conversationId
|
|
62024
|
-
})
|
|
62025
|
-
});
|
|
62026
|
-
if (!response.ok) {
|
|
62027
|
-
throw v2Error("agent chat", response, await response.text());
|
|
62028
|
-
}
|
|
62029
|
-
await streamReply(response);
|
|
62030
62781
|
process.stdout.write("\n");
|
|
62031
62782
|
};
|
|
62032
|
-
var createConversation = async (id, firstMessage) => {
|
|
62033
|
-
const versionNumber = await deployedVersionNumber(id);
|
|
62034
|
-
const created = await gqlRequest(
|
|
62035
|
-
`mutation CliCreateAgentConversation($input: CreateAgentConversationInput!) {
|
|
62036
|
-
createAgentConversation(input: $input) { agentConversation { id } }
|
|
62037
|
-
}`,
|
|
62038
|
-
{
|
|
62039
|
-
input: {
|
|
62040
|
-
agentConversation: {
|
|
62041
|
-
agentId: id,
|
|
62042
|
-
versionNumber,
|
|
62043
|
-
title: firstMessage.length > 50 ? `${firstMessage.slice(0, 47)}...` : firstMessage
|
|
62044
|
-
}
|
|
62045
|
-
}
|
|
62046
|
-
}
|
|
62047
|
-
);
|
|
62048
|
-
const conversationId = created.createAgentConversation?.agentConversation?.id;
|
|
62049
|
-
if (conversationId == null)
|
|
62050
|
-
throw new Error("Failed to create a conversation.");
|
|
62051
|
-
return conversationId;
|
|
62052
|
-
};
|
|
62053
62783
|
var chat = async (args, id) => {
|
|
62054
|
-
const
|
|
62784
|
+
const agent = cliClient().agent(id);
|
|
62055
62785
|
let conversationId = flagValue(args, "--conversation", "-c") ?? null;
|
|
62056
62786
|
const single = await readValue(
|
|
62057
62787
|
flagValue(args, "--message", "-m"),
|
|
62058
62788
|
"--message"
|
|
62059
62789
|
);
|
|
62060
62790
|
if (single != null) {
|
|
62061
|
-
conversationId ??= await createConversation(
|
|
62791
|
+
conversationId ??= await agent.createConversation(single);
|
|
62062
62792
|
try {
|
|
62063
|
-
await send(
|
|
62793
|
+
await send(agent, single, conversationId);
|
|
62064
62794
|
} finally {
|
|
62065
62795
|
process.stderr.write(`Conversation: ${conversationId}
|
|
62066
62796
|
`);
|
|
@@ -62087,11 +62817,12 @@ var chat = async (args, id) => {
|
|
|
62087
62817
|
continue;
|
|
62088
62818
|
}
|
|
62089
62819
|
try {
|
|
62090
|
-
conversationId ??= await createConversation(
|
|
62091
|
-
await send(
|
|
62820
|
+
conversationId ??= await agent.createConversation(message);
|
|
62821
|
+
await send(agent, message, conversationId);
|
|
62092
62822
|
} catch (error62) {
|
|
62823
|
+
const hinted = withOrgHint(error62);
|
|
62093
62824
|
process.stderr.write(
|
|
62094
|
-
`${
|
|
62825
|
+
`${hinted instanceof Error ? hinted.message : String(hinted)}
|
|
62095
62826
|
`
|
|
62096
62827
|
);
|
|
62097
62828
|
}
|
|
@@ -62123,53 +62854,24 @@ var runAgent = async (args) => {
|
|
|
62123
62854
|
|
|
62124
62855
|
// src/commands/automation.ts
|
|
62125
62856
|
var runRuns = async (automationId, args) => {
|
|
62126
|
-
const limit2 = Number(flagValue(args, "--limit") ?? 20);
|
|
62127
|
-
const data = await gqlRequest(
|
|
62128
|
-
`query CliAutomationRuns($automationId: String!, $first: Int!) {
|
|
62129
|
-
automationRuns(condition: { automationId: $automationId }, orderBy: [STARTED_AT_DESC], first: $first) {
|
|
62130
|
-
nodes { id startedAt endedAt errored isCancelled manuallyTriggered version { num } }
|
|
62131
|
-
}
|
|
62132
|
-
}`,
|
|
62133
|
-
// Over-fetch when status-filtering so --failed still fills the limit.
|
|
62134
|
-
{
|
|
62135
|
-
automationId,
|
|
62136
|
-
first: args.includes("--failed") || args.includes("--running") ? limit2 * 5 : limit2
|
|
62137
|
-
}
|
|
62138
|
-
);
|
|
62139
|
-
let runs = data.automationRuns.nodes;
|
|
62140
|
-
if (args.includes("--failed")) runs = runs.filter((r) => r.errored);
|
|
62141
|
-
if (args.includes("--running")) {
|
|
62142
|
-
runs = runs.filter((r) => r.endedAt == null && !r.isCancelled);
|
|
62143
|
-
}
|
|
62144
62857
|
printResult(
|
|
62145
|
-
|
|
62146
|
-
|
|
62147
|
-
|
|
62148
|
-
|
|
62149
|
-
|
|
62150
|
-
status: r.errored ? "errored" : r.isCancelled ? "cancelled" : r.endedAt == null ? "running" : "ok",
|
|
62151
|
-
manual: r.manuallyTriggered
|
|
62152
|
-
})),
|
|
62858
|
+
await cliClient().automation(automationId).runs({
|
|
62859
|
+
limit: integerFlag(args, "--limit", 20),
|
|
62860
|
+
failed: args.includes("--failed"),
|
|
62861
|
+
running: args.includes("--running")
|
|
62862
|
+
}),
|
|
62153
62863
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62154
62864
|
);
|
|
62155
62865
|
};
|
|
62156
62866
|
var runState = async (runId, args) => {
|
|
62157
|
-
const
|
|
62158
|
-
`query CliAutomationRunState($id: String!) {
|
|
62159
|
-
automationRun(id: $id) { state }
|
|
62160
|
-
}`,
|
|
62161
|
-
{ id: runId }
|
|
62162
|
-
);
|
|
62163
|
-
if (data.automationRun == null) throw new Error(`Run ${runId} not found.`);
|
|
62867
|
+
const state = await cliClient().automationRunState(runId);
|
|
62164
62868
|
const node2 = flagValue(args, "--node");
|
|
62165
|
-
const state = data.automationRun.state ?? {};
|
|
62166
62869
|
printResult(
|
|
62167
62870
|
node2 != null ? { [node2]: state[node2] ?? "(no state for this node)" } : state,
|
|
62168
62871
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62169
62872
|
);
|
|
62170
62873
|
};
|
|
62171
62874
|
var runTrigger = async (automationId, args) => {
|
|
62172
|
-
const { organizationId } = await getAccessToken();
|
|
62173
62875
|
const body = {};
|
|
62174
62876
|
if (args.includes("-")) {
|
|
62175
62877
|
Object.assign(
|
|
@@ -62184,18 +62886,10 @@ var runTrigger = async (automationId, args) => {
|
|
|
62184
62886
|
if (eq > 0) body[pair.slice(0, eq)] = pair.slice(eq + 1);
|
|
62185
62887
|
}
|
|
62186
62888
|
}
|
|
62187
|
-
|
|
62188
|
-
|
|
62189
|
-
|
|
62190
|
-
method: "POST",
|
|
62191
|
-
headers: { "Content-Type": "application/json" },
|
|
62192
|
-
body: JSON.stringify(body)
|
|
62193
|
-
}
|
|
62889
|
+
printResult(
|
|
62890
|
+
await cliClient().automation(automationId).run(body),
|
|
62891
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62194
62892
|
);
|
|
62195
|
-
const raw2 = await res.text();
|
|
62196
|
-
if (!res.ok) throw v2Error("automation run", res, raw2);
|
|
62197
|
-
const responseBody = JSON.parse(raw2);
|
|
62198
|
-
printResult(responseBody, resolveFormat(flagValue(args, "-o", "--output")));
|
|
62199
62893
|
};
|
|
62200
62894
|
var runAutomation = async (args) => {
|
|
62201
62895
|
const [sub, id, ...rest] = args;
|
|
@@ -62300,29 +62994,7 @@ var adapterFor = (type) => {
|
|
|
62300
62994
|
};
|
|
62301
62995
|
|
|
62302
62996
|
// src/commands/runner.ts
|
|
62303
|
-
var createActionRunner =
|
|
62304
|
-
const identityResult = await gqlRequest(
|
|
62305
|
-
`mutation CliCreateMachineIdentity($name: String!) {
|
|
62306
|
-
createMachineIdentity(input: { name: $name }) {
|
|
62307
|
-
identity { id }
|
|
62308
|
-
}
|
|
62309
|
-
}`,
|
|
62310
|
-
{ name: name2 }
|
|
62311
|
-
);
|
|
62312
|
-
const identityId = identityResult.createMachineIdentity?.identity?.id;
|
|
62313
|
-
if (identityId == null) throw new Error("Failed to create machine identity");
|
|
62314
|
-
const runnerResult = await gqlRequest(
|
|
62315
|
-
`mutation CliCreateActionRunner($identityId: String!, $workspaceId: String!) {
|
|
62316
|
-
createActionRunner(
|
|
62317
|
-
input: { actionRunner: { identityId: $identityId, workspaceId: $workspaceId } }
|
|
62318
|
-
) { actionRunner { id } }
|
|
62319
|
-
}`,
|
|
62320
|
-
{ identityId, workspaceId }
|
|
62321
|
-
);
|
|
62322
|
-
const actionRunnerId = runnerResult.createActionRunner?.actionRunner?.id;
|
|
62323
|
-
if (actionRunnerId == null) throw new Error("Failed to create action runner");
|
|
62324
|
-
return { actionRunnerId, identityId };
|
|
62325
|
-
};
|
|
62997
|
+
var createActionRunner = (workspaceId, name2) => cliClient().runners.create({ workspaceId, name: name2 });
|
|
62326
62998
|
var runCreate = async (workspaceId, args) => {
|
|
62327
62999
|
const name2 = flagValue(args, "--name") ?? "Action Runner";
|
|
62328
63000
|
printResult(
|
|
@@ -62331,53 +63003,12 @@ var runCreate = async (workspaceId, args) => {
|
|
|
62331
63003
|
);
|
|
62332
63004
|
};
|
|
62333
63005
|
var runToken = async (runnerId, args) => {
|
|
62334
|
-
const
|
|
62335
|
-
const result = await gqlRequest(
|
|
62336
|
-
`mutation CliCreateActionRunnerToken($actionRunnerId: String!, $note: String) {
|
|
62337
|
-
createActionRunnerToken(
|
|
62338
|
-
input: { actionRunnerId: $actionRunnerId, note: $note }
|
|
62339
|
-
) { result }
|
|
62340
|
-
}`,
|
|
62341
|
-
{ actionRunnerId: runnerId, note }
|
|
62342
|
-
);
|
|
62343
|
-
const secret = result.createActionRunnerToken?.result;
|
|
62344
|
-
if (secret == null) throw new Error("Failed to mint runner token");
|
|
63006
|
+
const secret = await cliClient().runner(runnerId).token({ note: flagValue(args, "--note") ?? "cli" });
|
|
62345
63007
|
printResult(
|
|
62346
63008
|
{ runnerId, secret },
|
|
62347
63009
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62348
63010
|
);
|
|
62349
63011
|
};
|
|
62350
|
-
var resolveWorkspaceId = async (runnerId) => {
|
|
62351
|
-
const data = await gqlRequest(
|
|
62352
|
-
`query CliResolveRunner($id: String!) {
|
|
62353
|
-
actionRunners(condition: { id: $id }, first: 1) { nodes { workspaceId } }
|
|
62354
|
-
}`,
|
|
62355
|
-
{ id: runnerId }
|
|
62356
|
-
);
|
|
62357
|
-
const workspaceId = data.actionRunners.nodes[0]?.workspaceId;
|
|
62358
|
-
if (workspaceId == null) {
|
|
62359
|
-
throw new Error(
|
|
62360
|
-
`Unknown runner ${runnerId} (or it has no workspace). Try: overai runner list`
|
|
62361
|
-
);
|
|
62362
|
-
}
|
|
62363
|
-
return workspaceId;
|
|
62364
|
-
};
|
|
62365
|
-
var enqueueAction = async (runnerId, actionId, inputs, args) => {
|
|
62366
|
-
const { organizationId } = await getAccessToken();
|
|
62367
|
-
const workspaceId = await resolveWorkspaceId(runnerId);
|
|
62368
|
-
const res = await v2Fetch(
|
|
62369
|
-
`/v2/actions/${organizationId}/${workspaceId}/run`,
|
|
62370
|
-
{
|
|
62371
|
-
method: "POST",
|
|
62372
|
-
headers: { "Content-Type": "application/json" },
|
|
62373
|
-
body: JSON.stringify({ actionId, inputs, actionRunnerId: runnerId })
|
|
62374
|
-
}
|
|
62375
|
-
);
|
|
62376
|
-
const raw2 = await res.text();
|
|
62377
|
-
if (!res.ok) throw v2Error("runner run", res, raw2);
|
|
62378
|
-
const body = JSON.parse(raw2);
|
|
62379
|
-
printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
|
|
62380
|
-
};
|
|
62381
63012
|
var runRun = async (runnerId, args) => {
|
|
62382
63013
|
const code = await readValue(flagValue(args, "--code"), "--code") ?? (process.stdin.isTTY ? "" : (await readStdin("the code")).trim());
|
|
62383
63014
|
if (code.length === 0) {
|
|
@@ -62389,48 +63020,30 @@ var runRun = async (runnerId, args) => {
|
|
|
62389
63020
|
if (interpreter !== "shell" && interpreter !== "powershell") {
|
|
62390
63021
|
throw new Error("--interpreter must be 'shell' or 'powershell'.");
|
|
62391
63022
|
}
|
|
62392
|
-
|
|
62393
|
-
runnerId,
|
|
62394
|
-
"
|
|
62395
|
-
{ actionRunnerId: runnerId, interpreter, code },
|
|
62396
|
-
args
|
|
62397
|
-
);
|
|
62398
|
-
};
|
|
62399
|
-
var runUpload = async (runnerId, args) => {
|
|
62400
|
-
const path = flagValue(args, "--path");
|
|
62401
|
-
if (path == null || path.length === 0) {
|
|
62402
|
-
throw new Error("Provide a file with --path '<path>'.");
|
|
62403
|
-
}
|
|
62404
|
-
await enqueueAction(
|
|
62405
|
-
runnerId,
|
|
62406
|
-
"RUNNER_UPLOAD_FILE",
|
|
62407
|
-
{ actionRunnerId: runnerId, filePath: path },
|
|
62408
|
-
args
|
|
63023
|
+
printResult(
|
|
63024
|
+
await cliClient().runner(runnerId).run({ code, interpreter }),
|
|
63025
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62409
63026
|
);
|
|
62410
63027
|
};
|
|
62411
|
-
var
|
|
62412
|
-
const
|
|
62413
|
-
|
|
62414
|
-
|
|
62415
|
-
|
|
62416
|
-
|
|
62417
|
-
|
|
62418
|
-
}
|
|
62419
|
-
}`,
|
|
62420
|
-
{ workspaceId: workspaceId ?? null, first: limit2 }
|
|
62421
|
-
);
|
|
62422
|
-
printResult(
|
|
62423
|
-
data.actionRunners.nodes.map((r) => ({
|
|
62424
|
-
id: r.id,
|
|
62425
|
-
name: r.identity?.name ?? null,
|
|
62426
|
-
workspaceId: r.workspaceId,
|
|
62427
|
-
kind: r.isCloud ? "cloud" : "self-hosted",
|
|
62428
|
-
archived: r.isArchived,
|
|
62429
|
-
createdAt: r.createdAt
|
|
62430
|
-
})),
|
|
63028
|
+
var runUpload = async (runnerId, args) => {
|
|
63029
|
+
const path = flagValue(args, "--path");
|
|
63030
|
+
if (path == null || path.length === 0) {
|
|
63031
|
+
throw new Error("Provide a file with --path '<path>'.");
|
|
63032
|
+
}
|
|
63033
|
+
printResult(
|
|
63034
|
+
await cliClient().runner(runnerId).upload(path),
|
|
62431
63035
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
62432
63036
|
);
|
|
62433
63037
|
};
|
|
63038
|
+
var runList = async (args) => {
|
|
63039
|
+
const workspaceId = args.find((a) => !a.startsWith("-"));
|
|
63040
|
+
const limit2 = integerFlag(args, "--limit", 50);
|
|
63041
|
+
const runners = await cliClient().runners.list({
|
|
63042
|
+
...workspaceId != null ? { workspaceId } : {},
|
|
63043
|
+
limit: limit2
|
|
63044
|
+
});
|
|
63045
|
+
printResult(runners, resolveFormat(flagValue(args, "-o", "--output")));
|
|
63046
|
+
};
|
|
62434
63047
|
var USAGE2 = "Usage: overai runner create <workspaceId> [--name <name>]\n overai runner token <runnerId> [--note <note>]\n overai runner run <runnerId> [--interpreter shell|powershell] --code '<code>'\n overai runner upload <runnerId> --path '<path>'\n overai runner list [workspaceId] [--limit <n>]\n";
|
|
62435
63048
|
var runRunner = async (args) => {
|
|
62436
63049
|
const [sub, id, ...rest] = args;
|
|
@@ -62574,29 +63187,26 @@ var runCreate2 = async (args) => {
|
|
|
62574
63187
|
};
|
|
62575
63188
|
|
|
62576
63189
|
// src/commands/dataFile.ts
|
|
62577
|
-
import {
|
|
63190
|
+
import { openAsBlob, writeFileSync as writeFileSync3 } from "fs";
|
|
62578
63191
|
var runDataFile = async (args) => {
|
|
62579
63192
|
const [operation, id, path] = args;
|
|
62580
63193
|
if (id == null || !["upload", "download", "head"].includes(operation ?? "")) {
|
|
62581
|
-
throw new Error(
|
|
63194
|
+
throw new Error(
|
|
63195
|
+
"Usage: overai data-file upload <id> <path> [-m <message>] | data-file download <id> [path|-] | data-file head <id> [--lines N]"
|
|
63196
|
+
);
|
|
62582
63197
|
}
|
|
62583
|
-
const
|
|
63198
|
+
const dataFile = cliClient().dataFile(id);
|
|
62584
63199
|
if (operation === "upload") {
|
|
62585
|
-
if (path == null || path === "-")
|
|
62586
|
-
|
|
62587
|
-
|
|
62588
|
-
fileSize: statSync2(path).size,
|
|
63200
|
+
if (path == null || path === "-")
|
|
63201
|
+
throw new Error("Upload requires a file path.");
|
|
63202
|
+
await dataFile.upload(await openAsBlob(path), {
|
|
62589
63203
|
message: flagValue(args, "-m", "--message") ?? ""
|
|
62590
63204
|
});
|
|
62591
|
-
const response2 = await fetch(url2, { method: "PUT", body: readFileSync5(path) });
|
|
62592
|
-
if (!response2.ok) throw v2Error("data-file upload", response2, await response2.text());
|
|
62593
63205
|
process.stdout.write(`${id}
|
|
62594
63206
|
`);
|
|
62595
63207
|
return;
|
|
62596
63208
|
}
|
|
62597
|
-
const
|
|
62598
|
-
const response = await v2Fetch(`/v2/data-files/${organizationId}/${id}${suffix}`, { redirect: "follow" });
|
|
62599
|
-
if (!response.ok) throw v2Error(`data-file ${String(operation)}`, response, await response.text());
|
|
63209
|
+
const response = operation === "head" ? await dataFile.head({ lines: integerFlag(args, "--lines", 50) }) : await dataFile.read();
|
|
62600
63210
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
62601
63211
|
if (path != null && path !== "-") writeFileSync3(path, bytes);
|
|
62602
63212
|
else process.stdout.write(bytes);
|
|
@@ -62606,40 +63216,39 @@ var runDataFile = async (args) => {
|
|
|
62606
63216
|
var runDataStream = async (args) => {
|
|
62607
63217
|
const [operation, id] = args;
|
|
62608
63218
|
if (id == null || operation !== "append" && operation !== "query") {
|
|
62609
|
-
throw new Error(
|
|
63219
|
+
throw new Error(
|
|
63220
|
+
"Usage: overai data-stream append <id> <json|@file|@-> | data-stream query <id> --start <date> --end <date> [--query <filter>] [--limit N]"
|
|
63221
|
+
);
|
|
62610
63222
|
}
|
|
62611
|
-
const
|
|
63223
|
+
const dataStream = cliClient().dataStream(id);
|
|
62612
63224
|
if (operation === "append") {
|
|
62613
|
-
const
|
|
62614
|
-
if (
|
|
63225
|
+
const raw2 = await readValue(args[2], "data stream input");
|
|
63226
|
+
if (raw2 == null)
|
|
63227
|
+
throw new Error("Data stream append requires JSON, @<file>, or @-.");
|
|
62615
63228
|
const parsed = (() => {
|
|
62616
63229
|
try {
|
|
62617
|
-
return JSON.parse(
|
|
63230
|
+
return JSON.parse(raw2);
|
|
62618
63231
|
} catch {
|
|
62619
63232
|
throw new Error("Data stream input must be valid JSON.");
|
|
62620
63233
|
}
|
|
62621
63234
|
})();
|
|
62622
|
-
|
|
62623
|
-
|
|
62624
|
-
|
|
62625
|
-
|
|
62626
|
-
});
|
|
62627
|
-
const appended = await response2.text();
|
|
62628
|
-
if (!response2.ok) throw v2Error("data-stream append", response2, appended);
|
|
62629
|
-
const body2 = JSON.parse(appended);
|
|
62630
|
-
printResult(body2, resolveFormat(flagValue(args, "-o", "--output")));
|
|
63235
|
+
printResult(
|
|
63236
|
+
await dataStream.append(parsed),
|
|
63237
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
63238
|
+
);
|
|
62631
63239
|
return;
|
|
62632
63240
|
}
|
|
62633
63241
|
const start = flagValue(args, "--start");
|
|
62634
63242
|
const end = flagValue(args, "--end");
|
|
62635
|
-
if (start == null || end == null)
|
|
62636
|
-
|
|
62637
|
-
const limit2 =
|
|
62638
|
-
|
|
62639
|
-
|
|
62640
|
-
|
|
62641
|
-
|
|
62642
|
-
|
|
63243
|
+
if (start == null || end == null)
|
|
63244
|
+
throw new Error("Data stream query requires --start and --end.");
|
|
63245
|
+
const limit2 = integerFlag(args, "--limit");
|
|
63246
|
+
const body = await dataStream.query({
|
|
63247
|
+
startAt: start,
|
|
63248
|
+
endAt: end,
|
|
63249
|
+
query: flagValue(args, "--query") ?? "",
|
|
63250
|
+
...limit2 != null ? { limit: limit2 } : {}
|
|
63251
|
+
});
|
|
62643
63252
|
printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
|
|
62644
63253
|
};
|
|
62645
63254
|
|
|
@@ -62654,12 +63263,21 @@ import {
|
|
|
62654
63263
|
existsSync as existsSync3,
|
|
62655
63264
|
lstatSync,
|
|
62656
63265
|
mkdirSync as mkdirSync3,
|
|
62657
|
-
readFileSync as
|
|
63266
|
+
readFileSync as readFileSync5,
|
|
62658
63267
|
unlinkSync,
|
|
62659
63268
|
writeFileSync as writeFileSync4
|
|
62660
63269
|
} from "fs";
|
|
62661
63270
|
import { join as join4, resolve as resolve3 } from "path";
|
|
62662
63271
|
|
|
63272
|
+
// src/gql.ts
|
|
63273
|
+
var gqlRequest = async (query, variables) => {
|
|
63274
|
+
try {
|
|
63275
|
+
return await cliClient().graphql(query, variables);
|
|
63276
|
+
} catch (error62) {
|
|
63277
|
+
throw withOrgHint(error62);
|
|
63278
|
+
}
|
|
63279
|
+
};
|
|
63280
|
+
|
|
62663
63281
|
// src/workspace/tree.ts
|
|
62664
63282
|
var fetchWorkspaceChildren = async (id) => {
|
|
62665
63283
|
const children = [];
|
|
@@ -62724,7 +63342,7 @@ var runClone = async (args, isShallow = false) => {
|
|
|
62724
63342
|
`${root} is already a cloned workspace. Use \`overai pull\` to refresh.`
|
|
62725
63343
|
);
|
|
62726
63344
|
}
|
|
62727
|
-
const partialCloneWorkspaceId = existsSync3(cloneMarker) ?
|
|
63345
|
+
const partialCloneWorkspaceId = existsSync3(cloneMarker) ? readFileSync5(cloneMarker, "utf8").trim() : null;
|
|
62728
63346
|
if (partialCloneWorkspaceId != null && partialCloneWorkspaceId !== workspaceId) {
|
|
62729
63347
|
throw new Error(
|
|
62730
63348
|
`${root} contains an incomplete clone of ${partialCloneWorkspaceId}. Retry that workspace or choose another directory.`
|
|
@@ -62742,7 +63360,7 @@ var runClone = async (args, isShallow = false) => {
|
|
|
62742
63360
|
if (entry.root !== root && existsSync3(entry.root)) {
|
|
62743
63361
|
if (lstatSync(entry.root).isSymbolicLink())
|
|
62744
63362
|
throw new Error(`Refusing to clone into symbolic link ${entry.root}.`);
|
|
62745
|
-
const savedId = completed ? readManifest(entry.root).workspaceId : existsSync3(marker) ?
|
|
63363
|
+
const savedId = completed ? readManifest(entry.root).workspaceId : existsSync3(marker) ? readFileSync5(marker, "utf8").trim() : null;
|
|
62746
63364
|
if (partialCloneWorkspaceId !== workspaceId || savedId !== entry.workspace.id)
|
|
62747
63365
|
throw new Error(
|
|
62748
63366
|
`${entry.root} already exists. Choose another clone directory.`
|
|
@@ -63261,7 +63879,7 @@ var runDev = async (args) => {
|
|
|
63261
63879
|
clearTimeout(timer);
|
|
63262
63880
|
});
|
|
63263
63881
|
});
|
|
63264
|
-
const port =
|
|
63882
|
+
const port = integerFlag(args, "--port", 4820);
|
|
63265
63883
|
await new Promise((resolve4, reject2) => {
|
|
63266
63884
|
server.once("error", reject2);
|
|
63267
63885
|
server.listen(port, "127.0.0.1", resolve4);
|
|
@@ -63309,54 +63927,16 @@ var runLogs = async (args) => {
|
|
|
63309
63927
|
);
|
|
63310
63928
|
}
|
|
63311
63929
|
const executionId = flagValue(args, "--execution");
|
|
63930
|
+
const fn2 = cliClient().fn(functionId);
|
|
63931
|
+
const fmt = resolveFormat(flagValue(args, "-o", "--output"));
|
|
63312
63932
|
if (executionId == null) {
|
|
63313
|
-
const limit2 = Number(flagValue(args, "--limit") ?? 20);
|
|
63314
|
-
const data2 = await gqlRequest(
|
|
63315
|
-
`query CliFunctionExecutions($functionId: String!, $first: Int!) {
|
|
63316
|
-
functionExecutions(condition: { functionId: $functionId }, orderBy: [CREATED_AT_DESC], first: $first) {
|
|
63317
|
-
nodes { id createdAt httpStatusCode executionTime requestMethod requestPath versionNumber }
|
|
63318
|
-
}
|
|
63319
|
-
}`,
|
|
63320
|
-
{ functionId, first: limit2 }
|
|
63321
|
-
);
|
|
63322
63933
|
printResult(
|
|
63323
|
-
|
|
63324
|
-
|
|
63934
|
+
await fn2.executions({ limit: integerFlag(args, "--limit", 20) }),
|
|
63935
|
+
fmt
|
|
63325
63936
|
);
|
|
63326
63937
|
return;
|
|
63327
63938
|
}
|
|
63328
|
-
|
|
63329
|
-
`query CliFunctionExecution($functionId: String!, $id: String!) {
|
|
63330
|
-
functionExecutions(condition: { functionId: $functionId, id: $id }, first: 1) {
|
|
63331
|
-
nodes { id summary createdAt httpStatusCode executionTime versionNumber logsUrl inputBodyUrl outputBodyUrl }
|
|
63332
|
-
}
|
|
63333
|
-
}`,
|
|
63334
|
-
{ functionId, id: executionId }
|
|
63335
|
-
);
|
|
63336
|
-
const execution = data.functionExecutions.nodes[0];
|
|
63337
|
-
if (execution == null) throw new Error(`Execution ${executionId} not found.`);
|
|
63338
|
-
const fetchText = async (url2) => url2 == null ? null : await fetch(url2).then((r) => r.ok ? r.text() : null);
|
|
63339
|
-
const [logs, input2, output2] = await Promise.all([
|
|
63340
|
-
fetchText(execution.logsUrl),
|
|
63341
|
-
fetchText(execution.inputBodyUrl),
|
|
63342
|
-
fetchText(execution.outputBodyUrl)
|
|
63343
|
-
]);
|
|
63344
|
-
const fmt = resolveFormat(flagValue(args, "-o", "--output"));
|
|
63345
|
-
printResult(
|
|
63346
|
-
{
|
|
63347
|
-
id: execution.id,
|
|
63348
|
-
createdAt: execution.createdAt,
|
|
63349
|
-
httpStatusCode: execution.httpStatusCode,
|
|
63350
|
-
executionTime: execution.executionTime,
|
|
63351
|
-
versionNumber: execution.versionNumber,
|
|
63352
|
-
summary: execution.summary,
|
|
63353
|
-
input: input2,
|
|
63354
|
-
output: output2,
|
|
63355
|
-
logs
|
|
63356
|
-
},
|
|
63357
|
-
// A single nested record reads better as JSON than a 1-row table.
|
|
63358
|
-
fmt === "table" ? "json" : fmt
|
|
63359
|
-
);
|
|
63939
|
+
printResult(await fn2.execution(executionId), fmt === "table" ? "json" : fmt);
|
|
63360
63940
|
};
|
|
63361
63941
|
var runFn = async (args) => {
|
|
63362
63942
|
if (args[0] === "logs") return runLogs(args.slice(1));
|
|
@@ -63367,8 +63947,6 @@ var runFn = async (args) => {
|
|
|
63367
63947
|
);
|
|
63368
63948
|
}
|
|
63369
63949
|
const method = (flagValue(args, "--method") ?? "POST").toUpperCase();
|
|
63370
|
-
const rawPath = flagValue(args, "--path") ?? "";
|
|
63371
|
-
const subPath = rawPath && !rawPath.startsWith("/") ? `/${rawPath}` : rawPath;
|
|
63372
63950
|
const sendsBody = !["GET", "HEAD", "DELETE"].includes(method);
|
|
63373
63951
|
if (!sendsBody && (args.includes("--input") || args.includes("-"))) {
|
|
63374
63952
|
process.stderr.write(
|
|
@@ -63376,16 +63954,12 @@ var runFn = async (args) => {
|
|
|
63376
63954
|
`
|
|
63377
63955
|
);
|
|
63378
63956
|
}
|
|
63379
|
-
const
|
|
63380
|
-
|
|
63381
|
-
|
|
63382
|
-
|
|
63383
|
-
|
|
63384
|
-
|
|
63385
|
-
headers: sendsBody ? { "Content-Type": "application/json" } : {},
|
|
63386
|
-
body: sendsBody ? JSON.stringify(input2) : void 0
|
|
63387
|
-
}
|
|
63388
|
-
);
|
|
63957
|
+
const res = await cliClient().fn(functionId).call({
|
|
63958
|
+
method,
|
|
63959
|
+
path: flagValue(args, "--path"),
|
|
63960
|
+
headers: sendsBody ? { "Content-Type": "application/json" } : {},
|
|
63961
|
+
body: sendsBody ? JSON.stringify(await collectInput(args)) : void 0
|
|
63962
|
+
});
|
|
63389
63963
|
const executionId = res.headers.get("x-execution-id");
|
|
63390
63964
|
if (executionId != null) {
|
|
63391
63965
|
process.stderr.write(`execution: ${executionId}
|
|
@@ -63398,11 +63972,11 @@ var runFn = async (args) => {
|
|
|
63398
63972
|
};
|
|
63399
63973
|
|
|
63400
63974
|
// src/commands/graphql.ts
|
|
63401
|
-
import { readFileSync as
|
|
63975
|
+
import { readFileSync as readFileSync6 } from "fs";
|
|
63402
63976
|
var runGraphql = async (args) => {
|
|
63403
63977
|
const inline = await readValue(flagValue(args, "-q", "--query"), "-q");
|
|
63404
63978
|
const file2 = flagValue(args, "-f", "--file");
|
|
63405
|
-
const query = inline ?? (file2 != null ?
|
|
63979
|
+
const query = inline ?? (file2 != null ? readFileSync6(file2, "utf8") : process.stdin.isTTY ? "" : (await readStdin("the query")).trim());
|
|
63406
63980
|
if (query.length === 0) {
|
|
63407
63981
|
throw new Error(
|
|
63408
63982
|
"Provide a query with -q '<query>', -q @<file>, -f <file>, or stdin."
|
|
@@ -63426,14 +64000,19 @@ var runGraphql = async (args) => {
|
|
|
63426
64000
|
);
|
|
63427
64001
|
}
|
|
63428
64002
|
})();
|
|
63429
|
-
const
|
|
63430
|
-
|
|
63431
|
-
|
|
63432
|
-
|
|
63433
|
-
|
|
63434
|
-
|
|
63435
|
-
|
|
63436
|
-
|
|
64003
|
+
const format2 = resolveFormat(flagValue(args, "-o", "--output"));
|
|
64004
|
+
if (!args.includes("--v1")) {
|
|
64005
|
+
printResult(
|
|
64006
|
+
await gqlRequest(query, variables),
|
|
64007
|
+
format2
|
|
64008
|
+
);
|
|
64009
|
+
return;
|
|
64010
|
+
}
|
|
64011
|
+
const res = await cliClient().fetch("/v1/graphql", {
|
|
64012
|
+
method: "POST",
|
|
64013
|
+
headers: { "Content-Type": "application/json" },
|
|
64014
|
+
body: JSON.stringify({ query, variables })
|
|
64015
|
+
});
|
|
63437
64016
|
const raw2 = await res.text();
|
|
63438
64017
|
const body = (() => {
|
|
63439
64018
|
try {
|
|
@@ -63449,39 +64028,11 @@ var runGraphql = async (args) => {
|
|
|
63449
64028
|
if (body == null) {
|
|
63450
64029
|
throw new Error("graphql returned an unreadable body.");
|
|
63451
64030
|
}
|
|
63452
|
-
printResult(body.data,
|
|
64031
|
+
printResult(body.data, format2);
|
|
63453
64032
|
};
|
|
63454
64033
|
|
|
63455
64034
|
// src/commands/integration.ts
|
|
63456
64035
|
var USAGE3 = "Usage: overai integration configure <id> --config <json|@file|@-> | integration config <id> | integration secret set <id> <KEY> --value <@file|@-> | integration secret unset <id> <KEY>";
|
|
63457
|
-
var setSecret = async (integrationId, key, rawValue) => {
|
|
63458
|
-
if (rawValue == null) {
|
|
63459
|
-
throw new Error("Integration secret set requires --value.");
|
|
63460
|
-
}
|
|
63461
|
-
if (!rawValue.startsWith("@")) {
|
|
63462
|
-
throw new Error(
|
|
63463
|
-
"--value must be @- (stdin) or @<file>, so the secret stays out of your shell history."
|
|
63464
|
-
);
|
|
63465
|
-
}
|
|
63466
|
-
const value = await readValue(rawValue, "--value");
|
|
63467
|
-
if (value == null || value === "") {
|
|
63468
|
-
throw new Error("--value resolved to an empty string.");
|
|
63469
|
-
}
|
|
63470
|
-
await gqlRequest(
|
|
63471
|
-
`mutation SetIntegrationSecret($input: UpdateIntegrationConfigInput!) {
|
|
63472
|
-
updateIntegrationConfig(input: $input) { success }
|
|
63473
|
-
}`,
|
|
63474
|
-
{ input: { integrationId, partialConfig: { [key]: value } } }
|
|
63475
|
-
);
|
|
63476
|
-
};
|
|
63477
|
-
var unsetSecret = async (integrationId, key) => {
|
|
63478
|
-
await gqlRequest(
|
|
63479
|
-
`mutation UnsetIntegrationSecret($input: DeleteIntegrationConfigKeyInput!) {
|
|
63480
|
-
deleteIntegrationConfigKey(input: $input) { success }
|
|
63481
|
-
}`,
|
|
63482
|
-
{ input: { integrationId, key } }
|
|
63483
|
-
);
|
|
63484
|
-
};
|
|
63485
64036
|
var runIntegration = async (args) => {
|
|
63486
64037
|
const [operation] = args;
|
|
63487
64038
|
if (operation === "secret") {
|
|
@@ -63489,22 +64040,36 @@ var runIntegration = async (args) => {
|
|
|
63489
64040
|
if (action !== "set" && action !== "unset" || id2 == null || key == null || key.startsWith("-")) {
|
|
63490
64041
|
throw new Error(USAGE3);
|
|
63491
64042
|
}
|
|
64043
|
+
const integration2 = cliClient().integration(id2);
|
|
63492
64044
|
if (action === "set") {
|
|
63493
|
-
|
|
64045
|
+
const rawValue = flagValue(args, "--value");
|
|
64046
|
+
if (rawValue == null) {
|
|
64047
|
+
throw new Error("Integration secret set requires --value.");
|
|
64048
|
+
}
|
|
64049
|
+
if (!rawValue.startsWith("@")) {
|
|
64050
|
+
throw new Error(
|
|
64051
|
+
"--value must be @- (stdin) or @<file>, so the secret stays out of your shell history."
|
|
64052
|
+
);
|
|
64053
|
+
}
|
|
64054
|
+
const value = await readValue(rawValue, "--value");
|
|
64055
|
+
if (value == null || value === "") {
|
|
64056
|
+
throw new Error("--value resolved to an empty string.");
|
|
64057
|
+
}
|
|
64058
|
+
await integration2.setSecret(key, value);
|
|
63494
64059
|
} else {
|
|
63495
|
-
await unsetSecret(
|
|
64060
|
+
await integration2.unsetSecret(key);
|
|
63496
64061
|
}
|
|
63497
|
-
|
|
63498
|
-
|
|
63499
|
-
|
|
64062
|
+
printResult(
|
|
64063
|
+
await integration2.config(),
|
|
64064
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
63500
64065
|
);
|
|
63501
|
-
printResult(result2, resolveFormat(flagValue(args, "-o", "--output")));
|
|
63502
64066
|
return;
|
|
63503
64067
|
}
|
|
63504
64068
|
const [, id] = args;
|
|
63505
64069
|
if (id == null || operation !== "configure" && operation !== "config") {
|
|
63506
64070
|
throw new Error(USAGE3);
|
|
63507
64071
|
}
|
|
64072
|
+
const integration = cliClient().integration(id);
|
|
63508
64073
|
if (operation === "configure") {
|
|
63509
64074
|
const raw2 = await readValue(flagValue(args, "--config"), "--config");
|
|
63510
64075
|
if (raw2 == null)
|
|
@@ -63516,16 +64081,16 @@ var runIntegration = async (args) => {
|
|
|
63516
64081
|
throw new Error("--config must be valid JSON.");
|
|
63517
64082
|
}
|
|
63518
64083
|
})();
|
|
63519
|
-
await
|
|
64084
|
+
await integration.configure(value);
|
|
63520
64085
|
}
|
|
63521
|
-
|
|
63522
|
-
|
|
63523
|
-
|
|
63524
|
-
|
|
64086
|
+
printResult(
|
|
64087
|
+
await integration.config(),
|
|
64088
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
64089
|
+
);
|
|
63525
64090
|
};
|
|
63526
64091
|
|
|
63527
64092
|
// src/commands/knowledgeBase.ts
|
|
63528
|
-
import {
|
|
64093
|
+
import { openAsBlob as openAsBlob2 } from "fs";
|
|
63529
64094
|
import { basename } from "path";
|
|
63530
64095
|
var runKnowledgeBase = async (args) => {
|
|
63531
64096
|
const [operation, id] = args;
|
|
@@ -63534,7 +64099,7 @@ var runKnowledgeBase = async (args) => {
|
|
|
63534
64099
|
"Usage: overai knowledge-base upload <id> <file...> | knowledge-base search <id> <query> [--limit N]"
|
|
63535
64100
|
);
|
|
63536
64101
|
}
|
|
63537
|
-
const
|
|
64102
|
+
const knowledgeBase = cliClient().knowledgeBase(id);
|
|
63538
64103
|
if (operation === "upload") {
|
|
63539
64104
|
const paths = args.slice(2).filter(
|
|
63540
64105
|
(arg, i, all) => !arg.startsWith("-") && all[i - 1] !== "-o" && all[i - 1] !== "--output"
|
|
@@ -63543,20 +64108,11 @@ var runKnowledgeBase = async (args) => {
|
|
|
63543
64108
|
throw new Error("Knowledge base upload requires at least one file path.");
|
|
63544
64109
|
const uploads = [];
|
|
63545
64110
|
for (const path of paths) {
|
|
63546
|
-
const
|
|
63547
|
-
|
|
63548
|
-
formData.append(
|
|
63549
|
-
"file",
|
|
63550
|
-
new Blob([new Uint8Array(bytes)]),
|
|
64111
|
+
const result = await knowledgeBase.upload(
|
|
64112
|
+
await openAsBlob2(path),
|
|
63551
64113
|
basename(path)
|
|
63552
64114
|
);
|
|
63553
|
-
|
|
63554
|
-
`/v2/knowledge-bases/${organizationId}/${id}/upload`,
|
|
63555
|
-
{ method: "POST", body: formData }
|
|
63556
|
-
);
|
|
63557
|
-
const raw3 = await response2.text();
|
|
63558
|
-
if (!response2.ok) throw v2Error("knowledge-base upload", response2, raw3);
|
|
63559
|
-
uploads.push({ file: basename(path), ...JSON.parse(raw3) });
|
|
64115
|
+
uploads.push({ file: basename(path), ...result });
|
|
63560
64116
|
}
|
|
63561
64117
|
printResult(uploads, resolveFormat(flagValue(args, "-o", "--output")));
|
|
63562
64118
|
return;
|
|
@@ -63564,22 +64120,9 @@ var runKnowledgeBase = async (args) => {
|
|
|
63564
64120
|
const query = args[2];
|
|
63565
64121
|
if (query == null || query.startsWith("-"))
|
|
63566
64122
|
throw new Error("Knowledge base search requires a query string.");
|
|
63567
|
-
const limit2 =
|
|
63568
|
-
const response = await v2Fetch(
|
|
63569
|
-
`/v2/knowledge-bases/${organizationId}/${id}/search`,
|
|
63570
|
-
{
|
|
63571
|
-
method: "POST",
|
|
63572
|
-
headers: { "Content-Type": "application/json" },
|
|
63573
|
-
body: JSON.stringify({
|
|
63574
|
-
query,
|
|
63575
|
-
...limit2 != null ? { limit: Number(limit2) } : {}
|
|
63576
|
-
})
|
|
63577
|
-
}
|
|
63578
|
-
);
|
|
63579
|
-
const raw2 = await response.text();
|
|
63580
|
-
if (!response.ok) throw v2Error("knowledge-base search", response, raw2);
|
|
64123
|
+
const limit2 = integerFlag(args, "--limit");
|
|
63581
64124
|
printResult(
|
|
63582
|
-
|
|
64125
|
+
await knowledgeBase.search(query, limit2 != null ? { limit: limit2 } : {}),
|
|
63583
64126
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
63584
64127
|
);
|
|
63585
64128
|
};
|
|
@@ -63872,25 +64415,16 @@ var unaliasOrg = async (alias) => {
|
|
|
63872
64415
|
// src/commands/printablePage.ts
|
|
63873
64416
|
var runPrintablePage = async (args) => {
|
|
63874
64417
|
const [operation, id] = args;
|
|
63875
|
-
if (operation !== "render" || id == null)
|
|
63876
|
-
|
|
63877
|
-
|
|
63878
|
-
|
|
63879
|
-
);
|
|
63880
|
-
if (data.printablePage == null) throw new Error(`Printable page ${id} not found.`);
|
|
64418
|
+
if (operation !== "render" || id == null)
|
|
64419
|
+
throw new Error(
|
|
64420
|
+
"Usage: overai printable-page render <id> [--search-params <json|@file>] [--timeout <ms>]"
|
|
64421
|
+
);
|
|
63881
64422
|
const searchParams = await readValue(flagValue(args, "--search-params"), "--search-params") ?? "{}";
|
|
63882
64423
|
JSON.parse(searchParams);
|
|
63883
|
-
const
|
|
63884
|
-
|
|
63885
|
-
|
|
63886
|
-
method: "POST",
|
|
63887
|
-
headers: { "Content-Type": "application/json" },
|
|
63888
|
-
body: JSON.stringify({ actionId: "PRINTABLE_PAGE_TO_PDF", inputs: { printablePageId: id, searchParams, includeDiagnostics: true } }),
|
|
63889
|
-
signal: AbortSignal.timeout(timeoutMs)
|
|
64424
|
+
const body = await cliClient().printablePage(id).render({
|
|
64425
|
+
searchParams,
|
|
64426
|
+
timeoutMs: integerFlag(args, "--timeout", 6e4)
|
|
63890
64427
|
});
|
|
63891
|
-
const raw2 = await response.text();
|
|
63892
|
-
if (!response.ok) throw v2Error("printable-page render", response, raw2);
|
|
63893
|
-
const body = JSON.parse(raw2);
|
|
63894
64428
|
printResult(body, resolveFormat(flagValue(args, "-o", "--output")));
|
|
63895
64429
|
};
|
|
63896
64430
|
|
|
@@ -64313,7 +64847,7 @@ var runRemote = async (args) => {
|
|
|
64313
64847
|
|
|
64314
64848
|
// src/commands/update.ts
|
|
64315
64849
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
64316
|
-
import { existsSync as existsSync5, readFileSync as
|
|
64850
|
+
import { existsSync as existsSync5, readFileSync as readFileSync7 } from "fs";
|
|
64317
64851
|
import { fileURLToPath } from "url";
|
|
64318
64852
|
var PACKAGE_NAME = "@overaihq/cli";
|
|
64319
64853
|
var packageRootUrl = () => {
|
|
@@ -64331,7 +64865,7 @@ var compareVersions = (a, b) => {
|
|
|
64331
64865
|
};
|
|
64332
64866
|
var cliVersion = () => {
|
|
64333
64867
|
const pkg = JSON.parse(
|
|
64334
|
-
|
|
64868
|
+
readFileSync7(new URL("package.json", packageRootUrl()), "utf8")
|
|
64335
64869
|
);
|
|
64336
64870
|
return pkg.version;
|
|
64337
64871
|
};
|
|
@@ -64438,8 +64972,7 @@ var runReport = async (args) => {
|
|
|
64438
64972
|
}
|
|
64439
64973
|
})();
|
|
64440
64974
|
const resources = manifest ? Object.entries(manifest.resources) : [];
|
|
64441
|
-
await
|
|
64442
|
-
...input2,
|
|
64975
|
+
await cliClient().report(input2.feedbackType, input2.detailedBugReport, {
|
|
64443
64976
|
source: "cli",
|
|
64444
64977
|
cliContext: {
|
|
64445
64978
|
cliVersion: cliVersion(),
|
|
@@ -64478,12 +65011,12 @@ var runResource = async (args) => {
|
|
|
64478
65011
|
);
|
|
64479
65012
|
return;
|
|
64480
65013
|
}
|
|
64481
|
-
const timeout =
|
|
65014
|
+
const timeout = integerFlag(args, "--timeout");
|
|
64482
65015
|
const patch = {
|
|
64483
65016
|
name: flagValue(args, "--name"),
|
|
64484
65017
|
description: flagValue(args, "--description"),
|
|
64485
65018
|
integrationTypeId: flagValue(args, "--type"),
|
|
64486
|
-
actionTimeoutSeconds: timeout
|
|
65019
|
+
actionTimeoutSeconds: timeout
|
|
64487
65020
|
};
|
|
64488
65021
|
[
|
|
64489
65022
|
["isArchived", "--archive", true],
|
|
@@ -64538,7 +65071,9 @@ var workflow = `# CLI editing workflow
|
|
|
64538
65071
|
step users can feel; push freely, deploy deliberately.
|
|
64539
65072
|
|
|
64540
65073
|
Never edit .overai/ by hand \u2014 it holds the manifest and pristine base copies
|
|
64541
|
-
that make status/diff/fast-forward work.
|
|
65074
|
+
that make status/diff/fast-forward work. \`.overai/base/\` mirrors every
|
|
65075
|
+
resource file as last synced; edit the working copy, never the base. Git and
|
|
65076
|
+
ripgrep skip the folder through its own ignore files.
|
|
64542
65077
|
|
|
64543
65078
|
A push conflict does not deploy anything. Normal push sends the manifest base
|
|
64544
65079
|
to an atomic server check; only explicit --force omits it. Never use --force as
|
|
@@ -64617,6 +65152,19 @@ around a clone-sync mismatch; use the correct workspace folder.
|
|
|
64617
65152
|
- Give each service its own credential. List, rotate, or revoke it with
|
|
64618
65153
|
\`overai sql credential list|rotate|revoke\`.
|
|
64619
65154
|
|
|
65155
|
+
## From a script
|
|
65156
|
+
|
|
65157
|
+
- The CLI is a shell over \`@overaihq/sdk\`. A Node script or a long-running
|
|
65158
|
+
program uses the package directly: \`createClient({ baseUrl, token: patToken(secret, baseUrl) })\`
|
|
65159
|
+
gives \`client.fn(id).call()\`, \`client.tableSpace(id).sql()\`,
|
|
65160
|
+
\`client.page(id).save()\`/\`.deploy()\`, \`client.workspaces.list()\`, and the
|
|
65161
|
+
rest of what the commands do, with the same errors. \`overai\` stays the right
|
|
65162
|
+
tool at a terminal; the SDK is for code.
|
|
65163
|
+
- \`@overaihq/sdk/env\` exports \`createEnv\`: \`await createEnv(client)\` is the \`env\` object function
|
|
65164
|
+
code already uses, outside the platform. Everything HTTP-backed is there
|
|
65165
|
+
(\`env.FNxxx.call\`, \`env.TBSxxx.sql\`, \`env.DFxxx.read\`, \`env.STORAGE\`,
|
|
65166
|
+
\`env.AI\`); \`env.BROWSER\` and \`env.CALLER\` exist only inside a function.
|
|
65167
|
+
|
|
64620
65168
|
## Reporting platform problems
|
|
64621
65169
|
|
|
64622
65170
|
When broken or unexplained platform behavior blocks progress, send a detailed
|
|
@@ -65015,7 +65563,7 @@ Users who prefer their own editor or an AI coding agent (Claude Code, Cursor) ca
|
|
|
65015
65563
|
|
|
65016
65564
|
Clone includes accessible, non-archived descendants under \`workspaces/<slug>.<workspaceId>/\`, each with its own manifest and overview. Commands use the nearest workspace folder: change into a child to work there. Add \`--recursive\` to status/diff/pull/push to include the live accessible subtree; recursive pull clones new children and matches existing folders by workspace ID. Recursive push saves only and rejects --deploy; deploy/restore remain single-workspace. Conflicts or failures exit nonzero while preserving local edits and successful work. Unavailable or moved-out workspaces stay on disk and are skipped. Local file moves do not move resources between workspaces in OverAI.
|
|
65017
65565
|
|
|
65018
|
-
The loop is git-shaped: \`overai clone <workspaceId>\` writes the workspace overview to \`WORKSPACE.md\` and materializes automations, functions, web pages, printable pages, and agents as local files; \`status\`/\`diff\`/\`pull\` track local resource edits against remote drift; \`push -m "why"\` creates new versions and \`deploy\` makes them live \u2014 **pushing alone changes nothing users see**. \`overai create <type>\` creates any current resource, while \`resource show|update <id>\` handles mutable metadata. \`workspace show [workspaceId]\` reads the current overview, and \`workspace users [workspaceId]\` lists effective, direct, and inherited access; inside a clone the id is optional. Resource-specific commands invoke functions and agents, trigger automations, run SQL, append/query streams, upload/download files, configure integrations, render printable pages, and pair or use runners. \`overai review\` validates changed resources before a push, and \`overai best-practices\` serves these same doc topics, plus the CLI's own workflow guide, to the local agent.
|
|
65566
|
+
The loop is git-shaped: \`overai clone <workspaceId>\` writes the workspace overview to \`WORKSPACE.md\` and materializes automations, functions, web pages, printable pages, and agents as local files (\`.overai/\` holds sync state and is ignored by git); \`status\`/\`diff\`/\`pull\` track local resource edits against remote drift; \`push -m "why"\` creates new versions and \`deploy\` makes them live \u2014 **pushing alone changes nothing users see**. \`overai create <type>\` creates any current resource, while \`resource show|update <id>\` handles mutable metadata. \`workspace show [workspaceId]\` reads the current overview, and \`workspace users [workspaceId]\` lists effective, direct, and inherited access; inside a clone the id is optional. Resource-specific commands invoke functions and agents, trigger automations, run SQL, append/query streams, upload/download files, configure integrations, render printable pages, and pair or use runners. \`overai review\` validates changed resources before a push, and \`overai best-practices\` serves these same doc topics, plus the CLI's own workflow guide, to the local agent.
|
|
65019
65567
|
|
|
65020
65568
|
Point users here when they ask about editing outside the browser, using a local AI coding agent, version-controlling a workspace, or scripting against the platform. Everything the CLI does is also doable in the Architect \u2014 it is an alternative surface, not a required one. Full command list: \`overai help\`; the user-facing guide is the help center article at \`/<orgId>/help/cli\`.
|
|
65021
65569
|
`
|
|
@@ -65237,6 +65785,10 @@ Two optional JSON Schemas declare the function's contract:
|
|
|
65237
65785
|
|
|
65238
65786
|
The deployed version's schemas type \`env.FNxxx.call()\` everywhere authors call this function: the envelope's \`body\` member types the call body, and the output schema types \`res.json()\`. Declare the output schema whenever the response shape is stable \u2014 callers get autocomplete and typo-catching lint instead of \`any\` \u2014 and keep both schemas in sync with what the code actually reads and returns. They describe the base path; a router's sub-paths are outside the declared contract.
|
|
65239
65787
|
|
|
65788
|
+
Autocomplete and deployed-schema types cover functions owned by or shared into this workspace. A manually named \`env.FNxxx\` (or \`env.fnxxx\`) outside that list has a generic call type, not the target's schema. Static unlisted references warn through \`architect/unlisted-function\`; an intentional cross-workspace call may be valid, but verify the ID and the deployed caller access against the actual caller. Do not claim access was verified without checking, change sharing or caller access just to silence the warning, or invoke a side-effecting function merely to test it. After verification, acknowledge a known reference with \`// eslint-disable-next-line architect/unlisted-function -- <verified reason>\` directly above it. Give a concrete reason; avoid casts, \`@ts-ignore\`, and blanket suppressions. Dynamic IDs are outside this static check.
|
|
65789
|
+
|
|
65790
|
+
If the warning gives a listed function's spelling, use that spelling instead of suppressing it; different casing loses its deployed-schema types.
|
|
65791
|
+
|
|
65240
65792
|
Lint enforces the output side: when an output schema is declared, a handler whose return value doesn't match it gets a lint error (both on code edits and on schema edits). Returning the plain JSON value (the runtime wraps it in a 200 response) keeps the check active; a hand-built \`Response\` passes unchecked because its payload is invisible to the type checker. Enum values are checked as their base type (\`string\`, not the exact members), and \`null\`/missing-return code paths are not caught \u2014 verify those yourself.
|
|
65241
65793
|
|
|
65242
65794
|
Callers can also name the declared shapes: the deployed schemas generate \`Env.FNxxx.Input\` (the call body) and \`Env.FNxxx.Output\` (the response) for annotating payloads and results.
|
|
@@ -65266,6 +65818,12 @@ Built-in variables:
|
|
|
65266
65818
|
- \`env.CALLER\` (verified JWT claims from the request, or null \u2014 useful for identifying the calling user from a web page)
|
|
65267
65819
|
- Any custom secrets/environment variables configured on the function
|
|
65268
65820
|
|
|
65821
|
+
The same \`env\` is importable outside the platform: \`import { createEnv } from "@overaihq/sdk/env"\` and \`const env = await createEnv(client)\`
|
|
65822
|
+
gives a Node script every HTTP-backed member above with the same names and
|
|
65823
|
+
shapes. \`env.BROWSER\` and \`env.CALLER\` exist only inside a function, and
|
|
65824
|
+
\`env.TBSxxx.sql\` there returns \`{ rows, rowCount }\` over HTTP instead of a
|
|
65825
|
+
direct database connection.
|
|
65826
|
+
|
|
65269
65827
|
## AI Access
|
|
65270
65828
|
|
|
65271
65829
|
Generate text or structured objects using LLMs:
|
|
@@ -66055,8 +66613,6 @@ Saves reject a stale editing base without discarding your draft. Incorporate the
|
|
|
66055
66613
|
|
|
66056
66614
|
\`\`\`typescript
|
|
66057
66615
|
declare global {
|
|
66058
|
-
const filterData: { id: string; attributes: { id: string; attributeId: string; value: string; }[]; }[] | null;
|
|
66059
|
-
const dataFile: Record<string, unknown> | null;
|
|
66060
66616
|
const searchParams: Record<string, unknown>;
|
|
66061
66617
|
const setSearchParam: { (key: string, value: string | null): void; (params: Record<string, string | null>): void }; // pass null to delete a param; pass an object to set/delete several in one URL update
|
|
66062
66618
|
const navigateToPage: (webPageId: string, queryParameters?: Record<string, string>, options?: { newTab?: boolean }) => void; // { newTab: true } opens the page in a new browser tab \u2014 use it instead of hand-building URLs with window.open
|
|
@@ -66070,6 +66626,8 @@ declare global {
|
|
|
66070
66626
|
/** @deprecated Use useLLMText, useLLMObject, or useLLMChat instead. */
|
|
66071
66627
|
const llmCompletion: (message: string, systemPrompt?: string, model?: string) => Promise<Record<string, unknown>>;
|
|
66072
66628
|
const callFunction: (functionId: string, options?: { body?: unknown; method?: string; query?: Record<string, string>; path?: string }) => Promise<Response>;
|
|
66629
|
+
// Start a deployed automation. \`inputs\` maps onto its event node's declared outputs (e.g. { fileUrl } for a file-upload trigger \u2014 upload with env.STORAGE.upload first). Throws on non-2xx.
|
|
66630
|
+
const startAutomation: (automationId: string, inputs?: Record<string, unknown>) => Promise<{ automationRunId: string }>;
|
|
66073
66631
|
|
|
66074
66632
|
// Imperative AI functions
|
|
66075
66633
|
// Prefer stream: false for one-shot generateText calls \u2014 errors (invalid PDF, prompt too long, rate limit) come back as HTTP errors with a friendly message instead of an empty body. Only stream when you wire onChunk for progressive UI.
|
|
@@ -66086,20 +66644,10 @@ declare global {
|
|
|
66086
66644
|
const callAgentGenerateObject: (agentId: string, message: string, schema: Record<string, unknown>) => Promise<{ object: unknown; model: string; finishReason: string; usage: { promptTokens: number; completionTokens: number; totalTokens: number }; toolResults: { toolName: string; input: unknown; output: unknown; error: unknown }[] }>;
|
|
66087
66645
|
const callAgentChat: (agentId: string, messages: { role: string; parts: { type: string; text?: string }[] }[], options?: { conversationId?: string; onChunk?: (accumulated: string) => void }) => Promise<string>;
|
|
66088
66646
|
|
|
66089
|
-
// Agent Hook \u2014 multi-turn streaming chat with an OverAI Agent.
|
|
66090
|
-
// Every turn is persisted server-side for a signed-in viewer. Pass conversationId
|
|
66091
|
-
// to resume a past thread (its full transcript, tool calls included, loads on
|
|
66092
|
-
// mount). Omit it to start fresh \u2014 a conversation is created on the first send and
|
|
66093
|
-
// returned as conversationId. messages[].parts holds full UI parts for loaded turns;
|
|
66094
|
-
// the live-streaming turn carries text only.
|
|
66095
|
-
// On a PUBLIC page there is no viewer identity: chat works, but the transcript
|
|
66096
|
-
// lives in the hook for the tab's life, conversationId stays null, and the
|
|
66097
|
-
// conversation helpers below throw. See "Public pages" below.
|
|
66647
|
+
// Agent Hook \u2014 multi-turn streaming chat with an OverAI Agent; persistence and resume are explained below the block. messages[].parts holds full UI parts for loaded turns; the live-streaming turn carries text only.
|
|
66098
66648
|
const useAgentChat: (agentId: string, options?: { conversationId?: string }) => { messages: { id?: string; role: string; text: string; parts?: { type: string; text?: string; toolName?: string; toolCallId?: string; state?: string; input?: unknown; output?: unknown }[] }[]; sendMessage: (text: string) => void; clearMessages: () => void; loading: boolean; error: string | null; conversationId: string | null };
|
|
66099
66649
|
|
|
66100
|
-
// Agent conversation management \u2014 list/read/manage a signed-in user's chat threads
|
|
66101
|
-
// with an agent. Unavailable on public pages (no identity owns a thread):
|
|
66102
|
-
// useAgentConversations returns an empty list, the rest throw.
|
|
66650
|
+
// Agent conversation management \u2014 list/read/manage a signed-in user's chat threads with an agent.
|
|
66103
66651
|
const useAgentConversations: (agentId: string) => { conversations: { id: string; title: string; updatedAt: string }[]; loading: boolean; error: string | null; refresh: () => Promise<void> };
|
|
66104
66652
|
const listAgentConversations: (agentId: string) => Promise<{ id: string; title: string; updatedAt: string }[]>;
|
|
66105
66653
|
const getAgentConversationMessages: (conversationId: string) => Promise<{ id?: string; role: string; text: string; parts?: { type: string; text?: string }[] }[]>;
|
|
@@ -66121,9 +66669,12 @@ declare global {
|
|
|
66121
66669
|
/** Escape hatch for dynamic SQL. Caller is responsible for parameterizing. */
|
|
66122
66670
|
unsafe: <Row = any>(query: string, params?: unknown[]) => Promise<{ rows: Row[]; rowCount: number }>;
|
|
66123
66671
|
};
|
|
66672
|
+
/** Several statements that must all land or none do. Pass lazy \`sql\` fragments; resolves to { results, executionId, durationMs } with results[i] = { rows, rowCount }. Any failure rolls everything back and throws. */
|
|
66673
|
+
transaction: (statements: readonly unknown[]) => Promise<{ results: { rows: Record<string, unknown>[]; rowCount: number }[]; executionId: string; durationMs: number }>;
|
|
66124
66674
|
/** @deprecated Use \`sql\` \u2014 it auto-parameterizes interpolated values and returns rows directly. query returns camelCased columns (sql returns snake_case); do not mix the two. */
|
|
66125
66675
|
query: (sql: TemplateStringsArray, ...values: unknown[]) => Promise<Response>;
|
|
66126
66676
|
};
|
|
66677
|
+
[automationId: \`AT\${string}\`]: { start: (inputs?: Record<string, unknown>) => Promise<{ automationRunId: string }> };
|
|
66127
66678
|
/** \`path\` routes to a sub-path inside the function (e.g. "/features/123") for functions that ship their own router; omit it to hit the base path. Method still defaults to POST. */
|
|
66128
66679
|
[functionId: \`FN\${string}\`]: { call: (options?: { body?: unknown; method?: string; query?: Record<string, string>; path?: string }) => Promise<Response> };
|
|
66129
66680
|
[agentId: \`AG\${string}\`]: { generateText: (message: string) => Promise<{ text: string; model: string; finishReason: string; usage: { promptTokens: number; completionTokens: number; totalTokens: number }; toolResults: { toolName: string; input: unknown; output: unknown; error: unknown }[] }>; generateObject: (message: string, schema: Record<string, unknown>) => Promise<{ object: unknown; model: string; finishReason: string; usage: { promptTokens: number; completionTokens: number; totalTokens: number }; toolResults: { toolName: string; input: unknown; output: unknown; error: unknown }[] }> };
|
|
@@ -66140,8 +66691,6 @@ declare global {
|
|
|
66140
66691
|
};
|
|
66141
66692
|
};
|
|
66142
66693
|
const React: typeof import("react");
|
|
66143
|
-
const useDataFile: () => Record<string, unknown> | null;
|
|
66144
|
-
const useFilterData: () => { id: string; attributes: { id: string; attributeId: string; value: string; }[]; }[] | null;
|
|
66145
66694
|
const useCurrentUser: () => { id: string; email: string; name: string; } | null;
|
|
66146
66695
|
// useTheme re-renders on the app's light/dark toggle. The page root already carries a \`dark\` class (Tailwind darkMode: "class"), so style with \`dark:\` variants \u2014 e.g. bg-white dark:bg-slate-900 \u2014 and reach for the hook only for JS-driven styling (chart palettes, canvas, map tiles).
|
|
66147
66696
|
// Two things a light-only page gets wrong in dark mode: a border or divide utility with no color class falls back to Tailwind's default light gray, so \`border-b\` alone stays a bright rule \u2014 pair it, e.g. border-b border-gray-200 dark:border-gray-700. And if the page loads daisyUI, its theme drives the inherited text color, so a hardcoded bg-white left to inherit turns light-on-white; give every surface a dark counterpart.
|
|
@@ -66154,19 +66703,29 @@ declare global {
|
|
|
66154
66703
|
const useLocalStorageState: <T>(key: string, initialValue: T) => [T, React.Dispatch<React.SetStateAction<T>>];
|
|
66155
66704
|
// useSessionStorageState is a useState-like hook backed by sessionStorage. Persists for the lifetime of the tab. REQUIRES noSandbox: true in the page config.
|
|
66156
66705
|
const useSessionStorageState: <T>(key: string, initialValue: T) => [T, React.Dispatch<React.SetStateAction<T>>];
|
|
66706
|
+
|
|
66707
|
+
// Legacy \u2014 populated only by the deprecated dataSourceUrl / filter page settings (see "Legacy data sources" below). New pages use env instead.
|
|
66708
|
+
const dataFile: Record<string, unknown> | null;
|
|
66709
|
+
const useDataFile: () => Record<string, unknown> | null;
|
|
66710
|
+
const filterData: { id: string; attributes: { id: string; attributeId: string; value: string; }[]; }[] | null;
|
|
66711
|
+
const useFilterData: () => { id: string; attributes: { id: string; attributeId: string; value: string; }[]; }[] | null;
|
|
66157
66712
|
}
|
|
66158
66713
|
\`\`\`
|
|
66159
66714
|
|
|
66160
|
-
IMPORTANT: Use
|
|
66715
|
+
IMPORTANT: Use useSearchParamState instead of the searchParams global when the component must re-render as the URL changes. URL state belongs in search params (via useSearchParamState), not local React state, so links and reloads preserve it.
|
|
66161
66716
|
|
|
66162
66717
|
IMPORTANT: callFunction and env.FNxxx.call return a Response object (like fetch) \u2014 call .json() or .text() to get the data. Date/timestamp values come back as ISO 8601 strings (e.g., "2026-04-06T00:00:00.000Z"). When the function declares input/output schemas, env.FNxxx.call types the body and .json() from them (the deployed version's declaration) \u2014 no annotation needed.
|
|
66163
66718
|
|
|
66719
|
+
Function autocomplete and deployed-schema types cover functions owned by or shared into this workspace. A manually named \`env.FNxxx\` or \`env.fnxxx\` outside that list remains a generic call, not a typed discovery of organization functions. A static unlisted reference raises advisory \`architect/unlisted-function\`; dynamic IDs are not checked. Verify the ID and deployed caller access for the page's actual caller before using an intentional cross-workspace reference. Never claim unverified access, change sharing or authorization just to silence the warning, or invoke a side-effecting function merely to test it. Once verified, acknowledge the reference with \`// eslint-disable-next-line architect/unlisted-function -- <verified reason>\` directly above it. Prefer a concrete reason, not casts, \`@ts-ignore\`, or blanket suppression.
|
|
66720
|
+
|
|
66721
|
+
If the warning gives a listed function's spelling, use that spelling instead of suppressing it; different casing loses its deployed-schema types.
|
|
66722
|
+
|
|
66164
66723
|
The \`env\` proxy matches the API available in Functions and Automations \u2014 the same code works in all three.
|
|
66165
66724
|
|
|
66166
66725
|
For AI in React components, prefer the reactive hooks (useLLMText, useLLMObject, useLLMChat, useAgentChat) \u2014 they re-render as the response streams in. In event handlers or imperative code, call generateText/generateObject (or env.AI.*) directly.
|
|
66167
66726
|
useAgentChat persists every turn server-side for a signed-in viewer: pass a conversationId to resume a past thread (full transcript, tool calls included, loads automatically), or omit it to start fresh and read the new thread's id off the returned conversationId. useAgentConversations(agentId) backs a history sidebar \u2014 call its refresh() after a first send so the newly created thread appears. listAgentConversations, getAgentConversationMessages, createAgentConversation, renameAgentConversation, and deleteAgentConversation are the imperative equivalents. On a public page none of that persistence exists (see Public pages) \u2014 useAgentChat still streams, holding the transcript in memory.
|
|
66168
66727
|
All AI functions/hooks accept optional File[] attachments for images/PDFs, and webSearch: true to enable web search.
|
|
66169
|
-
Available models:
|
|
66728
|
+
Available models: read \`availableModelIds\` from the \`getWebPageContext\` data tool. Omit \`model\` to use this workspace's default.
|
|
66170
66729
|
|
|
66171
66730
|
IMPORTANT: Keep generateObject / useLLMObject / agent generateObject schemas simple. Anthropic models reject schemas with more than 16 nullable or union-typed fields (this includes optional fields the AI SDK emits as \`type: [..., "null"]\`). Prefer non-nullable fields, split into multiple calls, or switch to a non-Anthropic model from the list above for larger schemas.
|
|
66172
66731
|
|
|
@@ -66242,25 +66801,16 @@ const { rows } = await env.TBS123.sql.unsafe(
|
|
|
66242
66801
|
|
|
66243
66802
|
Pages render UI; they don't perform server-side actions directly. To do anything with side effects beyond table-space SQL (send email, hit a third-party API, post to Slack, etc.), call a Function or trigger an Automation. Table spaces are the exception: read AND write them directly with env.TBSxxx.sql as shown above.
|
|
66244
66803
|
|
|
66245
|
-
- **Common actions** like sending email, Slack messages, SMS, or HTTP calls are first-class Automation nodes. \`SEND_EMAIL\` and \`HTTP\` need no integration; \`SLACK_SEND_MESSAGE\` and \`TWILIO_SEND_SMS\` require their respective integration to be configured. Build
|
|
66804
|
+
- **Common actions** like sending email, Slack messages, SMS, or HTTP calls are first-class Automation nodes. \`SEND_EMAIL\` and \`HTTP\` need no integration; \`SLACK_SEND_MESSAGE\` and \`TWILIO_SEND_SMS\` require their respective integration to be configured. Build the automation, deploy it, and start it from the page with \`env.ATxxx.start(inputs)\` (snippet below) \u2014 never hand-build its webhook URL.
|
|
66246
66805
|
- **Custom server logic** belongs in a Function. Call it from the page via \`callFunction('FN123', { body: {...} })\` or \`env.FN123.call({ body: {...} })\`. A Function that ships its own router serves many routes \u2014 reach one with \`path\`: \`env.FN123.call({ method: 'GET', path: '/features/123' })\`. Omit \`path\` for the base path; the method defaults to POST either way.
|
|
66247
66806
|
- **Action runners** (\`env.ACTIONS.run\`) are server-only \u2014 not available on a page. To run an action runner action from a page, put the \`env.ACTIONS.run(...)\` call in a Function and invoke that Function from the page.
|
|
66248
66807
|
- **Email** (\`env.EMAIL.send\`) is server-only for the same reason. Put the \`env.EMAIL.send(...)\` call in a Function and invoke that Function from the page.
|
|
66249
66808
|
- **Integrations** are credentials/config consumed *by* automation nodes or functions \u2014 they are not available directly in the page context. Only reach for an Integration when the work requires authenticated access to a specific third-party service.
|
|
66250
66809
|
|
|
66251
66810
|
\`\`\`typescript
|
|
66252
|
-
//
|
|
66253
|
-
//
|
|
66254
|
-
|
|
66255
|
-
const response = await fetch(
|
|
66256
|
-
'https://api.overai.com/v1/automation/webhook/ORG123/AT123',
|
|
66257
|
-
{
|
|
66258
|
-
method: 'POST',
|
|
66259
|
-
headers: { 'Content-Type': 'application/json' },
|
|
66260
|
-
body: JSON.stringify({ recipient: 'user@example.com' }),
|
|
66261
|
-
},
|
|
66262
|
-
);
|
|
66263
|
-
const { automationRunId } = await response.json();
|
|
66811
|
+
// Start a deployed automation. inputs maps onto its event node's declared
|
|
66812
|
+
// outputs; for a file-upload trigger, upload first and pass the url.
|
|
66813
|
+
const { automationRunId } = await env.AT123.start({ recipient: 'user@example.com' });
|
|
66264
66814
|
|
|
66265
66815
|
// To use an integration's credentials, call a Function that reads the integration config server-side.
|
|
66266
66816
|
const config = await callFunction('FN123', { body: { integrationId: 'IN123' } });
|
|
@@ -66300,17 +66850,13 @@ Page settings (\`authorizationMode\`, \`noSandbox\`, \`hideTopBar\`, \`runtime\`
|
|
|
66300
66850
|
|
|
66301
66851
|
\`runtime: "v2"\` serves the page from its own origin instead of the sandboxed srcdoc iframe: separate renderer process, real localStorage/sessionStorage and cookies with no noSandbox flag needed. It is versioned like every other setting \u2014 save and deploy to publish. Public (/public/:id) links always use v1 regardless of the toggle. Only v2 reaches browser devices: Web Serial, WebUSB and WebHID always work there; camera, microphone, geolocation, display-capture, fullscreen and screen-wake-lock work once listed in \`permissions\`.
|
|
66302
66852
|
|
|
66303
|
-
|
|
66304
|
-
|
|
66305
|
-
\`dataSourceUrl\` is fetched **verbatim** and its response becomes the \`data\` global. It is a plain static URL, not a template:
|
|
66853
|
+
### Legacy data sources: \`dataSourceUrl\`, \`filter\`, \`data\`, \`items\`
|
|
66306
66854
|
|
|
66307
|
-
|
|
66308
|
-
- If your data depends on a search param or anything else known only at render time, don't use \`dataSourceUrl\` \u2014 fetch it in the page with \`useEffect\` + \`env\`/\`fetch\`, which is the normal path anyway.
|
|
66309
|
-
- To clear it, pass JSON \`null\`. The string \`"null"\` is a four-character URL, not an empty value, and it fails at fetch time.
|
|
66855
|
+
These populate the \`data\`/\`items\` globals once, at render start, from the old item/attribute model that builders can no longer create. New pages use \`env\` (\`env.TBSxxx.sql\`, \`env.DFxxx\`), which can depend on search params, re-query on demand and report its own errors. Don't rewrite a working page just to migrate it. If you must touch them:
|
|
66310
66856
|
|
|
66311
|
-
|
|
66312
|
-
|
|
66313
|
-
A templated filter is **not** an access boundary
|
|
66857
|
+
- \`dataSourceUrl\` is fetched verbatim \u2014 no \`{x}\` or Liquid interpolation. Anything that depends on a search param belongs in a page-side fetch instead. Clear it with JSON \`null\`; the string \`"null"\` is a four-character URL.
|
|
66858
|
+
- \`filter\` evaluates Liquid in every string value against \`now\` (rounded to the minute) and each search param by name, e.g. \`{{ now | minus: 1209600000 | toISOString }}\` or \`{{ since }}\`. A template whose variable is missing from the URL fails the whole page rather than querying on an empty value.
|
|
66859
|
+
- A templated filter is **not** an access boundary: on a public or portal page the visitor controls the search params, so \`{{ tenant }}\` scoping is editable from the URL bar. Scope with the workspace's own access.
|
|
66314
66860
|
|
|
66315
66861
|
## Critical Rules
|
|
66316
66862
|
|
|
@@ -66323,13 +66869,13 @@ A templated filter is **not** an access boundary. On a public or portal page the
|
|
|
66323
66869
|
| \`useSessionStorageState(key, init)\` | Single-tab session state (wizard progress, scroll restoration) | Reload (same tab); cleared on tab close | **Requires \`noSandbox: true\`** |
|
|
66324
66870
|
| \`useState\` | Truly ephemeral UI (hover, animation step, in-flight form field before submit) | Nothing | Lost on every navigation |
|
|
66325
66871
|
|
|
66326
|
-
When the page uses \`useLocalStorageState\` or \`useSessionStorageState
|
|
66872
|
+
When the page uses \`useLocalStorageState\` or \`useSessionStorageState\` on the default v1 runtime, set \`noSandbox: true\` in the page config first \u2014 the hooks throw a clear error otherwise. A \`runtime: "v2"\` page needs no flag.
|
|
66327
66873
|
|
|
66328
66874
|
2. **DO NOT import React or hooks.** React, useState, useEffect, useRef, useMemo, useCallback, and useReducer are all globally available. Importing them will cause errors.
|
|
66329
66875
|
3. **The main component MUST be named \`App\` and MUST NOT be exported.** Write \`function App() { ... }\` \u2014 no \`export\`.
|
|
66330
66876
|
4. **Use Tailwind CSS for styling.** It's built in.
|
|
66331
66877
|
5. **Import external libraries from esm.sh.** Example: \`import confetti from "https://esm.sh/canvas-confetti@1.9.3"\`. Imports must be absolute https URLs \u2014 the sandbox cannot resolve bare or relative specifiers.
|
|
66332
|
-
6. **Sandbox restrictions.**
|
|
66878
|
+
6. **Sandbox restrictions (v1 runtime).** By default the page runs in a sandboxed iframe (allow-scripts only). Raw \`localStorage\`, \`sessionStorage\`, cookies, alert/confirm/prompt, and form submissions are blocked. Use \`useLocalStorageState\` / \`useSessionStorageState\` for storage (both require disabling the sandbox \u2014 see Rule 1). Set \`noSandbox: true\` to lift the sandbox, or \`runtime: "v2"\` (see Web Page Configuration) when the page also needs its own origin or browser devices.
|
|
66333
66879
|
7. **Read code before editing.** Reading a large page's config returns its outline instead of the code \u2014 then read only the blocks or line ranges you are about to change. Edits return the changed lines, numbered, so don't re-read to verify. Prefer small, targeted edits \u2014 insert or search-replace \u2014 over rewriting a whole block.
|
|
66334
66880
|
8. **Decompose large pages.** When a page exceeds ~200 lines, break it into multiple top-level function components (e.g., \`function DataTable() { ... }\` used inside \`function App() { ... }\`), so each can be read and edited on its own.
|
|
66335
66881
|
9. **Add TSDoc comments to every top-level declaration.** Write a \`/** brief description */\` comment above each function, component, and constant. Code outlines show these comments, giving structural context without reading the full code. Always add or update these when creating or modifying a block.
|
|
@@ -66340,6 +66886,46 @@ A templated filter is **not** an access boundary. On a public or portal page the
|
|
|
66340
66886
|
12. **Sanity-check chart math with console.log.** You cannot see the rendered output. When building or debugging visualizations, log intermediate values (scales, domains, ranges, computed positions, angles) and verify they make sense before saving. For example: \`console.log("gauge", { min, max, value, fraction, startAngle, endAngle, valueAngle })\`. Remove logs once the chart is working.
|
|
66341
66887
|
13. **Rebuild imported HTML natively \u2014 never embed it.** When the user brings HTML from somewhere else (an exported dashboard, a design mockup, a page from another tool), recreate it as a native page: an \`App\` component, Tailwind, d3 for charts. Pay close attention to preserving the original styling \u2014 colors, spacing, type scale, layout. Do NOT load a foreign HTML file into a \`srcDoc\` iframe or inject it into the DOM. Embedded HTML is opaque to code outlines and reachable only by blind string patches that silently do nothing when the source drifts \u2014 so every later request turns into guesswork. Port it once and every edit after that is a normal edit. (A Liquid printable page is the exception: Liquid is HTML templating, so imported markup becomes the template body directly.)
|
|
66342
66888
|
|
|
66889
|
+
## Best Practices
|
|
66890
|
+
|
|
66891
|
+
**Decide the page's purpose first, then design for it.** A page answers one question; several questions become tabs or separate pages. Most pages are one of three kinds, and each wants a different shape:
|
|
66892
|
+
|
|
66893
|
+
- **Single-flow page** \u2014 one task, start to finish (submit a request, review an item, check in). Keep it simple: one column, one primary action per screen, generous spacing. Think consumer app, not admin panel.
|
|
66894
|
+
- **KPI dashboard** \u2014 a few measures that matter, seen from several angles (trend, breakdown, against target). Users don't want to read a number, they want to feel it: a dense, color-accented table or a chart built for the specific question beats a row of big-number tiles. Add headline tiles only when asked.
|
|
66895
|
+
- **Command center** \u2014 operators who live in the page and need to act fast. Information density is the point: compact rows, inline status, filters and actions within reach, no decorative whitespace.
|
|
66896
|
+
|
|
66897
|
+
Name the kind to the user when you propose a design; if the request mixes kinds, split it rather than compromising all three.
|
|
66898
|
+
|
|
66899
|
+
**Build a clear hierarchy.** Size is only one tool. Group related elements and separate unrelated ones with spacing, borders or dividers; order sections by importance, with the thing the user came for first; distinguish primary actions from secondary ones; mute labels and metadata so values stand out. The visible structure should mirror the data model underneath, so relationships between concepts are obvious. A reader should see what matters before reading a word.
|
|
66900
|
+
|
|
66901
|
+
**Spend pixels on data, not decoration.** Don't repeat a label on every row or card when a column header or section title carries it. Use color sparingly and for meaning: if problems are red, tune the thresholds so only real problems are, or the signal is lost. No emojis. Add a tooltip where a value's origin or calculation isn't obvious. Disable a control the user can't use right now instead of hiding it, so the page teaches what it can do.
|
|
66902
|
+
|
|
66903
|
+
**Choose the layout deliberately.**
|
|
66904
|
+
|
|
66905
|
+
- A scrolling document, or a command center where panels scroll independently inside a fixed viewport? For the latter, use CSS grid over flex, fill the viewport, and don't cap the page with a top-level max-width.
|
|
66906
|
+
- Tables for rows the user compares; cards or grids for non-uniform items. Size each column for its content and decide which wrap and which truncate.
|
|
66907
|
+
- Drill in with a drawer when the surrounding context should stay visible, a large modal when the user needs focus. Make the background inert while a modal is open.
|
|
66908
|
+
- Decide whether the page must work on a small screen; not every page does, but check the ones that will be opened on a phone.
|
|
66909
|
+
- Style for both themes: the page root carries a \`dark\` class, so pair every surface and border with a \`dark:\` variant (see \`useTheme\` above).
|
|
66910
|
+
|
|
66911
|
+
**Represent data accurately.** A page that looks right but misreports the data is worse than one that shows an error. Common failures:
|
|
66912
|
+
|
|
66913
|
+
- **A query \`LIMIT\` is not a count.** Loading \`LIMIT 1000\` and labeling it "1000 items" misreports every larger table. Run a separate \`count(*)\` for totals, and label a truncated list as such ("Showing 1,000 of 14,212").
|
|
66914
|
+
- **Offer "Load more" when there is more.** Prefer a subtle "Load more" control over numbered pagination; either way the user must be able to reach every row.
|
|
66915
|
+
- **Dates are not timestamps \u2014 check the time zone before you format.** A \`date\` column (a calendar day, no time) arrives from \`env.TBSxxx.sql\` as a JS \`Date\` at 00:00 UTC, so \`toLocaleDateString()\` in any zone west of UTC shows the previous day. Format a day from its UTC fields (\`d.toISOString().slice(0, 10)\` or \`Intl.DateTimeFormat(undefined, { timeZone: "UTC", dateStyle: "medium" })\`), and never pass it through local-time math. A \`timestamptz\` is a real instant: format it in the viewer's zone and show the zone (\`timeZoneName: "short"\`) when readers may be in different places. A \`timestamp\` without zone is ambiguous \u2014 ask which zone it was written in rather than guessing. Function responses carry dates as ISO strings; the same rules apply after \`new Date(iso)\`. Day-boundary filters (\`today\`, \`this week\`) must be computed in the business's zone, in SQL via \`AT TIME ZONE\`, not in the browser's. Tell the user which columns are days and which are instants, and label the zone in the UI.
|
|
66916
|
+
- **Never fall back to a value that hides a data problem.** \`?? 0\`, \`?? "N/A"\`, \`?? []\` make a broken query or a missing column look like a legitimate result. Show an explicit empty or error state, and when a value is unexpectedly null, surface it (a dash, an "unknown" badge) rather than inventing a default.
|
|
66917
|
+
|
|
66918
|
+
**Embed PDFs with \`<object>\` on a v2 page.** When \`runtime: "v2"\`, render a PDF with \`<object data={url} type="application/pdf" />\` rather than an \`<iframe>\`.
|
|
66919
|
+
|
|
66920
|
+
**Link stored files through the app host.** Storage URLs are persisted as \`https://api.<host>/v1/storage/...\`, where the browser holds no session. Before rendering one as a link, embed or download, rewrite it to the app origin's proxy, \`https://app.<host>/api/v1/storage/...\`:
|
|
66921
|
+
|
|
66922
|
+
\`\`\`typescript
|
|
66923
|
+
const browserStorageUrl = (url: string) =>
|
|
66924
|
+
url.replace(/^https:\\/\\/api\\.([^/]+)\\/v1\\/storage\\//, "https://app.$1/api/v1/storage/");
|
|
66925
|
+
\`\`\`
|
|
66926
|
+
|
|
66927
|
+
The edge also redirects a credential-less api.* read there, so an unrewritten link degrades to an extra hop rather than failing. The proxy authenticates with the signed-in session cookie, so it works for workspace members only. On a public page the visitor has no session: use \`presignFile\` for links there. Page code calling \`fetchFile\`, \`env.STORAGE.fetch\` or \`presignFile\` is unaffected either way \u2014 those carry their own credentials.
|
|
66928
|
+
|
|
66343
66929
|
## Known-Good Libraries
|
|
66344
66930
|
|
|
66345
66931
|
These libraries are tested and work from \`https://esm.sh/...\`. Do NOT import React \u2014 it's already global.
|
|
@@ -66349,10 +66935,15 @@ These libraries are tested and work from \`https://esm.sh/...\`. Do NOT import R
|
|
|
66349
66935
|
- **date-fns** \u2014 \`import { format, parseISO } from "https://esm.sh/date-fns@4"\` \u2014 Date formatting and manipulation.
|
|
66350
66936
|
- **papaparse** \u2014 \`import Papa from "https://esm.sh/papaparse@5"\` \u2014 CSV parsing.
|
|
66351
66937
|
|
|
66352
|
-
### Do NOT use
|
|
66938
|
+
### Do NOT use libraries that depend on React
|
|
66939
|
+
|
|
66940
|
+
An esm.sh build of a React library imports its own React (\`import "/react@>=16.8"\`), a second copy beside the page's global one, so every hook inside it fails with "Invalid hook call". The page has no import map to redirect that specifier, so there is no workaround. This rules out, among others:
|
|
66941
|
+
|
|
66353
66942
|
- **react-resize-detector** \u2014 Use a \`ResizeObserver\` hook instead (see pattern below).
|
|
66354
66943
|
- **@tanstack/react-table** \u2014 Build tables with plain \`<table>\` + Tailwind + \`useState\` for sorting/filtering/pagination.
|
|
66355
|
-
- **recharts, visx** \u2014 Use d3 directly instead.
|
|
66944
|
+
- **recharts, visx, and any other React chart or component kit** \u2014 Use d3 directly instead.
|
|
66945
|
+
|
|
66946
|
+
React-free libraries (d3, date-fns, papaparse) import fine.
|
|
66356
66947
|
|
|
66357
66948
|
### Responsive chart pattern
|
|
66358
66949
|
|
|
@@ -66683,38 +67274,17 @@ var runReview = async () => {
|
|
|
66683
67274
|
process.stdout.write("Nothing modified locally \u2014 nothing to review.\n");
|
|
66684
67275
|
return;
|
|
66685
67276
|
}
|
|
67277
|
+
const client = cliClient();
|
|
66686
67278
|
for (const target of lintTargets) {
|
|
66687
67279
|
try {
|
|
66688
|
-
const response = await
|
|
66689
|
-
|
|
66690
|
-
|
|
66691
|
-
|
|
66692
|
-
|
|
66693
|
-
surface: target.surface,
|
|
66694
|
-
workspaceId: manifest.workspaceId,
|
|
66695
|
-
functionOutputSchema: target.functionOutputSchema
|
|
66696
|
-
})
|
|
67280
|
+
const response = await client.lint({
|
|
67281
|
+
code: target.code,
|
|
67282
|
+
surface: target.surface,
|
|
67283
|
+
workspaceId: manifest.workspaceId,
|
|
67284
|
+
functionOutputSchema: target.functionOutputSchema
|
|
66697
67285
|
});
|
|
66698
|
-
const responseText = await response.text();
|
|
66699
|
-
if (!response.ok) {
|
|
66700
|
-
throw new Error(
|
|
66701
|
-
`${target.label}: HTTP ${String(response.status)}${responseText ? ` \u2014 ${responseText}` : ""}`
|
|
66702
|
-
);
|
|
66703
|
-
}
|
|
66704
|
-
const parsed = lintResponseSchema.safeParse(
|
|
66705
|
-
(() => {
|
|
66706
|
-
try {
|
|
66707
|
-
return JSON.parse(responseText);
|
|
66708
|
-
} catch {
|
|
66709
|
-
return null;
|
|
66710
|
-
}
|
|
66711
|
-
})()
|
|
66712
|
-
);
|
|
66713
|
-
if (!parsed.success) {
|
|
66714
|
-
throw new Error(`${target.label}: invalid response from lint service`);
|
|
66715
|
-
}
|
|
66716
67286
|
findings2.push(
|
|
66717
|
-
...
|
|
67287
|
+
...response.diagnostics.map(
|
|
66718
67288
|
(diagnostic) => `${target.label}:${String(diagnostic.line)}:${String(diagnostic.column)}: ${diagnostic.severity}: ${diagnostic.message}${diagnostic.ruleId == null ? "" : ` (${diagnostic.ruleId})`}`
|
|
66719
67289
|
)
|
|
66720
67290
|
);
|
|
@@ -66749,23 +67319,6 @@ var runReview = async () => {
|
|
|
66749
67319
|
import { createInterface as createInterface3 } from "readline";
|
|
66750
67320
|
|
|
66751
67321
|
// src/commands/sqlCredential.ts
|
|
66752
|
-
var connectionString = async (tableSpaceId, secret) => {
|
|
66753
|
-
const response = await v2Fetch("/v2/cluster-info");
|
|
66754
|
-
const body = await response.json();
|
|
66755
|
-
return `postgresql://overai:${encodeURIComponent(secret)}@${body.postgres.host}:${String(body.postgres.port)}/${tableSpaceId}?sslmode=${body.postgres.sslMode}${body.postgres.sslMode === "verify-full" ? "&sslrootcert=system" : ""}`;
|
|
66756
|
-
};
|
|
66757
|
-
var credentialTableSpaceId = async (credentialId) => {
|
|
66758
|
-
const data = await gqlRequest(
|
|
66759
|
-
`query TableSpaceCredential($id: String!) {
|
|
66760
|
-
tableSpaceCredential(id: $id) { tableSpaceId }
|
|
66761
|
-
}`,
|
|
66762
|
-
{ id: credentialId }
|
|
66763
|
-
);
|
|
66764
|
-
if (!data.tableSpaceCredential) {
|
|
66765
|
-
throw new Error("Credential not found or you lack access to it");
|
|
66766
|
-
}
|
|
66767
|
-
return data.tableSpaceCredential.tableSpaceId;
|
|
66768
|
-
};
|
|
66769
67322
|
var runSqlCredential = async (args) => {
|
|
66770
67323
|
const [action, id] = args;
|
|
66771
67324
|
if (!action || !id) {
|
|
@@ -66785,67 +67338,31 @@ var runSqlCredential = async (args) => {
|
|
|
66785
67338
|
if (!args.includes("--never") && (!Number.isInteger(days) || days < 1)) {
|
|
66786
67339
|
throw new Error("--expires-in must be a positive whole number of days");
|
|
66787
67340
|
}
|
|
66788
|
-
const
|
|
66789
|
-
|
|
66790
|
-
|
|
66791
|
-
|
|
66792
|
-
|
|
66793
|
-
|
|
66794
|
-
name: name2,
|
|
66795
|
-
validUntil: args.includes("--never") ? null : new Date(Date.now() + days * 864e5).toISOString()
|
|
66796
|
-
}
|
|
66797
|
-
);
|
|
66798
|
-
const result = data.createTableSpaceCredential?.result;
|
|
66799
|
-
if (!result) throw new Error("The server did not return a credential");
|
|
66800
|
-
process.stdout.write(
|
|
66801
|
-
`${await connectionString(tableSpaceId, result.secret)}
|
|
66802
|
-
`
|
|
66803
|
-
);
|
|
67341
|
+
const credential = await cliClient().tableSpace(tableSpaceId).credentials.create({
|
|
67342
|
+
name: name2,
|
|
67343
|
+
validUntil: args.includes("--never") ? null : new Date(Date.now() + days * 864e5)
|
|
67344
|
+
});
|
|
67345
|
+
process.stdout.write(`${credential.connectionString}
|
|
67346
|
+
`);
|
|
66804
67347
|
return;
|
|
66805
67348
|
}
|
|
66806
67349
|
if (action === "list") {
|
|
66807
67350
|
const tableSpaceId = id;
|
|
66808
|
-
const data = await gqlRequest(
|
|
66809
|
-
`query TableSpaceCredentials($tableSpaceId: String!) {
|
|
66810
|
-
tableSpaceCredentials(condition: { tableSpaceId: $tableSpaceId }) {
|
|
66811
|
-
nodes { id name validUntil lastUsedAt createdAt }
|
|
66812
|
-
}
|
|
66813
|
-
}`,
|
|
66814
|
-
{ tableSpaceId }
|
|
66815
|
-
);
|
|
66816
67351
|
printResult(
|
|
66817
|
-
|
|
67352
|
+
await cliClient().tableSpace(tableSpaceId).credentials.list(),
|
|
66818
67353
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
66819
67354
|
);
|
|
66820
67355
|
return;
|
|
66821
67356
|
}
|
|
66822
67357
|
if (action === "rotate") {
|
|
66823
|
-
const
|
|
66824
|
-
|
|
66825
|
-
const data = await gqlRequest(
|
|
66826
|
-
`mutation RotateTableSpaceCredential($credentialId: String!) {
|
|
66827
|
-
rotateTableSpaceCredential(input: { credentialId: $credentialId }) { result }
|
|
66828
|
-
}`,
|
|
66829
|
-
{ credentialId }
|
|
66830
|
-
);
|
|
66831
|
-
const secret = data.rotateTableSpaceCredential?.result;
|
|
66832
|
-
if (!secret) throw new Error("The server did not return a credential");
|
|
66833
|
-
process.stdout.write(`${await connectionString(tableSpaceId, secret)}
|
|
67358
|
+
const { connectionString: connectionString2 } = await cliClient().tableSpaceCredential(id).rotate();
|
|
67359
|
+
process.stdout.write(`${connectionString2}
|
|
66834
67360
|
`);
|
|
66835
67361
|
return;
|
|
66836
67362
|
}
|
|
66837
67363
|
if (action === "revoke") {
|
|
66838
|
-
|
|
66839
|
-
|
|
66840
|
-
await gqlRequest(
|
|
66841
|
-
`mutation RevokeTableSpaceCredential($id: String!, $validUntil: Datetime!) {
|
|
66842
|
-
updateTableSpaceCredential(input: { id: $id, patch: { validUntil: $validUntil } }) {
|
|
66843
|
-
tableSpaceCredential { id }
|
|
66844
|
-
}
|
|
66845
|
-
}`,
|
|
66846
|
-
{ id: credentialId, validUntil: (/* @__PURE__ */ new Date()).toISOString() }
|
|
66847
|
-
);
|
|
66848
|
-
process.stdout.write(`${credentialId} revoked
|
|
67364
|
+
await cliClient().tableSpaceCredential(id).revoke();
|
|
67365
|
+
process.stdout.write(`${id} revoked
|
|
66849
67366
|
`);
|
|
66850
67367
|
return;
|
|
66851
67368
|
}
|
|
@@ -66853,32 +67370,12 @@ var runSqlCredential = async (args) => {
|
|
|
66853
67370
|
};
|
|
66854
67371
|
|
|
66855
67372
|
// src/commands/sql.ts
|
|
66856
|
-
var runQuery = async (
|
|
66857
|
-
|
|
66858
|
-
|
|
66859
|
-
|
|
66860
|
-
|
|
66861
|
-
|
|
66862
|
-
body: JSON.stringify(
|
|
66863
|
-
params == null ? { query, ignoreCamelCase: true } : { unsafe: { query, params } }
|
|
66864
|
-
)
|
|
66865
|
-
}
|
|
66866
|
-
);
|
|
66867
|
-
const raw2 = await res.text();
|
|
66868
|
-
const body = (() => {
|
|
66869
|
-
try {
|
|
66870
|
-
return JSON.parse(raw2);
|
|
66871
|
-
} catch {
|
|
66872
|
-
return null;
|
|
66873
|
-
}
|
|
66874
|
-
})();
|
|
66875
|
-
if (!res.ok || body?.ok === false) throw v2Error("sql", res, raw2);
|
|
66876
|
-
return {
|
|
66877
|
-
rows: body?.rows ?? [],
|
|
66878
|
-
rowCount: body?.rowCount ?? 0,
|
|
66879
|
-
resultSetCount: body?.resultSetCount ?? 1,
|
|
66880
|
-
durationMs: body?.durationMs ?? 0
|
|
66881
|
-
};
|
|
67373
|
+
var runQuery = async (tableSpaceId, query, params) => {
|
|
67374
|
+
try {
|
|
67375
|
+
return await cliClient().tableSpace(tableSpaceId).sql(query, { params });
|
|
67376
|
+
} catch (error62) {
|
|
67377
|
+
throw withOrgHint(error62);
|
|
67378
|
+
}
|
|
66882
67379
|
};
|
|
66883
67380
|
var summarize = (result) => `(${String(result.rowCount)} row${result.rowCount === 1 ? "" : "s"}, ${String(result.durationMs)}ms)`;
|
|
66884
67381
|
var REPL_HELP = ` \\dt list tables
|
|
@@ -66888,7 +67385,7 @@ var REPL_HELP = ` \\dt list tables
|
|
|
66888
67385
|
Statements run when a line ends with ";". Each statement runs in its own
|
|
66889
67386
|
transaction \u2014 BEGIN/SET/temp tables don't carry across statements.
|
|
66890
67387
|
`;
|
|
66891
|
-
var runRepl = async (
|
|
67388
|
+
var runRepl = async (tableSpaceId, format2) => {
|
|
66892
67389
|
const interactive = process.stdin.isTTY;
|
|
66893
67390
|
const rl = createInterface3({
|
|
66894
67391
|
input: process.stdin,
|
|
@@ -66904,7 +67401,7 @@ var runRepl = async (organizationId, tableSpaceId, format2) => {
|
|
|
66904
67401
|
};
|
|
66905
67402
|
const execute = async (sql, params) => {
|
|
66906
67403
|
try {
|
|
66907
|
-
const result = await runQuery(
|
|
67404
|
+
const result = await runQuery(tableSpaceId, sql, params);
|
|
66908
67405
|
if (result.rows.length > 0) {
|
|
66909
67406
|
process.stdout.write(`${formatResult(result.rows, format2)}
|
|
66910
67407
|
`);
|
|
@@ -67008,7 +67505,7 @@ var runSql = async (args) => {
|
|
|
67008
67505
|
);
|
|
67009
67506
|
}
|
|
67010
67507
|
const format2 = resolveFormat(flagValue(args, "-o", "--output"));
|
|
67011
|
-
|
|
67508
|
+
await cliClient().organizationId();
|
|
67012
67509
|
const query = (() => {
|
|
67013
67510
|
const rest = args.slice(1);
|
|
67014
67511
|
for (let i = 0; i < rest.length; i++) {
|
|
@@ -67021,9 +67518,8 @@ var runSql = async (args) => {
|
|
|
67021
67518
|
}
|
|
67022
67519
|
return void 0;
|
|
67023
67520
|
})();
|
|
67024
|
-
if (query == null) return runRepl(
|
|
67521
|
+
if (query == null) return runRepl(tableSpaceId, format2);
|
|
67025
67522
|
const result = await runQuery(
|
|
67026
|
-
organizationId,
|
|
67027
67523
|
tableSpaceId,
|
|
67028
67524
|
await readValue(query, "the query") ?? query
|
|
67029
67525
|
);
|
|
@@ -67035,35 +67531,22 @@ var runSql = async (args) => {
|
|
|
67035
67531
|
};
|
|
67036
67532
|
|
|
67037
67533
|
// src/commands/storage.ts
|
|
67038
|
-
import { openAsBlob, writeFileSync as writeFileSync5 } from "fs";
|
|
67534
|
+
import { openAsBlob as openAsBlob3, writeFileSync as writeFileSync5 } from "fs";
|
|
67039
67535
|
var USAGE4 = "Usage: overai storage upload <path> [--no-random-prefix] | storage download <key> [path|-] | storage exists <key> | storage head <key> [--lines N] | storage presign <key> [--expires-in <seconds>]";
|
|
67040
67536
|
var runStorage = async (args) => {
|
|
67041
67537
|
const [operation, first2, second] = args;
|
|
67042
67538
|
if (operation == null) throw new Error(USAGE4);
|
|
67043
|
-
const
|
|
67044
|
-
const segment = (key) => encodeURIComponent(key);
|
|
67539
|
+
const storage = cliClient().storage;
|
|
67045
67540
|
if (operation === "upload") {
|
|
67046
67541
|
if (first2 == null || first2 === "-") {
|
|
67047
|
-
throw new Error(
|
|
67048
|
-
|
|
67049
|
-
|
|
67050
|
-
const query = randomPrefix ? "" : "?disableRandomPrefix=true";
|
|
67051
|
-
const response = await v2Fetch(
|
|
67052
|
-
`/v2/storage/${organizationId}/stream${query}`,
|
|
67053
|
-
{
|
|
67054
|
-
method: "POST",
|
|
67055
|
-
headers: {
|
|
67056
|
-
"Content-Type": "application/octet-stream",
|
|
67057
|
-
"x-file-name": first2.split("/").pop() ?? first2
|
|
67058
|
-
},
|
|
67059
|
-
body: await openAsBlob(first2)
|
|
67060
|
-
}
|
|
67061
|
-
);
|
|
67062
|
-
if (!response.ok) {
|
|
67063
|
-
throw v2Error("storage upload", response, await response.text());
|
|
67542
|
+
throw new Error(
|
|
67543
|
+
"Upload requires a file path (stdin uploads need a filename to build the key)."
|
|
67544
|
+
);
|
|
67064
67545
|
}
|
|
67065
|
-
const { path } = await
|
|
67066
|
-
|
|
67546
|
+
const { key, path } = await storage.upload(await openAsBlob3(first2), {
|
|
67547
|
+
name: first2.split("/").pop() ?? first2,
|
|
67548
|
+
randomPrefix: !args.includes("--no-random-prefix")
|
|
67549
|
+
});
|
|
67067
67550
|
const format2 = resolveFormat(flagValue(args, "-o", "--output"));
|
|
67068
67551
|
if (format2 === "json") printResult({ key, path }, format2);
|
|
67069
67552
|
else process.stdout.write(`${key}
|
|
@@ -67072,59 +67555,38 @@ var runStorage = async (args) => {
|
|
|
67072
67555
|
}
|
|
67073
67556
|
if (first2 == null) throw new Error(USAGE4);
|
|
67074
67557
|
if (operation === "download") {
|
|
67075
|
-
const response = await
|
|
67076
|
-
`/v2/storage/${organizationId}/${segment(first2)}`,
|
|
67077
|
-
{ redirect: "follow" }
|
|
67078
|
-
);
|
|
67079
|
-
if (!response.ok) {
|
|
67080
|
-
throw v2Error("storage download", response, await response.text());
|
|
67081
|
-
}
|
|
67558
|
+
const response = await storage.download(first2);
|
|
67082
67559
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
67083
67560
|
if (second != null && second !== "-") writeFileSync5(second, bytes);
|
|
67084
67561
|
else process.stdout.write(bytes);
|
|
67085
67562
|
return;
|
|
67086
67563
|
}
|
|
67087
67564
|
if (operation === "exists") {
|
|
67088
|
-
const
|
|
67089
|
-
|
|
67090
|
-
);
|
|
67091
|
-
if (response.status === 404) {
|
|
67565
|
+
const meta3 = await storage.exists(first2);
|
|
67566
|
+
if (meta3 == null) {
|
|
67092
67567
|
if (resolveFormat(flagValue(args, "-o", "--output")) === "json") {
|
|
67093
67568
|
printResult({ exists: false }, "json");
|
|
67094
67569
|
}
|
|
67095
67570
|
process.exitCode = 1;
|
|
67096
67571
|
return;
|
|
67097
67572
|
}
|
|
67098
|
-
if (!response.ok) {
|
|
67099
|
-
throw v2Error("storage exists", response, await response.text());
|
|
67100
|
-
}
|
|
67101
67573
|
printResult(
|
|
67102
|
-
{ exists: true, ...
|
|
67574
|
+
{ exists: true, ...meta3 },
|
|
67103
67575
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
67104
67576
|
);
|
|
67105
67577
|
return;
|
|
67106
67578
|
}
|
|
67107
67579
|
if (operation === "head") {
|
|
67108
|
-
|
|
67109
|
-
|
|
67110
|
-
`/v2/storage/${organizationId}/${segment(first2)}/head?numLines=${encodeURIComponent(lines)}`
|
|
67580
|
+
process.stdout.write(
|
|
67581
|
+
await storage.head(first2, { lines: integerFlag(args, "--lines", 50) })
|
|
67111
67582
|
);
|
|
67112
|
-
if (!response.ok) {
|
|
67113
|
-
throw v2Error("storage head", response, await response.text());
|
|
67114
|
-
}
|
|
67115
|
-
process.stdout.write(await response.text());
|
|
67116
67583
|
return;
|
|
67117
67584
|
}
|
|
67118
67585
|
if (operation === "presign") {
|
|
67119
|
-
|
|
67120
|
-
|
|
67121
|
-
|
|
67586
|
+
process.stdout.write(
|
|
67587
|
+
`${await storage.presign(first2, { expiresIn: integerFlag(args, "--expires-in", 60 * 60 * 24 * 7) })}
|
|
67588
|
+
`
|
|
67122
67589
|
);
|
|
67123
|
-
if (!response.ok) {
|
|
67124
|
-
throw v2Error("storage presign", response, await response.text());
|
|
67125
|
-
}
|
|
67126
|
-
process.stdout.write(`${(await response.text()).trim()}
|
|
67127
|
-
`);
|
|
67128
67590
|
return;
|
|
67129
67591
|
}
|
|
67130
67592
|
throw new Error(USAGE4);
|
|
@@ -67136,7 +67598,7 @@ var workspaceIdFrom = (args) => args.find(
|
|
|
67136
67598
|
) ?? openClone().manifest.workspaceId;
|
|
67137
67599
|
var listWorkspaces = async (args) => {
|
|
67138
67600
|
const archived = args.includes("--archived");
|
|
67139
|
-
const limit2 =
|
|
67601
|
+
const limit2 = integerFlag(args, "--limit", 200);
|
|
67140
67602
|
printResult(
|
|
67141
67603
|
(await cliClient().workspaces.list({
|
|
67142
67604
|
first: limit2,
|
|
@@ -67312,7 +67774,8 @@ Usage:
|
|
|
67312
67774
|
overai sql credential rotate|revoke <credentialId>
|
|
67313
67775
|
|
|
67314
67776
|
Workspace sync (edit resources as local files):
|
|
67315
|
-
overai clone <workspaceId> [dir] Clone workspace and accessible descendants
|
|
67777
|
+
overai clone <workspaceId> [dir] Clone workspace and accessible descendants;
|
|
67778
|
+
.overai/ holds sync state, ignored by git
|
|
67316
67779
|
overai status [--recursive] Local edits + remote drift
|
|
67317
67780
|
overai diff [filter] [--from <ref>] [--to <ref>] [--recursive]
|
|
67318
67781
|
Diff versions (refs: N, base, local, deployed, latest;
|