@overaihq/cli 0.14.14 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1158 -15
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -38209,7 +38209,7 @@ var agentToolRequestSchema = external_exports.object({
|
|
|
38209
38209
|
path: external_exports.string().prefault("/").transform((p) => p.startsWith("/") ? p : `/${p}`),
|
|
38210
38210
|
headers: external_exports.record(external_exports.string(), external_exports.string()).prefault({}),
|
|
38211
38211
|
queryParams: external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean()])).prefault({}),
|
|
38212
|
-
body: external_exports.unknown()
|
|
38212
|
+
body: external_exports.unknown().optional()
|
|
38213
38213
|
});
|
|
38214
38214
|
var agentToolRequestJsonSchemaSchema = external_exports.object({
|
|
38215
38215
|
type: external_exports.literal("object"),
|
|
@@ -43967,6 +43967,10 @@ var consoleLogsPayloadSchema = external_exports.object({
|
|
|
43967
43967
|
var runtimeErrorPayloadSchema = external_exports.object({
|
|
43968
43968
|
error: external_exports.string().nullable()
|
|
43969
43969
|
});
|
|
43970
|
+
var hostShortcutPayloadSchema = external_exports.enum([
|
|
43971
|
+
"commandPalette",
|
|
43972
|
+
"architect"
|
|
43973
|
+
]);
|
|
43970
43974
|
var pageInteractionPayloadSchema = external_exports.object({
|
|
43971
43975
|
clicks: external_exports.number().int().min(0),
|
|
43972
43976
|
keypresses: external_exports.number().int().min(0)
|
|
@@ -45112,6 +45116,8 @@ var NodeEnum = /* @__PURE__ */ ((NodeEnum2) => {
|
|
|
45112
45116
|
NodeEnum2["readFoldersFromLocalFolder"] = "READ_FOLDERS_FROM_LOCAL_FOLDER";
|
|
45113
45117
|
NodeEnum2["redisAction"] = "REDIS_ACTION";
|
|
45114
45118
|
NodeEnum2["renameLocalFile"] = "RENAME_LOCAL_FILE";
|
|
45119
|
+
NodeEnum2["ringcentralAction"] = "RINGCENTRAL_ACTION";
|
|
45120
|
+
NodeEnum2["ringcentralQuery"] = "RINGCENTRAL_QUERY";
|
|
45115
45121
|
NodeEnum2["runContainerScript"] = "RUN_CONTAINER_SCRIPT";
|
|
45116
45122
|
NodeEnum2["runFunction"] = "RUN_FUNCTION";
|
|
45117
45123
|
NodeEnum2["runTableSpaceQuery"] = "RUN_TABLE_SPACE_QUERY";
|
|
@@ -45319,7 +45325,7 @@ var automationNodeSchema = external_exports.lazy(
|
|
|
45319
45325
|
var automationNodesSchema = external_exports.array(automationNodeSchema);
|
|
45320
45326
|
var iterationStateSchema = external_exports.object({
|
|
45321
45327
|
iteration: external_exports.number().int(),
|
|
45322
|
-
iteratee: external_exports.any(),
|
|
45328
|
+
iteratee: external_exports.any().nonoptional(),
|
|
45323
45329
|
state: external_exports.lazy(() => automationStateSchema),
|
|
45324
45330
|
/**
|
|
45325
45331
|
* Set when a completed iteration's `state` is compacted to `{}` to keep the
|
|
@@ -60689,6 +60695,58 @@ var printablePageRender = (client, id) => ({
|
|
|
60689
60695
|
}
|
|
60690
60696
|
});
|
|
60691
60697
|
|
|
60698
|
+
// ../sdk/src/references.ts
|
|
60699
|
+
var referencesSchema = external_exports.object({
|
|
60700
|
+
inbound: external_exports.array(
|
|
60701
|
+
external_exports.object({
|
|
60702
|
+
resourceId: external_exports.string(),
|
|
60703
|
+
referencerId: external_exports.string(),
|
|
60704
|
+
referencerKind: external_exports.string(),
|
|
60705
|
+
referencerName: external_exports.string(),
|
|
60706
|
+
referencerWorkspaceId: external_exports.string()
|
|
60707
|
+
})
|
|
60708
|
+
),
|
|
60709
|
+
outbound: external_exports.array(
|
|
60710
|
+
external_exports.object({
|
|
60711
|
+
resourceId: external_exports.string(),
|
|
60712
|
+
targetId: external_exports.string(),
|
|
60713
|
+
targetKind: external_exports.string(),
|
|
60714
|
+
targetName: external_exports.string(),
|
|
60715
|
+
targetWorkspaceId: external_exports.string()
|
|
60716
|
+
})
|
|
60717
|
+
)
|
|
60718
|
+
});
|
|
60719
|
+
var resourceReferences = async (client, resourceIds, options) => resourceIds.length === 0 ? { inbound: [], outbound: [] } : referencesSchema.parse(
|
|
60720
|
+
await client.trpc("getResourceReferences", {
|
|
60721
|
+
resourceIds,
|
|
60722
|
+
referencerWorkspaceIds: options?.referencerWorkspaceIds
|
|
60723
|
+
})
|
|
60724
|
+
);
|
|
60725
|
+
var agentToolReachSchema = external_exports.array(
|
|
60726
|
+
external_exports.object({
|
|
60727
|
+
agentId: external_exports.string(),
|
|
60728
|
+
agentName: external_exports.string(),
|
|
60729
|
+
agentWorkspaceId: external_exports.string(),
|
|
60730
|
+
tools: external_exports.array(
|
|
60731
|
+
external_exports.object({
|
|
60732
|
+
kind: external_exports.string(),
|
|
60733
|
+
id: external_exports.string(),
|
|
60734
|
+
name: external_exports.string(),
|
|
60735
|
+
accessMode: external_exports.string().nullable(),
|
|
60736
|
+
isReachable: external_exports.boolean(),
|
|
60737
|
+
isReachableFromTarget: external_exports.boolean().nullable()
|
|
60738
|
+
})
|
|
60739
|
+
),
|
|
60740
|
+
hiddenCount: external_exports.number(),
|
|
60741
|
+
hiddenUnreachableCount: external_exports.number(),
|
|
60742
|
+
hiddenLostAtTargetCount: external_exports.number(),
|
|
60743
|
+
canShareIntoTarget: external_exports.boolean()
|
|
60744
|
+
})
|
|
60745
|
+
);
|
|
60746
|
+
var agentToolReach = async (client, agentIds, targetWorkspaceId) => agentToolReachSchema.parse(
|
|
60747
|
+
await client.trpc("getAgentToolReach", { agentIds, targetWorkspaceId })
|
|
60748
|
+
);
|
|
60749
|
+
|
|
60692
60750
|
// ../sdk/src/report.ts
|
|
60693
60751
|
var report = async (client, kind, details, options) => {
|
|
60694
60752
|
await client.trpc("architectIssues.report", {
|
|
@@ -60773,6 +60831,7 @@ var ID_PREFIXES = {
|
|
|
60773
60831
|
knowledge_base: { prefix: "kb", body: 10 },
|
|
60774
60832
|
knowledge_base_chunk: { prefix: "kbc", body: 20 },
|
|
60775
60833
|
knowledge_base_document: { prefix: "kbd", body: 20 },
|
|
60834
|
+
library: { prefix: "lib", body: 10 },
|
|
60776
60835
|
mailbox: { prefix: "mbx", body: 10 },
|
|
60777
60836
|
mailbox_address: { prefix: "mba", body: 10 },
|
|
60778
60837
|
mailbox_message: { prefix: "mbm", body: 10 },
|
|
@@ -60852,6 +60911,153 @@ var idTableByPrefix = (id) => {
|
|
|
60852
60911
|
return best?.table ?? null;
|
|
60853
60912
|
};
|
|
60854
60913
|
|
|
60914
|
+
// ../sdk/src/resourceGroups.ts
|
|
60915
|
+
var memberKind = (table) => table.replace(/_(\w)/g, (_, letter) => letter.toUpperCase());
|
|
60916
|
+
var resolveMember = async (client, resourceId) => {
|
|
60917
|
+
const row = await client.resource(resourceId).show();
|
|
60918
|
+
const table = idTableByPrefix(row.id);
|
|
60919
|
+
if (table == null) throw new Error(`Unsupported resource id: ${resourceId}`);
|
|
60920
|
+
return {
|
|
60921
|
+
member: { resourceKind: memberKind(table), resourceId: row.id },
|
|
60922
|
+
workspaceId: row.workspaceId
|
|
60923
|
+
};
|
|
60924
|
+
};
|
|
60925
|
+
var membershipOf = async (client, member) => {
|
|
60926
|
+
const data = await client.graphql(
|
|
60927
|
+
`query SdkResourceGroupMembership($resourceKind: String!, $resourceId: String!) {
|
|
60928
|
+
resourceGroupMembers(condition: { resourceKind: $resourceKind, resourceId: $resourceId }) {
|
|
60929
|
+
nodes { groupId group { name } }
|
|
60930
|
+
}
|
|
60931
|
+
}`,
|
|
60932
|
+
{ ...member }
|
|
60933
|
+
);
|
|
60934
|
+
const row = data.resourceGroupMembers?.nodes[0];
|
|
60935
|
+
return row == null ? null : { ...member, groupId: row.groupId, groupName: row.group?.name ?? null };
|
|
60936
|
+
};
|
|
60937
|
+
var removeMembership = async (client, member) => {
|
|
60938
|
+
const membership = await membershipOf(client, member);
|
|
60939
|
+
if (membership == null) return null;
|
|
60940
|
+
await client.graphql(
|
|
60941
|
+
`mutation SdkRemoveResourceGroupMember($resourceKind: String!, $resourceId: String!) {
|
|
60942
|
+
deleteResourceGroupMember(input: { resourceKind: $resourceKind, resourceId: $resourceId }) {
|
|
60943
|
+
deletedResourceGroupMemberNodeId
|
|
60944
|
+
}
|
|
60945
|
+
}`,
|
|
60946
|
+
{ ...member }
|
|
60947
|
+
);
|
|
60948
|
+
return membership;
|
|
60949
|
+
};
|
|
60950
|
+
var removeResourceFromGroup = async (client, storedId) => {
|
|
60951
|
+
const table = idTableByPrefix(storedId);
|
|
60952
|
+
return table == null ? null : removeMembership(client, {
|
|
60953
|
+
resourceKind: memberKind(table),
|
|
60954
|
+
resourceId: storedId
|
|
60955
|
+
});
|
|
60956
|
+
};
|
|
60957
|
+
var resourceGroupCollection = (client) => ({
|
|
60958
|
+
list: async (options) => {
|
|
60959
|
+
const data = await client.graphql(
|
|
60960
|
+
`query SdkResourceGroups($condition: ResourceGroupCondition) {
|
|
60961
|
+
resourceGroups(condition: $condition) {
|
|
60962
|
+
nodes {
|
|
60963
|
+
id name workspaceId
|
|
60964
|
+
resourceGroupMembersByGroupId { nodes { resourceKind resourceId } }
|
|
60965
|
+
}
|
|
60966
|
+
}
|
|
60967
|
+
}`,
|
|
60968
|
+
{
|
|
60969
|
+
condition: options?.workspaceId == null ? null : { workspaceId: options.workspaceId }
|
|
60970
|
+
}
|
|
60971
|
+
);
|
|
60972
|
+
return (data.resourceGroups?.nodes ?? []).map((group) => ({
|
|
60973
|
+
id: group.id,
|
|
60974
|
+
name: group.name,
|
|
60975
|
+
workspaceId: group.workspaceId,
|
|
60976
|
+
members: group.resourceGroupMembersByGroupId.nodes
|
|
60977
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
60978
|
+
},
|
|
60979
|
+
create: async (input2) => {
|
|
60980
|
+
const data = await client.graphql(
|
|
60981
|
+
`mutation SdkCreateResourceGroup($workspaceId: String!, $name: String!) {
|
|
60982
|
+
createResourceGroup(input: { resourceGroup: { workspaceId: $workspaceId, name: $name } }) {
|
|
60983
|
+
resourceGroup { id }
|
|
60984
|
+
}
|
|
60985
|
+
}`,
|
|
60986
|
+
input2
|
|
60987
|
+
);
|
|
60988
|
+
const id = data.createResourceGroup?.resourceGroup?.id;
|
|
60989
|
+
if (id == null) throw new Error("createResourceGroup returned no group.");
|
|
60990
|
+
return { id };
|
|
60991
|
+
},
|
|
60992
|
+
membershipOf: async (resourceId) => membershipOf(client, (await resolveMember(client, resourceId)).member),
|
|
60993
|
+
removeMember: async (resourceId) => removeMembership(client, (await resolveMember(client, resourceId)).member)
|
|
60994
|
+
});
|
|
60995
|
+
var resourceGroupResource = (client, id) => ({
|
|
60996
|
+
id,
|
|
60997
|
+
rename: async (name2) => {
|
|
60998
|
+
const data = await client.graphql(
|
|
60999
|
+
`mutation SdkRenameResourceGroup($id: String!, $name: String!) {
|
|
61000
|
+
updateResourceGroup(input: { id: $id, patch: { name: $name } }) { resourceGroup { id } }
|
|
61001
|
+
}`,
|
|
61002
|
+
{ id, name: name2 }
|
|
61003
|
+
);
|
|
61004
|
+
if (data.updateResourceGroup?.resourceGroup == null) {
|
|
61005
|
+
throw new Error(`Resource group ${id} was not renamed.`);
|
|
61006
|
+
}
|
|
61007
|
+
},
|
|
61008
|
+
delete: async () => {
|
|
61009
|
+
await client.graphql(
|
|
61010
|
+
`mutation SdkDeleteResourceGroup($id: String!) {
|
|
61011
|
+
deleteResourceGroup(input: { id: $id }) { deletedResourceGroupNodeId }
|
|
61012
|
+
}`,
|
|
61013
|
+
{ id }
|
|
61014
|
+
);
|
|
61015
|
+
},
|
|
61016
|
+
add: async (resourceIds) => {
|
|
61017
|
+
const data = await client.graphql(
|
|
61018
|
+
`query SdkResourceGroupWorkspace($id: String!) {
|
|
61019
|
+
resourceGroup(id: $id) { workspaceId }
|
|
61020
|
+
}`,
|
|
61021
|
+
{ id }
|
|
61022
|
+
);
|
|
61023
|
+
const groupWorkspaceId = data.resourceGroup?.workspaceId;
|
|
61024
|
+
if (groupWorkspaceId == null) {
|
|
61025
|
+
throw new Error(
|
|
61026
|
+
`Resource group ${id} not found (or not editable by you).`
|
|
61027
|
+
);
|
|
61028
|
+
}
|
|
61029
|
+
const resolved = await Promise.all(
|
|
61030
|
+
resourceIds.map(async (resourceId) => ({
|
|
61031
|
+
resourceId,
|
|
61032
|
+
...await resolveMember(client, resourceId)
|
|
61033
|
+
}))
|
|
61034
|
+
);
|
|
61035
|
+
const misplaced = resolved.filter(
|
|
61036
|
+
(entry) => entry.workspaceId !== groupWorkspaceId
|
|
61037
|
+
);
|
|
61038
|
+
if (misplaced.length > 0) {
|
|
61039
|
+
throw new Error(
|
|
61040
|
+
`${misplaced.map(
|
|
61041
|
+
(entry) => `${entry.resourceId} is in workspace ${String(entry.workspaceId)}`
|
|
61042
|
+
).join("; ")}, but group ${id} is in ${groupWorkspaceId}. Move ${misplaced.length === 1 ? "it" : "them"} to that workspace first.`
|
|
61043
|
+
);
|
|
61044
|
+
}
|
|
61045
|
+
const previous = [];
|
|
61046
|
+
for (const { member } of resolved) {
|
|
61047
|
+
previous.push(await removeMembership(client, member));
|
|
61048
|
+
await client.graphql(
|
|
61049
|
+
`mutation SdkAddResourceGroupMember($member: ResourceGroupMemberInput!) {
|
|
61050
|
+
createResourceGroupMember(input: { resourceGroupMember: $member }) {
|
|
61051
|
+
resourceGroupMember { groupId }
|
|
61052
|
+
}
|
|
61053
|
+
}`,
|
|
61054
|
+
{ member: { groupId: id, ...member } }
|
|
61055
|
+
);
|
|
61056
|
+
}
|
|
61057
|
+
return previous;
|
|
61058
|
+
}
|
|
61059
|
+
});
|
|
61060
|
+
|
|
60855
61061
|
// ../sdk/src/resourceShow.ts
|
|
60856
61062
|
var resourceTables = {
|
|
60857
61063
|
workspace: {
|
|
@@ -61015,7 +61221,33 @@ var genericResource = (client, id) => {
|
|
|
61015
61221
|
throw new Error(`No supported changes supplied for ${id}.`);
|
|
61016
61222
|
}
|
|
61017
61223
|
return show(current.id);
|
|
61018
|
-
}
|
|
61224
|
+
},
|
|
61225
|
+
move: async (workspaceId) => {
|
|
61226
|
+
const resource = resourceTableFor(id);
|
|
61227
|
+
if (resource === resourceTables.workspace) {
|
|
61228
|
+
throw new Error(
|
|
61229
|
+
`${id} is a workspace; reparent it instead of moving it.`
|
|
61230
|
+
);
|
|
61231
|
+
}
|
|
61232
|
+
const current = await show(id);
|
|
61233
|
+
const result = await client.graphql(
|
|
61234
|
+
`mutation SdkMoveResource($id: String!, $workspaceId: String!) {
|
|
61235
|
+
${resource.mutation}(input: { id: $id, patch: { workspaceId: $workspaceId } }) {
|
|
61236
|
+
updated: ${resource.result} { id workspaceId }
|
|
61237
|
+
}
|
|
61238
|
+
}`,
|
|
61239
|
+
{ id: current.id, workspaceId }
|
|
61240
|
+
);
|
|
61241
|
+
const updated = result[resource.mutation]?.updated;
|
|
61242
|
+
if (updated == null) {
|
|
61243
|
+
throw new Error(
|
|
61244
|
+
`Resource ${id} was not moved; check that you can edit both workspaces.`
|
|
61245
|
+
);
|
|
61246
|
+
}
|
|
61247
|
+
const leftGroup = await removeResourceFromGroup(client, current.id);
|
|
61248
|
+
return { ...updated, leftGroup };
|
|
61249
|
+
},
|
|
61250
|
+
references: () => resourceReferences(client, [id])
|
|
61019
61251
|
};
|
|
61020
61252
|
};
|
|
61021
61253
|
|
|
@@ -61318,9 +61550,137 @@ var tableSpaceCredentialResource = (client, credentialId) => {
|
|
|
61318
61550
|
var exchangeSchema = external_exports.object({ token: external_exports.string(), expiresIn: external_exports.number() });
|
|
61319
61551
|
var staticToken = (jwt2) => () => jwt2;
|
|
61320
61552
|
|
|
61553
|
+
// ../sdk/src/paginate.ts
|
|
61554
|
+
var paginate = async (client, query, field, variables = {}) => {
|
|
61555
|
+
const nodes = [];
|
|
61556
|
+
let after = null;
|
|
61557
|
+
do {
|
|
61558
|
+
const data = await client.graphql(
|
|
61559
|
+
query,
|
|
61560
|
+
{ ...variables, after }
|
|
61561
|
+
);
|
|
61562
|
+
const connection = data[field];
|
|
61563
|
+
if (connection == null) return nodes;
|
|
61564
|
+
nodes.push(...connection.nodes);
|
|
61565
|
+
const page = connection.pageInfo;
|
|
61566
|
+
if (page.hasNextPage && (page.endCursor == null || page.endCursor === after))
|
|
61567
|
+
throw new Error(`${field} pagination did not advance.`);
|
|
61568
|
+
after = page.hasNextPage ? page.endCursor : null;
|
|
61569
|
+
} while (after != null);
|
|
61570
|
+
return nodes;
|
|
61571
|
+
};
|
|
61572
|
+
|
|
61321
61573
|
// ../sdk/src/workspaces.ts
|
|
61574
|
+
var SHARE_KINDS = [
|
|
61575
|
+
"table_space",
|
|
61576
|
+
"function",
|
|
61577
|
+
"agent",
|
|
61578
|
+
"integration",
|
|
61579
|
+
"action_runner"
|
|
61580
|
+
];
|
|
61581
|
+
var SHARE_FIELDS = "id fromWorkspaceId toWorkspaceId resourceKind resourceId fromWorkspace { name } toWorkspace { name }";
|
|
61582
|
+
var shareFromRow = (row) => ({
|
|
61583
|
+
id: row.id,
|
|
61584
|
+
fromWorkspaceId: row.fromWorkspaceId,
|
|
61585
|
+
fromWorkspaceName: row.fromWorkspace?.name ?? null,
|
|
61586
|
+
toWorkspaceId: row.toWorkspaceId,
|
|
61587
|
+
toWorkspaceName: row.toWorkspace?.name ?? null,
|
|
61588
|
+
resourceKind: row.resourceKind,
|
|
61589
|
+
resourceId: row.resourceId
|
|
61590
|
+
});
|
|
61591
|
+
var storedShareEnds = async (client, from, to) => {
|
|
61592
|
+
const data = await client.graphql(
|
|
61593
|
+
`query SdkShareWorkspaceIds($from: String!, $to: String!) {
|
|
61594
|
+
from: workspaces(condition: { idIgnoringCase: $from }, includeArchived: YES, first: 1) { nodes { id } }
|
|
61595
|
+
to: workspaces(condition: { idIgnoringCase: $to }, includeArchived: YES, first: 1) { nodes { id } }
|
|
61596
|
+
}`,
|
|
61597
|
+
{ from, to }
|
|
61598
|
+
);
|
|
61599
|
+
const stored = {
|
|
61600
|
+
from: data.from?.nodes[0]?.id,
|
|
61601
|
+
to: data.to?.nodes[0]?.id
|
|
61602
|
+
};
|
|
61603
|
+
if (stored.from == null) {
|
|
61604
|
+
throw new Error(`Workspace ${from} not found (or not visible to you).`);
|
|
61605
|
+
}
|
|
61606
|
+
if (stored.to == null) {
|
|
61607
|
+
throw new Error(`Workspace ${to} not found (or not visible to you).`);
|
|
61608
|
+
}
|
|
61609
|
+
return { from: stored.from, to: stored.to };
|
|
61610
|
+
};
|
|
61611
|
+
var workspaceTree = async (client, includeArchived) => {
|
|
61612
|
+
const [workspaces, edges, roles] = await Promise.all([
|
|
61613
|
+
paginate(
|
|
61614
|
+
client,
|
|
61615
|
+
`query SdkWorkspaceTreeNodes($after: Cursor, $includeArchived: IncludeArchivedOption!) {
|
|
61616
|
+
workspaces(first: 100, after: $after, includeArchived: $includeArchived) {
|
|
61617
|
+
nodes { id name isArchived }
|
|
61618
|
+
pageInfo { hasNextPage endCursor }
|
|
61619
|
+
}
|
|
61620
|
+
}`,
|
|
61621
|
+
"workspaces",
|
|
61622
|
+
{ includeArchived: includeArchived ? "YES" : "NO" }
|
|
61623
|
+
),
|
|
61624
|
+
paginate(
|
|
61625
|
+
client,
|
|
61626
|
+
`query SdkWorkspaceTreeEdges($after: Cursor) {
|
|
61627
|
+
workspaceWorkspaces(first: 100, after: $after) {
|
|
61628
|
+
nodes { workspaceId parentWorkspaceId }
|
|
61629
|
+
pageInfo { hasNextPage endCursor }
|
|
61630
|
+
}
|
|
61631
|
+
}`,
|
|
61632
|
+
"workspaceWorkspaces"
|
|
61633
|
+
),
|
|
61634
|
+
client.graphql(
|
|
61635
|
+
`query SdkWorkspaceTreeRoles { myWorkspaceRoles { nodes { workspaceId role } } }`
|
|
61636
|
+
)
|
|
61637
|
+
]);
|
|
61638
|
+
const role = new Map(
|
|
61639
|
+
roles.myWorkspaceRoles.nodes.map((r) => [r.workspaceId, r.role])
|
|
61640
|
+
);
|
|
61641
|
+
const parentOf = new Map(
|
|
61642
|
+
edges.map((e) => [e.workspaceId, e.parentWorkspaceId])
|
|
61643
|
+
);
|
|
61644
|
+
const nodes = new Map(
|
|
61645
|
+
workspaces.map((w) => [
|
|
61646
|
+
w.id,
|
|
61647
|
+
{
|
|
61648
|
+
id: w.id,
|
|
61649
|
+
name: w.name,
|
|
61650
|
+
isArchived: w.isArchived,
|
|
61651
|
+
role: role.get(w.id) ?? null,
|
|
61652
|
+
parentWorkspaceId: null,
|
|
61653
|
+
children: []
|
|
61654
|
+
}
|
|
61655
|
+
])
|
|
61656
|
+
);
|
|
61657
|
+
const roots = [...nodes.values()].filter((node2) => {
|
|
61658
|
+
const parent = nodes.get(parentOf.get(node2.id) ?? "");
|
|
61659
|
+
if (parent == null) return true;
|
|
61660
|
+
node2.parentWorkspaceId = parent.id;
|
|
61661
|
+
parent.children.push(node2);
|
|
61662
|
+
return false;
|
|
61663
|
+
});
|
|
61664
|
+
const sort2 = (list) => {
|
|
61665
|
+
list.sort((a, b) => a.name.localeCompare(b.name));
|
|
61666
|
+
list.forEach((node2) => sort2(node2.children));
|
|
61667
|
+
return list;
|
|
61668
|
+
};
|
|
61669
|
+
return sort2(roots);
|
|
61670
|
+
};
|
|
61322
61671
|
var workspaceCollection = (client) => ({
|
|
61323
61672
|
create: (input2) => createWorkspace(client, input2),
|
|
61673
|
+
tree: (options) => workspaceTree(client, options?.includeArchived === true),
|
|
61674
|
+
shares: async () => (await paginate(
|
|
61675
|
+
client,
|
|
61676
|
+
`query SdkAllWorkspaceShares($after: Cursor) {
|
|
61677
|
+
workspaceResourceShares(first: 100, after: $after) {
|
|
61678
|
+
nodes { ${SHARE_FIELDS} }
|
|
61679
|
+
pageInfo { hasNextPage endCursor }
|
|
61680
|
+
}
|
|
61681
|
+
}`,
|
|
61682
|
+
"workspaceResourceShares"
|
|
61683
|
+
)).map(shareFromRow),
|
|
61324
61684
|
list: async (options) => {
|
|
61325
61685
|
const data = await client.graphql(
|
|
61326
61686
|
`query SdkWorkspaceList($first: Int!, $includeArchived: IncludeArchivedOption!) {
|
|
@@ -61394,6 +61754,109 @@ var workspaceResource = (client, id) => ({
|
|
|
61394
61754
|
}
|
|
61395
61755
|
]
|
|
61396
61756
|
);
|
|
61757
|
+
},
|
|
61758
|
+
tree: async (options) => {
|
|
61759
|
+
const find2 = (list) => list.map(
|
|
61760
|
+
(node3) => node3.id.toLowerCase() === id.toLowerCase() ? node3 : find2(node3.children)
|
|
61761
|
+
).find((node3) => node3 != null);
|
|
61762
|
+
const node2 = find2(
|
|
61763
|
+
await workspaceTree(client, options?.includeArchived === true)
|
|
61764
|
+
);
|
|
61765
|
+
if (node2 == null) {
|
|
61766
|
+
throw new Error(`Workspace ${id} not found (or not visible to you).`);
|
|
61767
|
+
}
|
|
61768
|
+
return node2;
|
|
61769
|
+
},
|
|
61770
|
+
setParent: async (parentWorkspaceId) => {
|
|
61771
|
+
const data = await client.graphql(
|
|
61772
|
+
`mutation SdkSetWorkspaceParent($workspaceId: String!, $parentWorkspaceId: String!) {
|
|
61773
|
+
setWorkspaceParent(input: { workspaceId: $workspaceId, parentWorkspaceId: $parentWorkspaceId }) {
|
|
61774
|
+
workspaceWorkspace { workspaceId }
|
|
61775
|
+
}
|
|
61776
|
+
}`,
|
|
61777
|
+
{ workspaceId: id, parentWorkspaceId }
|
|
61778
|
+
);
|
|
61779
|
+
if (data.setWorkspaceParent?.workspaceWorkspace == null) {
|
|
61780
|
+
throw new Error(
|
|
61781
|
+
`Workspace ${id} was not moved; check that you manage both workspaces.`
|
|
61782
|
+
);
|
|
61783
|
+
}
|
|
61784
|
+
},
|
|
61785
|
+
moveToRoot: async () => {
|
|
61786
|
+
const data = await client.graphql(
|
|
61787
|
+
`mutation SdkMoveWorkspaceToRoot($workspaceId: String!) {
|
|
61788
|
+
deleteWorkspaceWorkspaceByWorkspaceId(input: { workspaceId: $workspaceId }) {
|
|
61789
|
+
workspaceWorkspace { workspaceId }
|
|
61790
|
+
}
|
|
61791
|
+
}`,
|
|
61792
|
+
{ workspaceId: id }
|
|
61793
|
+
);
|
|
61794
|
+
return data.deleteWorkspaceWorkspaceByWorkspaceId?.workspaceWorkspace != null;
|
|
61795
|
+
},
|
|
61796
|
+
shares: async () => {
|
|
61797
|
+
const data = await client.graphql(
|
|
61798
|
+
`query SdkWorkspaceShares($id: String!) {
|
|
61799
|
+
from: workspaceResourceShares(condition: { fromWorkspaceId: $id }) { nodes { ${SHARE_FIELDS} } }
|
|
61800
|
+
to: workspaceResourceShares(condition: { toWorkspaceId: $id }) { nodes { ${SHARE_FIELDS} } }
|
|
61801
|
+
}`,
|
|
61802
|
+
{ id }
|
|
61803
|
+
);
|
|
61804
|
+
return [...data.from?.nodes ?? [], ...data.to?.nodes ?? []].map(
|
|
61805
|
+
shareFromRow
|
|
61806
|
+
);
|
|
61807
|
+
},
|
|
61808
|
+
share: async (input2) => {
|
|
61809
|
+
if (!SHARE_KINDS.includes(input2.kind)) {
|
|
61810
|
+
throw new Error(
|
|
61811
|
+
`Unknown share kind "${input2.kind}". Use one of: ${SHARE_KINDS.join(", ")}.`
|
|
61812
|
+
);
|
|
61813
|
+
}
|
|
61814
|
+
const ends = await storedShareEnds(client, id, input2.toWorkspaceId);
|
|
61815
|
+
const data = await client.graphql(
|
|
61816
|
+
`mutation SdkCreateWorkspaceShare($share: WorkspaceResourceShareInput!) {
|
|
61817
|
+
createWorkspaceResourceShare(input: { workspaceResourceShare: $share }) {
|
|
61818
|
+
workspaceResourceShare { id }
|
|
61819
|
+
}
|
|
61820
|
+
}`,
|
|
61821
|
+
{
|
|
61822
|
+
share: {
|
|
61823
|
+
fromWorkspaceId: ends.from,
|
|
61824
|
+
toWorkspaceId: ends.to,
|
|
61825
|
+
resourceKind: input2.kind,
|
|
61826
|
+
resourceId: input2.resourceId ?? null
|
|
61827
|
+
}
|
|
61828
|
+
}
|
|
61829
|
+
);
|
|
61830
|
+
const shareId = data.createWorkspaceResourceShare?.workspaceResourceShare?.id;
|
|
61831
|
+
if (shareId == null)
|
|
61832
|
+
throw new Error("createWorkspaceResourceShare returned no share.");
|
|
61833
|
+
return { id: shareId };
|
|
61834
|
+
},
|
|
61835
|
+
unshare: async (input2) => {
|
|
61836
|
+
const ends = await storedShareEnds(client, id, input2.toWorkspaceId);
|
|
61837
|
+
const data = await client.graphql(
|
|
61838
|
+
`query SdkFindWorkspaceShare($from: String!, $to: String!, $kind: String!) {
|
|
61839
|
+
workspaceResourceShares(condition: { fromWorkspaceId: $from, toWorkspaceId: $to, resourceKind: $kind }) {
|
|
61840
|
+
nodes { ${SHARE_FIELDS} }
|
|
61841
|
+
}
|
|
61842
|
+
}`,
|
|
61843
|
+
{ from: ends.from, to: ends.to, kind: input2.kind }
|
|
61844
|
+
);
|
|
61845
|
+
const resourceId = input2.resourceId?.toLowerCase() ?? null;
|
|
61846
|
+
const row = data.workspaceResourceShares?.nodes.find(
|
|
61847
|
+
(share) => (share.resourceId?.toLowerCase() ?? null) === resourceId
|
|
61848
|
+
);
|
|
61849
|
+
if (row == null) {
|
|
61850
|
+
throw new Error(
|
|
61851
|
+
`No ${input2.resourceId == null ? `whole-kind ${input2.kind}` : `${input2.kind} ${input2.resourceId}`} share from ${ends.from} to ${ends.to}.`
|
|
61852
|
+
);
|
|
61853
|
+
}
|
|
61854
|
+
await client.graphql(
|
|
61855
|
+
`mutation SdkDeleteWorkspaceShare($id: String!) {
|
|
61856
|
+
deleteWorkspaceResourceShare(input: { id: $id }) { deletedWorkspaceResourceShareNodeId }
|
|
61857
|
+
}`,
|
|
61858
|
+
{ id: row.id }
|
|
61859
|
+
);
|
|
61397
61860
|
}
|
|
61398
61861
|
});
|
|
61399
61862
|
|
|
@@ -61512,6 +61975,7 @@ var OverAIClient = class {
|
|
|
61512
61975
|
};
|
|
61513
61976
|
workspaces = workspaceCollection(this);
|
|
61514
61977
|
runners = runnerCollection(this);
|
|
61978
|
+
resourceGroups = resourceGroupCollection(this);
|
|
61515
61979
|
storage = storageApi(this);
|
|
61516
61980
|
/** Its `deploy` checks deployed callers first; see `FunctionResource`. */
|
|
61517
61981
|
fn(id) {
|
|
@@ -61581,6 +62045,20 @@ var OverAIClient = class {
|
|
|
61581
62045
|
resource(id) {
|
|
61582
62046
|
return genericResource(this, id);
|
|
61583
62047
|
}
|
|
62048
|
+
resourceGroup(id) {
|
|
62049
|
+
return resourceGroupResource(this, id);
|
|
62050
|
+
}
|
|
62051
|
+
/**
|
|
62052
|
+
* References to and from many resources at once (at most 200 ids).
|
|
62053
|
+
* `referencerWorkspaceIds` limits inbound referencers to those workspaces.
|
|
62054
|
+
*/
|
|
62055
|
+
resourceReferences(resourceIds, options) {
|
|
62056
|
+
return resourceReferences(this, resourceIds, options);
|
|
62057
|
+
}
|
|
62058
|
+
/** Whether each agent's deployed tools resolve from its workspace and from `targetWorkspaceId`. */
|
|
62059
|
+
agentToolReach(agentIds, targetWorkspaceId) {
|
|
62060
|
+
return agentToolReach(this, agentIds, targetWorkspaceId);
|
|
62061
|
+
}
|
|
61584
62062
|
/** Claims of the JWT most recently obtained from the token source, or null before any request. Display only. */
|
|
61585
62063
|
claims() {
|
|
61586
62064
|
return this.#claims;
|
|
@@ -61899,6 +62377,9 @@ var unknownFlags = (args, known, valueFlags = []) => {
|
|
|
61899
62377
|
}
|
|
61900
62378
|
return out;
|
|
61901
62379
|
};
|
|
62380
|
+
var positionals = (args, valueFlags) => args.filter(
|
|
62381
|
+
(arg, index) => !arg.startsWith("-") && !valueFlags.includes(args[index - 1] ?? "")
|
|
62382
|
+
);
|
|
61902
62383
|
var flagValue = (args, ...names) => {
|
|
61903
62384
|
for (const name2 of names) {
|
|
61904
62385
|
const i = args.indexOf(name2);
|
|
@@ -63203,7 +63684,7 @@ ${lines.join("\n")}
|
|
|
63203
63684
|
var runRestore = (args) => {
|
|
63204
63685
|
const { root, manifest } = openClone();
|
|
63205
63686
|
const all = args.includes("--all");
|
|
63206
|
-
const filter2 =
|
|
63687
|
+
const filter2 = positionals2(args)[0];
|
|
63207
63688
|
if (filter2 == null && !all) {
|
|
63208
63689
|
throw new Error(
|
|
63209
63690
|
"Usage: overai restore <filter> (resource id, name, or path substring), or --all to discard every local edit."
|
|
@@ -63306,7 +63787,7 @@ var runPull = async (clone2) => {
|
|
|
63306
63787
|
var resourcesMatching = (manifest, filter2) => Object.entries(manifest.resources).filter(
|
|
63307
63788
|
([id, resource]) => filter2 == null || id === filter2 || resource.name.toLowerCase().includes(filter2.toLowerCase()) || resource.files.some((f) => f.includes(filter2))
|
|
63308
63789
|
);
|
|
63309
|
-
var
|
|
63790
|
+
var positionals2 = (args) => {
|
|
63310
63791
|
const valueFlags = /* @__PURE__ */ new Set(["-m", "--message", "-o", "--output"]);
|
|
63311
63792
|
const out = [];
|
|
63312
63793
|
for (let i = 0; i < args.length; i++) {
|
|
@@ -63348,7 +63829,7 @@ var runPush = async (args, clone2) => {
|
|
|
63348
63829
|
const deploy = args.includes("--deploy");
|
|
63349
63830
|
const force = args.includes("--force");
|
|
63350
63831
|
const allowBreaking = args.includes("--allow-breaking");
|
|
63351
|
-
const pathFilter =
|
|
63832
|
+
const pathFilter = positionals2(args)[0];
|
|
63352
63833
|
let pushed = 0;
|
|
63353
63834
|
for (const [id, resource] of resourcesMatching(manifest, pathFilter)) {
|
|
63354
63835
|
const { state, changedFiles } = localState(root, resource);
|
|
@@ -63431,7 +63912,7 @@ var runPush = async (args, clone2) => {
|
|
|
63431
63912
|
};
|
|
63432
63913
|
var runDeploy = async (args) => {
|
|
63433
63914
|
const { root, manifest } = openClone();
|
|
63434
|
-
const pathFilter =
|
|
63915
|
+
const pathFilter = positionals2(args)[0];
|
|
63435
63916
|
const allowBreaking = args.includes("--allow-breaking");
|
|
63436
63917
|
const pending = resourcesMatching(manifest, pathFilter).filter(
|
|
63437
63918
|
([, r]) => r.deployedVersion !== r.baseVersion
|
|
@@ -64697,12 +65178,478 @@ var runReport = async (args) => {
|
|
|
64697
65178
|
);
|
|
64698
65179
|
};
|
|
64699
65180
|
|
|
65181
|
+
// src/commands/move.ts
|
|
65182
|
+
var printReport = (args, report2) => {
|
|
65183
|
+
if (flagValue(args, "-o", "--output") === "json") {
|
|
65184
|
+
printResult(report2, "json");
|
|
65185
|
+
return;
|
|
65186
|
+
}
|
|
65187
|
+
process.stdout.write(
|
|
65188
|
+
[
|
|
65189
|
+
...report2.plan,
|
|
65190
|
+
"",
|
|
65191
|
+
...report2.warnings.length === 0 ? ["No warnings."] : report2.warnings.map(
|
|
65192
|
+
(line, index) => index === 0 ? line : ` ${line}`
|
|
65193
|
+
),
|
|
65194
|
+
"",
|
|
65195
|
+
report2.dryRun ? "Dry run: nothing changed." : ""
|
|
65196
|
+
].join("\n").trimEnd() + "\n"
|
|
65197
|
+
);
|
|
65198
|
+
};
|
|
65199
|
+
var workspacesById = (forest) => {
|
|
65200
|
+
const byId = /* @__PURE__ */ new Map();
|
|
65201
|
+
const visit2 = (node2) => {
|
|
65202
|
+
byId.set(node2.id.toLowerCase(), node2);
|
|
65203
|
+
node2.children.forEach(visit2);
|
|
65204
|
+
};
|
|
65205
|
+
forest.forEach(visit2);
|
|
65206
|
+
return byId;
|
|
65207
|
+
};
|
|
65208
|
+
var subtreeIds = (node2) => [
|
|
65209
|
+
node2.id,
|
|
65210
|
+
...node2.children.flatMap(subtreeIds)
|
|
65211
|
+
];
|
|
65212
|
+
var userLabel = (user) => user.email ?? user.name ?? user.id;
|
|
65213
|
+
var ROLE_ORDER = ["manager", "editor", "viewer", "end_user"];
|
|
65214
|
+
var roleRank = (role) => {
|
|
65215
|
+
const rank = role == null ? -1 : ROLE_ORDER.indexOf(role);
|
|
65216
|
+
return rank === -1 ? ROLE_ORDER.length : rank;
|
|
65217
|
+
};
|
|
65218
|
+
var strongerRole = (a, b) => roleRank(a) <= roleRank(b) ? a : b;
|
|
65219
|
+
var reaches = (shares, from, to, kind, resourceId) => {
|
|
65220
|
+
const target = to.toLowerCase();
|
|
65221
|
+
const seen = /* @__PURE__ */ new Set([from.toLowerCase()]);
|
|
65222
|
+
const queue = [from.toLowerCase()];
|
|
65223
|
+
for (let at = queue.shift(); at != null; at = queue.shift()) {
|
|
65224
|
+
if (at === target) return true;
|
|
65225
|
+
shares.filter(
|
|
65226
|
+
(share) => share.fromWorkspaceId.toLowerCase() === at && share.resourceKind === kind && (share.resourceId == null || share.resourceId.toLowerCase() === resourceId.toLowerCase())
|
|
65227
|
+
).forEach((share) => {
|
|
65228
|
+
const next = share.toWorkspaceId.toLowerCase();
|
|
65229
|
+
if (!seen.has(next)) {
|
|
65230
|
+
seen.add(next);
|
|
65231
|
+
queue.push(next);
|
|
65232
|
+
}
|
|
65233
|
+
});
|
|
65234
|
+
}
|
|
65235
|
+
return false;
|
|
65236
|
+
};
|
|
65237
|
+
var rowName = (row) => {
|
|
65238
|
+
if (typeof row.name === "string") return row.name;
|
|
65239
|
+
const identity = row.identity;
|
|
65240
|
+
return typeof identity?.name === "string" ? identity.name : row.id;
|
|
65241
|
+
};
|
|
65242
|
+
var accessibleViews = {
|
|
65243
|
+
function: {
|
|
65244
|
+
collection: "workspaceAccessibleFunctions",
|
|
65245
|
+
idField: "functionId",
|
|
65246
|
+
relation: "function"
|
|
65247
|
+
},
|
|
65248
|
+
table_space: {
|
|
65249
|
+
collection: "workspaceAccessibleTableSpaces",
|
|
65250
|
+
idField: "tableSpaceId",
|
|
65251
|
+
relation: "tableSpace"
|
|
65252
|
+
},
|
|
65253
|
+
agent: {
|
|
65254
|
+
collection: "workspaceAccessibleAgents",
|
|
65255
|
+
idField: "agentId",
|
|
65256
|
+
relation: "agent"
|
|
65257
|
+
},
|
|
65258
|
+
integration: {
|
|
65259
|
+
collection: "workspaceAccessibleIntegrations",
|
|
65260
|
+
idField: "integrationId",
|
|
65261
|
+
relation: "integration"
|
|
65262
|
+
},
|
|
65263
|
+
action_runner: {
|
|
65264
|
+
collection: "workspaceAccessibleActionRunners",
|
|
65265
|
+
idField: "actionRunnerId",
|
|
65266
|
+
relation: "actionRunner"
|
|
65267
|
+
}
|
|
65268
|
+
};
|
|
65269
|
+
var SHARED_RESOURCE_CAP = 200;
|
|
65270
|
+
var sharedResources = async (client, share) => {
|
|
65271
|
+
if (share.resourceId != null) {
|
|
65272
|
+
const row = await client.resource(share.resourceId).show().catch(() => null);
|
|
65273
|
+
return {
|
|
65274
|
+
resources: [
|
|
65275
|
+
{
|
|
65276
|
+
id: share.resourceId,
|
|
65277
|
+
name: row == null ? share.resourceId : rowName(row)
|
|
65278
|
+
}
|
|
65279
|
+
],
|
|
65280
|
+
total: 1
|
|
65281
|
+
};
|
|
65282
|
+
}
|
|
65283
|
+
const kind = SHARE_KINDS.find((known) => known === share.resourceKind);
|
|
65284
|
+
if (kind == null) return { resources: [], total: 0 };
|
|
65285
|
+
const view = accessibleViews[kind];
|
|
65286
|
+
const data = await client.graphql(
|
|
65287
|
+
`query CliSharedKindResources($workspaceId: String!, $first: Int!) {
|
|
65288
|
+
${view.collection}(condition: { workspaceId: $workspaceId }, first: $first) {
|
|
65289
|
+
totalCount
|
|
65290
|
+
nodes { ${view.idField} ${view.relation} { ${resourceTables[kind].fields} } }
|
|
65291
|
+
}
|
|
65292
|
+
}`,
|
|
65293
|
+
{ workspaceId: share.fromWorkspaceId, first: SHARED_RESOURCE_CAP }
|
|
65294
|
+
);
|
|
65295
|
+
const connection = data[view.collection];
|
|
65296
|
+
return {
|
|
65297
|
+
resources: (connection?.nodes ?? []).map((node2) => {
|
|
65298
|
+
const id = String(node2[view.idField]);
|
|
65299
|
+
const row = node2[view.relation];
|
|
65300
|
+
return { id, name: row == null ? id : rowName(row) };
|
|
65301
|
+
}),
|
|
65302
|
+
total: connection?.totalCount ?? 0
|
|
65303
|
+
};
|
|
65304
|
+
};
|
|
65305
|
+
var moveWorkspace = async (args) => {
|
|
65306
|
+
const [workspaceId] = positionals(args, ["--to", "-o", "--output"]);
|
|
65307
|
+
const to = flagValue(args, "--to");
|
|
65308
|
+
if (workspaceId == null || to == null) {
|
|
65309
|
+
throw new Error(
|
|
65310
|
+
"Usage: overai workspace move <workspaceId> --to <parentWorkspaceId|root> [--dry-run]"
|
|
65311
|
+
);
|
|
65312
|
+
}
|
|
65313
|
+
const dryRun = args.includes("--dry-run");
|
|
65314
|
+
const client = cliClient();
|
|
65315
|
+
const [forest, allShares] = await Promise.all([
|
|
65316
|
+
client.workspaces.tree({ includeArchived: true }),
|
|
65317
|
+
client.workspaces.shares()
|
|
65318
|
+
]);
|
|
65319
|
+
const byId = workspacesById(forest);
|
|
65320
|
+
const label = (id) => {
|
|
65321
|
+
if (id == null) return "the top level";
|
|
65322
|
+
const node2 = byId.get(id.toLowerCase());
|
|
65323
|
+
return node2 == null ? id : `"${node2.name}" (${node2.id})`;
|
|
65324
|
+
};
|
|
65325
|
+
const moved = byId.get(workspaceId.toLowerCase());
|
|
65326
|
+
if (moved == null) {
|
|
65327
|
+
throw new Error(
|
|
65328
|
+
`Workspace ${workspaceId} not found (or not visible to you).`
|
|
65329
|
+
);
|
|
65330
|
+
}
|
|
65331
|
+
const newParent = to === "root" ? null : byId.get(to.toLowerCase());
|
|
65332
|
+
if (newParent === void 0) {
|
|
65333
|
+
throw new Error(`Workspace ${to} not found (or not visible to you).`);
|
|
65334
|
+
}
|
|
65335
|
+
const oldParentId = moved.parentWorkspaceId;
|
|
65336
|
+
if (oldParentId != null && oldParentId.toLowerCase() === newParent?.id.toLowerCase()) {
|
|
65337
|
+
(flagValue(args, "-o", "--output") === "json" ? process.stderr : process.stdout).write(
|
|
65338
|
+
`${label(moved.id)} is already under ${label(oldParentId)}; nothing to move.
|
|
65339
|
+
`
|
|
65340
|
+
);
|
|
65341
|
+
return;
|
|
65342
|
+
}
|
|
65343
|
+
const subtreeStoredIds = subtreeIds(moved);
|
|
65344
|
+
const subtree = new Set(subtreeStoredIds.map((id) => id.toLowerCase()));
|
|
65345
|
+
const deletedShares = oldParentId == null ? [] : allShares.filter(
|
|
65346
|
+
(share) => share.fromWorkspaceId.toLowerCase() === oldParentId.toLowerCase() && share.toWorkspaceId.toLowerCase() === moved.id.toLowerCase()
|
|
65347
|
+
);
|
|
65348
|
+
const [movedUsers, parentUsers, shared] = await Promise.all([
|
|
65349
|
+
client.workspace(moved.id).users(),
|
|
65350
|
+
newParent == null ? [] : client.workspace(newParent.id).users(),
|
|
65351
|
+
Promise.all(
|
|
65352
|
+
deletedShares.map(async (share) => ({
|
|
65353
|
+
share,
|
|
65354
|
+
...await sharedResources(client, share)
|
|
65355
|
+
}))
|
|
65356
|
+
)
|
|
65357
|
+
]);
|
|
65358
|
+
const plan = [
|
|
65359
|
+
`Moving workspace ${label(moved.id)} from ${oldParentId == null ? "the top level (or a parent you cannot see)" : label(oldParentId)} to ${label(newParent?.id ?? null)}.`,
|
|
65360
|
+
oldParentId == null ? "Shares from a parent you cannot see cannot be listed; the database deletes them with the move." : deletedShares.length === 0 ? `No shares from ${label(oldParentId)} into it to delete.` : `Will delete ${String(deletedShares.length)} share${deletedShares.length === 1 ? "" : "s"} from ${label(oldParentId)} into it: ${shared.map(
|
|
65361
|
+
({ share, resources }) => share.resourceId == null ? `all ${share.resourceKind}` : `${share.resourceKind} "${resources[0]?.name ?? share.resourceId}" (${share.resourceId})`
|
|
65362
|
+
).join("; ")}.`
|
|
65363
|
+
];
|
|
65364
|
+
const warnings = [];
|
|
65365
|
+
if (newParent != null && subtree.has(newParent.id.toLowerCase())) {
|
|
65366
|
+
warnings.push(
|
|
65367
|
+
`${label(newParent.id)} is inside ${label(moved.id)}; the database will refuse this move.`
|
|
65368
|
+
);
|
|
65369
|
+
}
|
|
65370
|
+
const movedById = new Map(movedUsers.map((user) => [user.id, user]));
|
|
65371
|
+
const parentById = new Map(parentUsers.map((user) => [user.id, user]));
|
|
65372
|
+
const access = [
|
|
65373
|
+
...movedUsers,
|
|
65374
|
+
...parentUsers.filter((user) => !movedById.has(user.id))
|
|
65375
|
+
].flatMap((user) => {
|
|
65376
|
+
const before = movedById.get(user.id)?.role ?? null;
|
|
65377
|
+
const after = strongerRole(
|
|
65378
|
+
movedById.get(user.id)?.directRole ?? null,
|
|
65379
|
+
parentById.get(user.id)?.role ?? null
|
|
65380
|
+
);
|
|
65381
|
+
if (before === after) return [];
|
|
65382
|
+
if (after == null)
|
|
65383
|
+
return [`${userLabel(user)} loses ${before ?? "access"}`];
|
|
65384
|
+
if (before == null) return [`${userLabel(user)} gains ${after}`];
|
|
65385
|
+
return roleRank(after) > roleRank(before) ? [`${userLabel(user)} drops to ${after} from ${before}`] : [`${userLabel(user)} rises to ${after} from ${before}`];
|
|
65386
|
+
});
|
|
65387
|
+
if (access.length > 0) {
|
|
65388
|
+
warnings.push(
|
|
65389
|
+
`Access on ${label(moved.id)} (from its direct and inherited roles; descendants with their own grants may differ):`,
|
|
65390
|
+
...access.map((line) => ` ${line}`)
|
|
65391
|
+
);
|
|
65392
|
+
}
|
|
65393
|
+
const sharedIds = shared.flatMap(
|
|
65394
|
+
({ share, resources }) => resources.map((resource) => ({ ...resource, kind: share.resourceKind }))
|
|
65395
|
+
);
|
|
65396
|
+
const sharedTotal = shared.reduce((sum2, { total }) => sum2 + total, 0);
|
|
65397
|
+
const references = await client.resourceReferences(
|
|
65398
|
+
sharedIds.slice(0, SHARED_RESOURCE_CAP).map((resource) => resource.id),
|
|
65399
|
+
{ referencerWorkspaceIds: subtreeStoredIds.slice(0, 500) }
|
|
65400
|
+
).catch((error62) => {
|
|
65401
|
+
warnings.push(
|
|
65402
|
+
`Could not check references: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
65403
|
+
);
|
|
65404
|
+
return null;
|
|
65405
|
+
});
|
|
65406
|
+
const sharedById = new Map(
|
|
65407
|
+
sharedIds.map((resource) => [resource.id.toLowerCase(), resource])
|
|
65408
|
+
);
|
|
65409
|
+
const brokenReferences = (references?.inbound ?? []).flatMap((ref) => {
|
|
65410
|
+
const resource = sharedById.get(ref.resourceId.toLowerCase());
|
|
65411
|
+
return resource != null && subtree.has(ref.referencerWorkspaceId.toLowerCase()) ? [
|
|
65412
|
+
`${ref.referencerKind} "${ref.referencerName}" (${ref.referencerId}) in ${label(ref.referencerWorkspaceId)} references ${resource.kind} "${resource.name}" (${resource.id}), shared by a share this move deletes`
|
|
65413
|
+
] : [];
|
|
65414
|
+
});
|
|
65415
|
+
if (brokenReferences.length > 0) {
|
|
65416
|
+
warnings.push(
|
|
65417
|
+
"May stop resolving (deployed content found by id; another share path may still reach it):",
|
|
65418
|
+
...brokenReferences.map((line) => ` ${line}`)
|
|
65419
|
+
);
|
|
65420
|
+
}
|
|
65421
|
+
if (sharedTotal > SHARED_RESOURCE_CAP) {
|
|
65422
|
+
warnings.push(
|
|
65423
|
+
`Checked references for the first ${String(SHARED_RESOURCE_CAP)} of ${String(sharedTotal)} shared resources.`
|
|
65424
|
+
);
|
|
65425
|
+
}
|
|
65426
|
+
printReport(args, {
|
|
65427
|
+
plan,
|
|
65428
|
+
warnings: warnings.length === 0 ? [] : ["WARN", ...warnings],
|
|
65429
|
+
dryRun
|
|
65430
|
+
});
|
|
65431
|
+
if (dryRun) return;
|
|
65432
|
+
const didMove = newParent == null ? await client.workspace(moved.id).moveToRoot() : await client.workspace(moved.id).setParent(newParent.id).then(() => true);
|
|
65433
|
+
(flagValue(args, "-o", "--output") === "json" ? process.stderr : process.stdout).write(
|
|
65434
|
+
didMove ? `Moved ${label(moved.id)}.
|
|
65435
|
+
` : `${label(moved.id)} was already at the top level, or its parent is not visible to you; nothing changed.
|
|
65436
|
+
`
|
|
65437
|
+
);
|
|
65438
|
+
};
|
|
65439
|
+
var moveResource = async (args) => {
|
|
65440
|
+
const [id] = positionals(args, ["--to", "-o", "--output"]);
|
|
65441
|
+
const to = flagValue(args, "--to");
|
|
65442
|
+
if (id == null || to == null) {
|
|
65443
|
+
throw new Error(
|
|
65444
|
+
"Usage: overai resource move <id> --to <workspaceId> [--dry-run]"
|
|
65445
|
+
);
|
|
65446
|
+
}
|
|
65447
|
+
const dryRun = args.includes("--dry-run");
|
|
65448
|
+
const client = cliClient();
|
|
65449
|
+
const row = await client.resource(id).show();
|
|
65450
|
+
const kind = idTableByPrefix(row.id);
|
|
65451
|
+
const fromId = typeof row.workspaceId === "string" ? row.workspaceId : null;
|
|
65452
|
+
if (kind == null || kind === "workspace" || fromId == null) {
|
|
65453
|
+
throw new Error(
|
|
65454
|
+
`${id} cannot be moved; use overai workspace move for a workspace.`
|
|
65455
|
+
);
|
|
65456
|
+
}
|
|
65457
|
+
const [forest, allShares, membership] = await Promise.all([
|
|
65458
|
+
client.workspaces.tree({ includeArchived: true }),
|
|
65459
|
+
client.workspaces.shares(),
|
|
65460
|
+
client.resourceGroups.membershipOf(row.id)
|
|
65461
|
+
]);
|
|
65462
|
+
const byId = workspacesById(forest);
|
|
65463
|
+
const label = (workspaceId) => {
|
|
65464
|
+
const node2 = byId.get(workspaceId.toLowerCase());
|
|
65465
|
+
return node2 == null ? workspaceId : `"${node2.name}" (${node2.id})`;
|
|
65466
|
+
};
|
|
65467
|
+
const destination = byId.get(to.toLowerCase());
|
|
65468
|
+
if (destination == null) {
|
|
65469
|
+
throw new Error(`Workspace ${to} not found (or not visible to you).`);
|
|
65470
|
+
}
|
|
65471
|
+
const subject = `${kind} "${rowName(row)}" (${row.id})`;
|
|
65472
|
+
if (destination.id.toLowerCase() === fromId.toLowerCase()) {
|
|
65473
|
+
(flagValue(args, "-o", "--output") === "json" ? process.stderr : process.stdout).write(`${subject} is already in ${label(fromId)}; nothing to move.
|
|
65474
|
+
`);
|
|
65475
|
+
return;
|
|
65476
|
+
}
|
|
65477
|
+
const ownShares = allShares.filter(
|
|
65478
|
+
(share) => share.resourceKind === kind && share.resourceId?.toLowerCase() === row.id.toLowerCase()
|
|
65479
|
+
);
|
|
65480
|
+
const plan = [
|
|
65481
|
+
`Moving ${subject} from ${label(fromId)} to ${label(destination.id)}.`,
|
|
65482
|
+
membership == null ? "It is in no resource group." : `Will remove it from group "${membership.groupName ?? membership.groupId}" (${membership.groupId}); a group holds only its own workspace's resources.`,
|
|
65483
|
+
ownShares.length === 0 ? "No shares name it." : `Will delete ${String(ownShares.length)} share${ownShares.length === 1 ? "" : "s"} naming it: ${ownShares.map(
|
|
65484
|
+
(share) => `${label(share.fromWorkspaceId)} \u2192 ${label(share.toWorkspaceId)}`
|
|
65485
|
+
).join("; ")}.`
|
|
65486
|
+
];
|
|
65487
|
+
const warnings = [];
|
|
65488
|
+
const failed = (what) => (error62) => {
|
|
65489
|
+
warnings.push(
|
|
65490
|
+
`Could not check ${what}: ${error62 instanceof Error ? error62.message : String(error62)}`
|
|
65491
|
+
);
|
|
65492
|
+
return null;
|
|
65493
|
+
};
|
|
65494
|
+
const [references, reach] = await Promise.all([
|
|
65495
|
+
client.resource(row.id).references().catch(failed("references")),
|
|
65496
|
+
kind === "agent" ? client.agentToolReach([row.id], destination.id).catch(failed("agent tool reach")) : null
|
|
65497
|
+
]);
|
|
65498
|
+
const sharesAfter = allShares.filter((share) => !ownShares.includes(share));
|
|
65499
|
+
const lostReach = [
|
|
65500
|
+
...(references?.inbound ?? []).flatMap(
|
|
65501
|
+
(ref) => reaches(allShares, fromId, ref.referencerWorkspaceId, kind, row.id) && !reaches(
|
|
65502
|
+
sharesAfter,
|
|
65503
|
+
destination.id,
|
|
65504
|
+
ref.referencerWorkspaceId,
|
|
65505
|
+
kind,
|
|
65506
|
+
row.id
|
|
65507
|
+
) ? [
|
|
65508
|
+
`${ref.referencerKind} "${ref.referencerName}" (${ref.referencerId}) in ${label(ref.referencerWorkspaceId)} will no longer reach ${subject}`
|
|
65509
|
+
] : []
|
|
65510
|
+
),
|
|
65511
|
+
...(references?.outbound ?? []).flatMap(
|
|
65512
|
+
(ref) => reaches(
|
|
65513
|
+
allShares,
|
|
65514
|
+
ref.targetWorkspaceId,
|
|
65515
|
+
fromId,
|
|
65516
|
+
ref.targetKind,
|
|
65517
|
+
ref.targetId
|
|
65518
|
+
) && !reaches(
|
|
65519
|
+
allShares,
|
|
65520
|
+
ref.targetWorkspaceId,
|
|
65521
|
+
destination.id,
|
|
65522
|
+
ref.targetKind,
|
|
65523
|
+
ref.targetId
|
|
65524
|
+
) ? [
|
|
65525
|
+
`${subject} will no longer reach ${ref.targetKind} "${ref.targetName}" (${ref.targetId}) in ${label(ref.targetWorkspaceId)}`
|
|
65526
|
+
] : []
|
|
65527
|
+
)
|
|
65528
|
+
];
|
|
65529
|
+
if (lostReach.length > 0) {
|
|
65530
|
+
warnings.push(
|
|
65531
|
+
"References by id in deployed content (heuristic: same workspace, or a chain of shares of that kind):",
|
|
65532
|
+
...lostReach.map((line) => ` ${line}`)
|
|
65533
|
+
);
|
|
65534
|
+
}
|
|
65535
|
+
const tools2 = (reach ?? []).flatMap((agent) => [
|
|
65536
|
+
...agent.tools.filter(
|
|
65537
|
+
(tool) => tool.isReachable && tool.isReachableFromTarget === false
|
|
65538
|
+
).map(
|
|
65539
|
+
(tool) => `${subject} will lose tool ${tool.kind} "${tool.name}" (${tool.id})`
|
|
65540
|
+
),
|
|
65541
|
+
...agent.hiddenLostAtTargetCount > 0 ? [
|
|
65542
|
+
`${subject} will lose ${String(agent.hiddenLostAtTargetCount)} tool${agent.hiddenLostAtTargetCount === 1 ? "" : "s"} you cannot see`
|
|
65543
|
+
] : []
|
|
65544
|
+
]);
|
|
65545
|
+
if (tools2.length > 0) {
|
|
65546
|
+
warnings.push(
|
|
65547
|
+
"Agent tools (from the server):",
|
|
65548
|
+
...tools2.map((line) => ` ${line}`)
|
|
65549
|
+
);
|
|
65550
|
+
}
|
|
65551
|
+
printReport(args, {
|
|
65552
|
+
plan,
|
|
65553
|
+
warnings: warnings.length === 0 ? [] : ["WARN", ...warnings],
|
|
65554
|
+
dryRun
|
|
65555
|
+
});
|
|
65556
|
+
if (dryRun) return;
|
|
65557
|
+
const result = await client.resource(row.id).move(destination.id);
|
|
65558
|
+
(flagValue(args, "-o", "--output") === "json" ? process.stderr : process.stdout).write(
|
|
65559
|
+
`Moved ${subject} to ${label(result.workspaceId)}${result.leftGroup == null ? "" : `; it left group "${result.leftGroup.groupName ?? result.leftGroup.groupId}"`}.
|
|
65560
|
+
`
|
|
65561
|
+
);
|
|
65562
|
+
};
|
|
65563
|
+
|
|
64700
65564
|
// src/commands/resource.ts
|
|
65565
|
+
var GROUP_USAGE = `Usage:
|
|
65566
|
+
overai resource group list [--workspace <id>]
|
|
65567
|
+
overai resource group create --workspace <id> --name <name>
|
|
65568
|
+
overai resource group rename <groupId> --name <name>
|
|
65569
|
+
overai resource group delete <groupId>
|
|
65570
|
+
overai resource group add <groupId> <resourceId>...
|
|
65571
|
+
overai resource group remove <resourceId>...
|
|
65572
|
+
`;
|
|
65573
|
+
var runGroup = async (args) => {
|
|
65574
|
+
const [operation, ...rest] = args;
|
|
65575
|
+
const ids = positionals(rest, ["--workspace", "--name", "-o", "--output"]);
|
|
65576
|
+
const name2 = flagValue(rest, "--name");
|
|
65577
|
+
const client = cliClient();
|
|
65578
|
+
if (operation === "list") {
|
|
65579
|
+
const workspaceId = flagValue(rest, "--workspace");
|
|
65580
|
+
printResult(
|
|
65581
|
+
(await client.resourceGroups.list({ workspaceId })).map((group) => ({
|
|
65582
|
+
id: group.id,
|
|
65583
|
+
name: group.name,
|
|
65584
|
+
workspaceId: group.workspaceId,
|
|
65585
|
+
resources: group.members.map((member) => member.resourceId).join(" ")
|
|
65586
|
+
})),
|
|
65587
|
+
resolveFormat(flagValue(rest, "-o", "--output"))
|
|
65588
|
+
);
|
|
65589
|
+
return;
|
|
65590
|
+
}
|
|
65591
|
+
if (operation === "create" && name2 != null) {
|
|
65592
|
+
const workspaceId = flagValue(rest, "--workspace") ?? openClone().manifest.workspaceId;
|
|
65593
|
+
const { id } = await client.resourceGroups.create({ workspaceId, name: name2 });
|
|
65594
|
+
process.stdout.write(
|
|
65595
|
+
`Created group "${name2}" (${id}) in ${workspaceId}.
|
|
65596
|
+
`
|
|
65597
|
+
);
|
|
65598
|
+
return;
|
|
65599
|
+
}
|
|
65600
|
+
const [groupId, ...resourceIds] = ids;
|
|
65601
|
+
if (operation === "rename" && groupId != null && name2 != null) {
|
|
65602
|
+
await client.resourceGroup(groupId).rename(name2);
|
|
65603
|
+
process.stdout.write(`Renamed group ${groupId} to "${name2}".
|
|
65604
|
+
`);
|
|
65605
|
+
return;
|
|
65606
|
+
}
|
|
65607
|
+
if (operation === "delete" && groupId != null) {
|
|
65608
|
+
await client.resourceGroup(groupId).delete();
|
|
65609
|
+
process.stdout.write(
|
|
65610
|
+
`Deleted group ${groupId}; its resources stay in the workspace.
|
|
65611
|
+
`
|
|
65612
|
+
);
|
|
65613
|
+
return;
|
|
65614
|
+
}
|
|
65615
|
+
if (operation === "add" && groupId != null && resourceIds.length > 0) {
|
|
65616
|
+
const previous = await client.resourceGroup(groupId).add(resourceIds);
|
|
65617
|
+
resourceIds.forEach((resourceId, index) => {
|
|
65618
|
+
const from = previous[index];
|
|
65619
|
+
process.stdout.write(
|
|
65620
|
+
`Added ${resourceId} to group ${groupId}${from == null || from.groupId === groupId ? "" : ` (left group "${from.groupName ?? from.groupId}")`}.
|
|
65621
|
+
`
|
|
65622
|
+
);
|
|
65623
|
+
});
|
|
65624
|
+
return;
|
|
65625
|
+
}
|
|
65626
|
+
if (operation === "remove" && ids.length > 0) {
|
|
65627
|
+
for (const resourceId of ids) {
|
|
65628
|
+
const membership = await client.resourceGroups.removeMember(resourceId);
|
|
65629
|
+
process.stdout.write(
|
|
65630
|
+
membership == null ? `${resourceId} is in no group.
|
|
65631
|
+
` : `Removed ${resourceId} from group "${membership.groupName ?? membership.groupId}".
|
|
65632
|
+
`
|
|
65633
|
+
);
|
|
65634
|
+
}
|
|
65635
|
+
return;
|
|
65636
|
+
}
|
|
65637
|
+
throw new Error(GROUP_USAGE.trimEnd());
|
|
65638
|
+
};
|
|
64701
65639
|
var runResource = async (args) => {
|
|
64702
65640
|
const [operation, id] = args;
|
|
65641
|
+
if (operation === "move") {
|
|
65642
|
+
await moveResource(args.slice(1));
|
|
65643
|
+
return;
|
|
65644
|
+
}
|
|
65645
|
+
if (operation === "group") {
|
|
65646
|
+
await runGroup(args.slice(1));
|
|
65647
|
+
return;
|
|
65648
|
+
}
|
|
64703
65649
|
if (operation !== "show" && operation !== "update" || id == null) {
|
|
64704
65650
|
throw new Error(
|
|
64705
|
-
|
|
65651
|
+
`Usage: overai resource show <id> | resource update <id> [--name <name>] [--description <text>] [--archive|--restore] [--enable|--disable] [--active|--inactive] | resource move <id> --to <workspaceId> [--dry-run]
|
|
65652
|
+
${GROUP_USAGE}`
|
|
64706
65653
|
);
|
|
64707
65654
|
}
|
|
64708
65655
|
const resource = resourceTableFor(id);
|
|
@@ -65132,7 +66079,7 @@ When a parent executes, it resolves to one of these handles. Child nodes only be
|
|
|
65132
66079
|
To run an event node, call \`runAutomationNode\` with a \`eventPayload\` object whose fields match the event node's declared outputs:
|
|
65133
66080
|
|
|
65134
66081
|
- **TIMER**: \`{ firedAt: "<ISO8601>", scheduledAt: "<ISO8601>" }\` \u2014 use current time for both when testing ad-hoc
|
|
65135
|
-
- **WEBHOOK**: \`{ payload:
|
|
66082
|
+
- **WEBHOOK**: \`{ payload: { ... }, queryParams: {}, firedAt: "<ISO8601>" }\` \u2014 \`payload\` is the parsed request body (a JSON object, not a JSON string), matching a live run; use a raw string only to simulate an XML body
|
|
65136
66083
|
- **EMAIL_RECEIVED**: \`{ from: "<email>", subject?: "<string>", text?: "<string>", html?: "<string>", headers?: {}, attachments?: [], firedAt: "<ISO8601>" }\`
|
|
65137
66084
|
- **FILE_UPLOAD**: You **cannot** provide a file URL programmatically. Tell the user: "Please click the debug run button on the file upload event node and select a file. Once you've done that, I'll continue." Then wait for them to confirm before proceeding.
|
|
65138
66085
|
|
|
@@ -65730,6 +66677,45 @@ A function can email recipients when it breaks: the handler throws, times out, o
|
|
|
65730
66677
|
`
|
|
65731
66678
|
};
|
|
65732
66679
|
|
|
66680
|
+
// ../common/src/architectDocs/libraries.ts
|
|
66681
|
+
var librariesDoc = {
|
|
66682
|
+
id: "libraries",
|
|
66683
|
+
summary: "Libraries: reusable components and functions that v2 pages import as overai:<libraryId>, with a Preview export, versions and sharing.",
|
|
66684
|
+
body: `
|
|
66685
|
+
## Libraries
|
|
66686
|
+
|
|
66687
|
+
A Library is a workspace resource holding one TypeScript/TSX module. Pages on the v2 runtime import its named exports:
|
|
66688
|
+
|
|
66689
|
+
\`\`\`tsx
|
|
66690
|
+
import { StatusBadge, formatMoney } from "overai:libxxxxxxxxxx";
|
|
66691
|
+
import { StatusBadge } from "overai:libxxxxxxxxxx@12"; // pinned to version 12
|
|
66692
|
+
\`\`\`
|
|
66693
|
+
|
|
66694
|
+
An unpinned import gets the library's deployed version. Lint flags an import of a library this workspace can't import, an archived library, or a pin to a version that doesn't exist; such an import leaves the page showing "Couldn't load the page's imports". A page can load at most 50 libraries, counting the libraries they import. Deploying a new version reaches open pages through their "new version available" refresh prompt. Library ids are lowercase; write them that way in imports. Only v2 pages can import libraries.
|
|
66695
|
+
|
|
66696
|
+
## Writing a library
|
|
66697
|
+
|
|
66698
|
+
- Export what pages need by name. A default export is not importable.
|
|
66699
|
+
- \`Preview\` is reserved: export a component named \`Preview\` and it renders in the library's editor. Show each state and a usage example there. Pages never load it, so it costs them nothing.
|
|
66700
|
+
- A library is a real module, so import what it uses: \`import { useState } from "react";\`. The page globals (hooks, \`env\`, SDK helpers) are not in scope.
|
|
66701
|
+
- Imports may be \`react\`, \`react/jsx-runtime\`, \`react-dom\`, \`react-dom/client\`, \`superjson\`, \`@zumer/snapdom\`, other libraries (\`overai:<libraryId>\`) and https URLs (esm.sh). Anything else fails the build.
|
|
66702
|
+
- Take data as props and leave fetching to the page. The preview runs with no page data, and a component that fetches for itself is harder to reuse.
|
|
66703
|
+
- A build error is served as a module that throws it, so it appears in the console of any page importing the library.
|
|
66704
|
+
- To reuse a component a page already has, create a library, move the component into it with a \`Preview\`, deploy it, then replace the page's copy with an import.
|
|
66705
|
+
- A version that does not build is never deployed, by a save or by Deploy; fix the reported error and save again.
|
|
66706
|
+
|
|
66707
|
+
## Versions and sharing
|
|
66708
|
+
|
|
66709
|
+
Saving creates a version and Deploy points pages at it. A library's own \`overai:\` imports also resolve to deployed versions, so an unsaved or undeployed change in one library never reaches a deployed page through another.
|
|
66710
|
+
|
|
66711
|
+
In the page editor's preview, the page's own library imports update on every edit, but the libraries those import keep the versions loaded when the preview opened. Reload the preview to pick up a newer deploy.
|
|
66712
|
+
|
|
66713
|
+
A library is shared into child workspaces like a function. Builders there read its source and preview but cannot edit it. A shared library brings its own imports along: pages in the child load whatever the library imports from its owning workspace, without that being shared too. To import one of those directly, share it. Library code is visible to anyone who can import it: keep secrets in a function, never in a library.
|
|
66714
|
+
|
|
66715
|
+
Archiving a library stops every deployed page and library that imports it from loading. \`setResourceArchived\` refuses at first and returns those importers; name them to the user, and call again with \`archiveDespiteImporters: true\` only if they still want it archived. Moving a library to another workspace warns the user about the same importers, since pages load a library only from the workspace that owns it or one it is shared into.
|
|
66716
|
+
`
|
|
66717
|
+
};
|
|
66718
|
+
|
|
65733
66719
|
// ../common/src/architectDocs/liquidTemplates.ts
|
|
65734
66720
|
var liquidTemplatesDoc = {
|
|
65735
66721
|
id: "liquidTemplates",
|
|
@@ -66335,6 +67321,10 @@ var webPagesDoc = {
|
|
|
66335
67321
|
body: `
|
|
66336
67322
|
Saves reject a stale editing base without discarding your draft. Incorporate the latest saved changes before retrying; never retry with a newer base unless those changes have been reconciled. A save conflict does not deploy anything.
|
|
66337
67323
|
|
|
67324
|
+
## Platform shortcuts
|
|
67325
|
+
|
|
67326
|
+
In React pages (v1 and v2), Cmd/Ctrl+K toggles the command palette and Cmd/Ctrl+I toggles the Architect when the host provides them, including while typing in inputs. These combinations are reserved for OverAI; use other keys for page actions. Other keys stay inside the page. Pressing inside a page dismisses outside host dropdowns without cancelling the page interaction. Nested third-party iframes do not forward these events.
|
|
67327
|
+
|
|
66338
67328
|
## Available Global Variables and Hooks
|
|
66339
67329
|
|
|
66340
67330
|
\`\`\`typescript
|
|
@@ -66600,7 +67590,7 @@ These populate the \`data\`/\`items\` globals once, at render start, from the ol
|
|
|
66600
67590
|
2. **DO NOT import React or hooks.** React, useState, useEffect, useRef, useMemo, useCallback, and useReducer are all globally available. Importing them will cause errors.
|
|
66601
67591
|
3. **The main component MUST be named \`App\` and MUST NOT be exported.** Write \`function App() { ... }\` \u2014 no \`export\`.
|
|
66602
67592
|
4. **Use Tailwind CSS for styling.** It's built in.
|
|
66603
|
-
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
|
|
67593
|
+
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 bare and relative specifiers do not resolve. On the v2 runtime, also import your organization's libraries as \`overai:<libraryId>\` (read the \`libraries\` topic).
|
|
66604
67594
|
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.
|
|
66605
67595
|
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.
|
|
66606
67596
|
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.
|
|
@@ -66667,7 +67657,7 @@ These libraries are tested and work from \`https://esm.sh/...\`. Do NOT import R
|
|
|
66667
67657
|
|
|
66668
67658
|
### Do NOT use libraries that depend on React
|
|
66669
67659
|
|
|
66670
|
-
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
|
|
67660
|
+
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's import map does not cover that specifier, so there is no workaround. This rules out, among others:
|
|
66671
67661
|
|
|
66672
67662
|
- **react-resize-detector** \u2014 Use a \`ResizeObserver\` hook instead (see pattern below).
|
|
66673
67663
|
- **@tanstack/react-table** \u2014 Build tables with plain \`<table>\` + Tailwind + \`useState\` for sorting/filtering/pagination.
|
|
@@ -66752,13 +67742,15 @@ var workspacesDoc = {
|
|
|
66752
67742
|
|
|
66753
67743
|
Workspaces serve as permission boundaries. By design, a builder (viewer, editor, manager) in one workspace is able to see ALL child workspaces. It is NOT guaranteed that a builder in one workspace has permissions to see the parents though.
|
|
66754
67744
|
|
|
66755
|
-
Resources (functions, tablespaces, integrations, agents, action runners) can be shared from one workspace to another, but ONLY from a parent to a direct child. This is done such that any builder is guaranteed to be able to see all usages of a resource in their workspace. This prevents issues where a builder makes a change and unintentionally breaks something.
|
|
67745
|
+
Resources (functions, tablespaces, integrations, agents, action runners, libraries) can be shared from one workspace to another, but ONLY from a parent to a direct child. This is done such that any builder is guaranteed to be able to see all usages of a resource in their workspace. This prevents issues where a builder makes a change and unintentionally breaks something.
|
|
66756
67746
|
|
|
66757
67747
|
To share a resource, go to the Workspace Overview page, and then click "Resource sharing" (Managers only) in the top bar.
|
|
66758
67748
|
|
|
66759
|
-
|
|
67749
|
+
Moves clear sharing. Reparenting a workspace deletes the shares its old parent made into it, and moving a resource to another workspace deletes the shares that name it specifically and takes it out of its resource group. Re-share what the new location needs.
|
|
66760
67750
|
|
|
66761
|
-
|
|
67751
|
+
Resources shared into a workspace appear in its Workspace Overview resource table alongside its own, each marked "Shared from <parent workspace>" ("Shared from another workspace" when the viewer can't see the parent), and the "Shared" filter chip narrows the table to them. They are read-only there: no action menu, no activity stats. A shared resource's name links to its page only when the viewer holds a builder role in the workspace that owns it; otherwise the row is listed but not clickable. A shared library is the exception: it always opens, read-only, viewed from the child workspace. To change or unshare it, a manager of the parent workspace uses "Resource sharing" there.
|
|
67752
|
+
|
|
67753
|
+
An agent's tools (functions, tablespaces, sub-agents, knowledge bases) resolve from the agent's own workspace, never the caller's. Sharing an agent therefore lets the recipient use its tools through it without those tools being shared. A library's own imports work the same way: sharing a library brings what it imports along. Moving an agent to a workspace that can't reach a tool silently drops that tool at runtime; the agent page header shows "N tools unavailable" when this has happened. Fix it by sharing the tool into the agent's workspace or moving the tool, not by detaching it.
|
|
66762
67754
|
|
|
66763
67755
|
Archived workspaces are hidden from the workspace tree but are not deleted. Archiving a workspace also archives its integrations, which deletes their credentials; restoring the workspace leaves them archived. Account admins can inventory every archived workspace from **All Workspaces \u2192 Show archived**. To restore one they manage, tell the user to right-click the workspace tree's root item, choose **View archived workspaces**, and then choose **Unarchive**.
|
|
66764
67756
|
|
|
@@ -66794,6 +67786,7 @@ var ARCHITECT_DOC_TOPICS = [
|
|
|
66794
67786
|
automationExecutionRulesDoc,
|
|
66795
67787
|
liquidTemplatesDoc,
|
|
66796
67788
|
webPagesDoc,
|
|
67789
|
+
librariesDoc,
|
|
66797
67790
|
printablePagesDoc,
|
|
66798
67791
|
functionsDoc,
|
|
66799
67792
|
functionDebuggingDoc,
|
|
@@ -66918,12 +67911,34 @@ var runReview = async () => {
|
|
|
66918
67911
|
);
|
|
66919
67912
|
}
|
|
66920
67913
|
if (resource.type === "webPage" && relPath.endsWith(".tsx")) {
|
|
67914
|
+
const metaPath = resource.files.find(
|
|
67915
|
+
(file2) => file2.endsWith(".meta.json")
|
|
67916
|
+
);
|
|
67917
|
+
const isV2 = iife(() => {
|
|
67918
|
+
const meta3 = metaPath ? readWorkingFile(root, metaPath) : null;
|
|
67919
|
+
const [parsed] = resultOfSync(
|
|
67920
|
+
() => JSON.parse(meta3 ?? "{}")
|
|
67921
|
+
);
|
|
67922
|
+
return typeof parsed === "object" && parsed !== null && "runtime" in parsed && parsed.runtime === "v2";
|
|
67923
|
+
});
|
|
66921
67924
|
const importRe = /^\s*import\s+(?:[^'"\n]*?\bfrom\s+)?["']([^"']+)["']/gm;
|
|
66922
67925
|
for (const match of content.matchAll(importRe)) {
|
|
66923
67926
|
const specifier = match[1];
|
|
66924
67927
|
if (specifier == null || specifier.startsWith("https://")) continue;
|
|
67928
|
+
const library = /^overai:([^@]*)(?:@([0-9]+))?$/i.exec(specifier);
|
|
67929
|
+
if (library) {
|
|
67930
|
+
if (!isIdOf("library", library[1]))
|
|
67931
|
+
findings2.push(
|
|
67932
|
+
`${relPath}: imports "${specifier}" \u2014 not a library id; copy the import line from the library's page (overai:lib followed by 10 characters).`
|
|
67933
|
+
);
|
|
67934
|
+
else if (!isV2)
|
|
67935
|
+
findings2.push(
|
|
67936
|
+
`${relPath}: imports "${specifier}" \u2014 libraries load only on the v2 runtime; set "runtime": "v2" in ${metaPath ?? "the page's meta.json"}.`
|
|
67937
|
+
);
|
|
67938
|
+
continue;
|
|
67939
|
+
}
|
|
66925
67940
|
findings2.push(
|
|
66926
|
-
/^react(-dom)?(\/|$)/.test(specifier) ? `${relPath}: imports "${specifier}" \u2014 React and its hooks are already in scope; remove the import or the page renders blank.` : `${relPath}: imports "${specifier}" \u2014
|
|
67941
|
+
/^react(-dom)?(\/|$)/.test(specifier) ? `${relPath}: imports "${specifier}" \u2014 React and its hooks are already in scope; remove the import or the page renders blank.` : `${relPath}: imports "${specifier}" \u2014 pages import https URLs (use https://esm.sh/...) or, on the v2 runtime, libraries as overai:<libraryId>.`
|
|
66927
67942
|
);
|
|
66928
67943
|
}
|
|
66929
67944
|
if (/^\s*export\s+default\b/m.test(content)) {
|
|
@@ -67380,10 +68395,99 @@ var listWorkspaceUsers = async (args) => {
|
|
|
67380
68395
|
resolveFormat(flagValue(args, "-o", "--output"))
|
|
67381
68396
|
);
|
|
67382
68397
|
};
|
|
68398
|
+
var printTree = async (args) => {
|
|
68399
|
+
const [workspaceId] = positionals(args, ["-o", "--output"]);
|
|
68400
|
+
const includeArchived = args.includes("--archived");
|
|
68401
|
+
const client = cliClient();
|
|
68402
|
+
const roots = workspaceId == null ? await client.workspaces.tree({ includeArchived }) : [await client.workspace(workspaceId).tree({ includeArchived })];
|
|
68403
|
+
if (resolveFormat(flagValue(args, "-o", "--output")) !== "table") {
|
|
68404
|
+
printResult(roots, "json");
|
|
68405
|
+
return;
|
|
68406
|
+
}
|
|
68407
|
+
const lines = (node2, depth) => [
|
|
68408
|
+
`${" ".repeat(depth)}${node2.name} ${node2.id}${node2.role == null ? "" : ` ${node2.role}`}${node2.isArchived ? " archived" : ""}`,
|
|
68409
|
+
...node2.children.flatMap((child) => lines(child, depth + 1))
|
|
68410
|
+
];
|
|
68411
|
+
process.stdout.write(
|
|
68412
|
+
`${roots.flatMap((root) => lines(root, 0)).join("\n") || "(no workspaces)"}
|
|
68413
|
+
`
|
|
68414
|
+
);
|
|
68415
|
+
};
|
|
68416
|
+
var listShares = async (args) => {
|
|
68417
|
+
const workspaceId = workspaceIdFrom(args);
|
|
68418
|
+
const client = cliClient();
|
|
68419
|
+
const shares = await client.workspace(workspaceId).shares();
|
|
68420
|
+
const names = new Map(
|
|
68421
|
+
await Promise.all(
|
|
68422
|
+
shares.flatMap(
|
|
68423
|
+
(share) => share.resourceId == null ? [] : [
|
|
68424
|
+
client.resource(share.resourceId).show().then(
|
|
68425
|
+
(row) => [
|
|
68426
|
+
share.resourceId,
|
|
68427
|
+
typeof row.name === "string" ? row.name : ""
|
|
68428
|
+
],
|
|
68429
|
+
() => [share.resourceId, ""]
|
|
68430
|
+
)
|
|
68431
|
+
]
|
|
68432
|
+
)
|
|
68433
|
+
)
|
|
68434
|
+
);
|
|
68435
|
+
printResult(
|
|
68436
|
+
shares.map((share) => ({
|
|
68437
|
+
from: `${share.fromWorkspaceName ?? ""} (${share.fromWorkspaceId})`,
|
|
68438
|
+
to: `${share.toWorkspaceName ?? ""} (${share.toWorkspaceId})`,
|
|
68439
|
+
kind: share.resourceKind,
|
|
68440
|
+
resource: share.resourceId == null ? `all ${share.resourceKind}` : `${names.get(share.resourceId) ?? ""} (${share.resourceId})`
|
|
68441
|
+
})),
|
|
68442
|
+
resolveFormat(flagValue(args, "-o", "--output"))
|
|
68443
|
+
);
|
|
68444
|
+
};
|
|
68445
|
+
var shareResource = async (args) => {
|
|
68446
|
+
const [fromId] = positionals(args, [
|
|
68447
|
+
"--to",
|
|
68448
|
+
"--kind",
|
|
68449
|
+
"--resource",
|
|
68450
|
+
"-o",
|
|
68451
|
+
"--output"
|
|
68452
|
+
]);
|
|
68453
|
+
const to = flagValue(args, "--to");
|
|
68454
|
+
const kind = flagValue(args, "--kind");
|
|
68455
|
+
if (fromId == null || to == null || kind == null) {
|
|
68456
|
+
throw new Error(
|
|
68457
|
+
"Usage: overai workspace share <fromWorkspaceId> --to <childWorkspaceId> --kind <kind> [--resource <id>] [--remove]"
|
|
68458
|
+
);
|
|
68459
|
+
}
|
|
68460
|
+
const shareKind = SHARE_KINDS.find((known) => known === kind);
|
|
68461
|
+
if (shareKind == null) {
|
|
68462
|
+
throw new Error(
|
|
68463
|
+
`Unknown share kind "${kind}". Use one of: ${SHARE_KINDS.join(", ")}.`
|
|
68464
|
+
);
|
|
68465
|
+
}
|
|
68466
|
+
const client = cliClient();
|
|
68467
|
+
const typedResourceId = flagValue(args, "--resource");
|
|
68468
|
+
const resourceId = typedResourceId == null ? null : (await client.resource(typedResourceId).show()).id;
|
|
68469
|
+
const what = resourceId == null ? `all ${shareKind}` : `${shareKind} ${resourceId}`;
|
|
68470
|
+
const input2 = { toWorkspaceId: to, kind: shareKind, resourceId };
|
|
68471
|
+
if (args.includes("--remove")) {
|
|
68472
|
+
await client.workspace(fromId).unshare(input2);
|
|
68473
|
+
process.stdout.write(
|
|
68474
|
+
`Stopped sharing ${what} from ${fromId} into ${to}.
|
|
68475
|
+
`
|
|
68476
|
+
);
|
|
68477
|
+
return;
|
|
68478
|
+
}
|
|
68479
|
+
await client.workspace(fromId).share(input2);
|
|
68480
|
+
process.stdout.write(`Shared ${what} from ${fromId} into ${to}.
|
|
68481
|
+
`);
|
|
68482
|
+
};
|
|
67383
68483
|
var USAGE5 = `Usage:
|
|
67384
68484
|
overai workspace list [--archived] [--limit <n>]
|
|
67385
68485
|
overai workspace show [workspaceId]
|
|
67386
68486
|
overai workspace users [workspaceId]
|
|
68487
|
+
overai workspace tree [workspaceId] [--archived]
|
|
68488
|
+
overai workspace move <workspaceId> --to <parentWorkspaceId|root> [--dry-run]
|
|
68489
|
+
overai workspace shares [workspaceId]
|
|
68490
|
+
overai workspace share <fromWorkspaceId> --to <childWorkspaceId> --kind <${SHARE_KINDS.join("|")}> [--resource <id>] [--remove]
|
|
67387
68491
|
`;
|
|
67388
68492
|
var runWorkspace = async (args) => {
|
|
67389
68493
|
if (args[0] === "list") {
|
|
@@ -67398,6 +68502,22 @@ var runWorkspace = async (args) => {
|
|
|
67398
68502
|
await listWorkspaceUsers(args.slice(1));
|
|
67399
68503
|
return;
|
|
67400
68504
|
}
|
|
68505
|
+
if (args[0] === "tree") {
|
|
68506
|
+
await printTree(args.slice(1));
|
|
68507
|
+
return;
|
|
68508
|
+
}
|
|
68509
|
+
if (args[0] === "move") {
|
|
68510
|
+
await moveWorkspace(args.slice(1));
|
|
68511
|
+
return;
|
|
68512
|
+
}
|
|
68513
|
+
if (args[0] === "shares") {
|
|
68514
|
+
await listShares(args.slice(1));
|
|
68515
|
+
return;
|
|
68516
|
+
}
|
|
68517
|
+
if (args[0] === "share") {
|
|
68518
|
+
await shareResource(args.slice(1));
|
|
68519
|
+
return;
|
|
68520
|
+
}
|
|
67401
68521
|
process.stderr.write(USAGE5);
|
|
67402
68522
|
process.exitCode = 1;
|
|
67403
68523
|
};
|
|
@@ -67501,10 +68621,33 @@ Usage:
|
|
|
67501
68621
|
overai workspace show [workspaceId] Show a workspace's name and overview
|
|
67502
68622
|
overai workspace users [workspaceId] List users and effective/direct roles
|
|
67503
68623
|
(workspaceId defaults from a clone)
|
|
68624
|
+
overai workspace tree [workspaceId] [--archived]
|
|
68625
|
+
Print the workspace hierarchy; no id
|
|
68626
|
+
prints every top-level workspace
|
|
68627
|
+
overai workspace move <workspaceId> --to <parentId|root> [--dry-run]
|
|
68628
|
+
Reparent a workspace; prints the shares
|
|
68629
|
+
it loses and who gains or loses access
|
|
68630
|
+
overai workspace shares [workspaceId] List shares from and into a workspace
|
|
68631
|
+
overai workspace share <fromWorkspaceId> --to <childWorkspaceId> --kind <kind> [--resource <id>] [--remove]
|
|
68632
|
+
Share a kind (table_space, function,
|
|
68633
|
+
agent, integration, action_runner), or
|
|
68634
|
+
one resource, into a direct child
|
|
67504
68635
|
overai create <type> [--workspace <id>] [--name <name>]
|
|
67505
68636
|
Create a complete, usable resource
|
|
67506
68637
|
overai resource show <id> Show metadata for any resource
|
|
67507
68638
|
overai resource update <id> [...] Edit metadata, state, or archive status
|
|
68639
|
+
overai resource move <id> --to <workspaceId> [--dry-run]
|
|
68640
|
+
Move a resource to another workspace;
|
|
68641
|
+
prints the group and shares it loses and
|
|
68642
|
+
references that may stop resolving
|
|
68643
|
+
overai resource group list [--workspace <id>]
|
|
68644
|
+
overai resource group create --workspace <id> --name <name>
|
|
68645
|
+
overai resource group rename <groupId> --name <name>
|
|
68646
|
+
overai resource group delete <groupId>
|
|
68647
|
+
overai resource group add <groupId> <resourceId>...
|
|
68648
|
+
overai resource group remove <resourceId>...
|
|
68649
|
+
Side-navigation groups: flat, one per
|
|
68650
|
+
resource, same workspace
|
|
67508
68651
|
overai graphql -q '<query>' | -f <file> [--variables <json>] [--v1]
|
|
67509
68652
|
Run a GraphQL operation (/v2; --v1 = legacy Hasura)
|
|
67510
68653
|
overai fn <functionId> [--method GET] [--path /features/123] [--input k=v ... | -]
|