@doist/automations-cli 1.21.0 → 1.21.1
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 +381 -324
- package/dist/index.js.map +4 -4
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -6899,7 +6899,7 @@ import { fileURLToPath } from "node:url";
|
|
|
6899
6899
|
// package.json
|
|
6900
6900
|
var package_default = {
|
|
6901
6901
|
name: "@doist/automations-cli",
|
|
6902
|
-
version: "1.21.
|
|
6902
|
+
version: "1.21.1",
|
|
6903
6903
|
description: "Command-line client for Todoist Automations",
|
|
6904
6904
|
type: "module",
|
|
6905
6905
|
bin: {
|
|
@@ -6944,7 +6944,7 @@ var package_default = {
|
|
|
6944
6944
|
},
|
|
6945
6945
|
dependencies: {
|
|
6946
6946
|
"@doist/cli-core": "1.7.0",
|
|
6947
|
-
"@napi-rs/keyring": "2.1.
|
|
6947
|
+
"@napi-rs/keyring": "2.1.1",
|
|
6948
6948
|
ai: "7.0.137",
|
|
6949
6949
|
commander: "15.0.0",
|
|
6950
6950
|
oauth4webapi: "3.8.8",
|
|
@@ -32872,6 +32872,313 @@ async function findAutomationsUsingConnection(api, connectionId, options) {
|
|
|
32872
32872
|
}
|
|
32873
32873
|
}
|
|
32874
32874
|
|
|
32875
|
+
// ../../packages/sdk/dist/esm/drafts/draft-api.js
|
|
32876
|
+
function bindDraftApi(api, workspaceId, { signal } = {}) {
|
|
32877
|
+
const createOptions = { signal, translate: false };
|
|
32878
|
+
const listConnections = (args) => api.connections.list(args, { signal });
|
|
32879
|
+
if (workspaceId === null) {
|
|
32880
|
+
return {
|
|
32881
|
+
workspaceId: null,
|
|
32882
|
+
get: (draftId) => api.automationDrafts.get(draftId, { signal }),
|
|
32883
|
+
create: (manifest) => api.automationDrafts.create(manifest, createOptions),
|
|
32884
|
+
update: (draftId, manifest) => api.automationDrafts.update(draftId, manifest, { signal }),
|
|
32885
|
+
createAutomationDraft: (automationId) => api.automations.createDraft(automationId, { signal }),
|
|
32886
|
+
upsertConnection: (draftId, body) => api.automationDraftConnections.upsert(draftId, body, { signal }),
|
|
32887
|
+
getConnectionStatus: async (draftId) => (await api.automationDraftConnections.getStatus(draftId, { signal })).validation,
|
|
32888
|
+
listConnections,
|
|
32889
|
+
finalize: (draftId) => api.automationDrafts.finalize(draftId, { signal }),
|
|
32890
|
+
getAutomation: (automationId) => api.automations.get(automationId, { signal }),
|
|
32891
|
+
test: (draftId, request2) => api.automationDrafts.test(draftId, request2, { signal }),
|
|
32892
|
+
getTestRun: (draftId, runId, args, requestSignal) => api.automationDrafts.getTestRun(draftId, runId, args, {
|
|
32893
|
+
signal: requestSignal ?? signal
|
|
32894
|
+
})
|
|
32895
|
+
};
|
|
32896
|
+
}
|
|
32897
|
+
return {
|
|
32898
|
+
workspaceId,
|
|
32899
|
+
get: (draftId) => api.workspaceAutomationDrafts.get(workspaceId, draftId, { signal }),
|
|
32900
|
+
create: (manifest) => api.workspaceAutomationDrafts.create(workspaceId, manifest, createOptions),
|
|
32901
|
+
update: (draftId, manifest) => api.workspaceAutomationDrafts.update(workspaceId, draftId, manifest, { signal }),
|
|
32902
|
+
createAutomationDraft: (automationId) => api.workspaceAutomations.createDraft(workspaceId, automationId, { signal }),
|
|
32903
|
+
upsertConnection: (draftId, body) => api.workspaceAutomationDraftConnections.upsert(workspaceId, draftId, body, { signal }),
|
|
32904
|
+
getConnectionStatus: async (draftId) => (await api.workspaceAutomationDraftConnections.getStatus(workspaceId, draftId, {
|
|
32905
|
+
signal
|
|
32906
|
+
})).validation,
|
|
32907
|
+
listConnections,
|
|
32908
|
+
finalize: (draftId) => api.workspaceAutomationDrafts.finalize(workspaceId, draftId, { signal }),
|
|
32909
|
+
getAutomation: (automationId) => api.workspaceAutomations.get(workspaceId, automationId, { signal }),
|
|
32910
|
+
test: (draftId, request2) => api.workspaceAutomationDrafts.test(workspaceId, draftId, request2, { signal }),
|
|
32911
|
+
getTestRun: (draftId, runId, args, requestSignal) => api.workspaceAutomationDrafts.getTestRun(workspaceId, draftId, runId, args, {
|
|
32912
|
+
signal: requestSignal ?? signal
|
|
32913
|
+
})
|
|
32914
|
+
};
|
|
32915
|
+
}
|
|
32916
|
+
|
|
32917
|
+
// ../../packages/sdk/dist/esm/drafts/draft-workflow-error.js
|
|
32918
|
+
var DraftWorkflowError = class extends Error {
|
|
32919
|
+
code;
|
|
32920
|
+
draftId;
|
|
32921
|
+
automationId;
|
|
32922
|
+
constructor(code, message, options = {}) {
|
|
32923
|
+
super(message, { cause: options.cause });
|
|
32924
|
+
this.name = "DraftWorkflowError";
|
|
32925
|
+
this.code = code;
|
|
32926
|
+
this.draftId = options.draftId;
|
|
32927
|
+
this.automationId = options.automationId;
|
|
32928
|
+
}
|
|
32929
|
+
};
|
|
32930
|
+
function getErrorMessage(error62) {
|
|
32931
|
+
return error62 instanceof Error ? error62.message : String(error62);
|
|
32932
|
+
}
|
|
32933
|
+
|
|
32934
|
+
// ../../packages/sdk/dist/esm/drafts/draft-changes.js
|
|
32935
|
+
async function createDraft(draftApi, { manifest, automationId }) {
|
|
32936
|
+
const partialManifest = parsePartialManifest(manifest);
|
|
32937
|
+
if (automationId === void 0) {
|
|
32938
|
+
const result = await draftApi.create(partialManifest);
|
|
32939
|
+
return { action: "created", target: toDraftTarget(result.draft), ...result };
|
|
32940
|
+
}
|
|
32941
|
+
const { draft } = await openEditDraft(draftApi, automationId);
|
|
32942
|
+
try {
|
|
32943
|
+
const result = await draftApi.update(draft.id, partialManifest);
|
|
32944
|
+
return { action: "created", target: toDraftTarget(result.draft), ...result };
|
|
32945
|
+
} catch (error62) {
|
|
32946
|
+
if (!isManifestRejection(error62))
|
|
32947
|
+
throw error62;
|
|
32948
|
+
throw new DraftWorkflowError("draft_manifest_rejected", `Opened draft ${draft.id} for automation ${automationId}, but the manifest was rejected: ${getErrorMessage(error62)}`, { draftId: draft.id, automationId, cause: error62 });
|
|
32949
|
+
}
|
|
32950
|
+
}
|
|
32951
|
+
async function updateDraft(draftApi, { draftId, manifest }) {
|
|
32952
|
+
const partialManifest = parsePartialManifest(manifest);
|
|
32953
|
+
const result = await draftApi.update(draftId, partialManifest);
|
|
32954
|
+
return { action: "updated", target: toDraftTarget(result.draft), ...result };
|
|
32955
|
+
}
|
|
32956
|
+
function toDraftTarget(draft) {
|
|
32957
|
+
return draft.automationId === null ? { kind: "new" } : { kind: "automation", automationId: draft.automationId };
|
|
32958
|
+
}
|
|
32959
|
+
function parsePartialManifest(value) {
|
|
32960
|
+
const validation = validatePartialManifest(value);
|
|
32961
|
+
if (!validation.isValid) {
|
|
32962
|
+
throw new DraftWorkflowError("manifest_invalid", `Manifest is invalid: ${validation.errors.join("; ")}`);
|
|
32963
|
+
}
|
|
32964
|
+
return validation.data;
|
|
32965
|
+
}
|
|
32966
|
+
async function openEditDraft(draftApi, automationId) {
|
|
32967
|
+
try {
|
|
32968
|
+
return await draftApi.createAutomationDraft(automationId);
|
|
32969
|
+
} catch (error62) {
|
|
32970
|
+
const conflict = getOpenDraftConflictError(error62);
|
|
32971
|
+
if (!conflict)
|
|
32972
|
+
throw error62;
|
|
32973
|
+
throw new DraftWorkflowError("draft_conflict", `Automation ${automationId} already has an open draft ${conflict.draftId}.`, { draftId: conflict.draftId, automationId, cause: error62 });
|
|
32974
|
+
}
|
|
32975
|
+
}
|
|
32976
|
+
function isManifestRejection(error62) {
|
|
32977
|
+
return error62 instanceof AutomationsRequestError && (error62.httpStatusCode === 400 || error62.httpStatusCode === 422);
|
|
32978
|
+
}
|
|
32979
|
+
|
|
32980
|
+
// ../../packages/sdk/dist/esm/drafts/connect-draft.js
|
|
32981
|
+
async function connectDraft(draftApi, { draftId, selections, auto }) {
|
|
32982
|
+
const bound = [];
|
|
32983
|
+
const required2 = selections.length > 0 ? getRequiredConnectorsFromManifest((await draftApi.get(draftId)).draft.partialManifest) : /* @__PURE__ */ new Map();
|
|
32984
|
+
const explicit = selections.flatMap((selection) => {
|
|
32985
|
+
const types = required2.get(selection.connectorId);
|
|
32986
|
+
if (!types || selection.connectionType && !types.has(selection.connectionType)) {
|
|
32987
|
+
const slot = selection.connectionType ? `${selection.connectorId} (${selection.connectionType})` : selection.connectorId;
|
|
32988
|
+
throw new DraftWorkflowError("connector_not_required", `Connector ${slot} is not used by draft ${draftId}. Required: ${describeRequired(required2)}.`, { draftId });
|
|
32989
|
+
}
|
|
32990
|
+
const connectionTypes = selection.connectionType ? [selection.connectionType] : [...types];
|
|
32991
|
+
return connectionTypes.map((connectionType) => ({ ...selection, connectionType }));
|
|
32992
|
+
});
|
|
32993
|
+
for (const { connectorId, connectionType, connectionId } of explicit) {
|
|
32994
|
+
await draftApi.upsertConnection(draftId, { connectorId, connectionType, connectionId });
|
|
32995
|
+
bound.push({ connectorId, connectionType, connectionId, mode: "explicit" });
|
|
32996
|
+
}
|
|
32997
|
+
const unresolved = [];
|
|
32998
|
+
if (auto) {
|
|
32999
|
+
const status = await draftApi.getConnectionStatus(draftId);
|
|
33000
|
+
for (const connector of status.connectors) {
|
|
33001
|
+
for (const connectionType of ["mcp", "trigger"]) {
|
|
33002
|
+
const slot = connector[connectionType];
|
|
33003
|
+
if (!slot.required || slot.status !== "missing")
|
|
33004
|
+
continue;
|
|
33005
|
+
const { connections } = await draftApi.listConnections({
|
|
33006
|
+
connectorId: connector.id,
|
|
33007
|
+
capability: connectionType,
|
|
33008
|
+
status: "authorized"
|
|
33009
|
+
});
|
|
33010
|
+
const [only] = connections;
|
|
33011
|
+
if (connections.length === 1 && only) {
|
|
33012
|
+
await draftApi.upsertConnection(draftId, {
|
|
33013
|
+
connectorId: connector.id,
|
|
33014
|
+
connectionType,
|
|
33015
|
+
connectionId: only.id
|
|
33016
|
+
});
|
|
33017
|
+
bound.push({
|
|
33018
|
+
connectorId: connector.id,
|
|
33019
|
+
connectionType,
|
|
33020
|
+
connectionId: only.id,
|
|
33021
|
+
mode: "auto"
|
|
33022
|
+
});
|
|
33023
|
+
continue;
|
|
33024
|
+
}
|
|
33025
|
+
unresolved.push({
|
|
33026
|
+
connectorId: connector.id,
|
|
33027
|
+
connectionType,
|
|
33028
|
+
reason: connections.length === 0 ? "no_connection" : "multiple_connections",
|
|
33029
|
+
candidateConnectionIds: connections.map((connection) => connection.id)
|
|
33030
|
+
});
|
|
33031
|
+
}
|
|
33032
|
+
}
|
|
33033
|
+
}
|
|
33034
|
+
const { isValid, missing } = await draftApi.getConnectionStatus(draftId);
|
|
33035
|
+
return { action: "connected", draftId, bound, unresolved, isValid, missing };
|
|
33036
|
+
}
|
|
33037
|
+
function describeRequired(required2) {
|
|
33038
|
+
if (required2.size === 0)
|
|
33039
|
+
return "none";
|
|
33040
|
+
return [...required2].map(([connectorId, types]) => `${connectorId} (${[...types].join(", ")})`).join(", ");
|
|
33041
|
+
}
|
|
33042
|
+
|
|
33043
|
+
// ../../packages/sdk/dist/esm/drafts/manifest-diff.js
|
|
33044
|
+
function stableStringify(value) {
|
|
33045
|
+
return JSON.stringify(sortKeys(value));
|
|
33046
|
+
}
|
|
33047
|
+
function isDeepEqual(left, right) {
|
|
33048
|
+
return stableStringify(left) === stableStringify(right);
|
|
33049
|
+
}
|
|
33050
|
+
function diffManifests(before, after) {
|
|
33051
|
+
const previous = asManifest(before);
|
|
33052
|
+
const next = asManifest(after);
|
|
33053
|
+
const changedProperties = [.../* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(next)])].filter((key) => key !== "steps").filter((key) => !isDeepEqual(previous[key], next[key])).sort();
|
|
33054
|
+
const previousSteps = stepsById(previous.steps);
|
|
33055
|
+
const nextSteps = stepsById(next.steps);
|
|
33056
|
+
const added = [...nextSteps.keys()].filter((id) => !previousSteps.has(id));
|
|
33057
|
+
const removed = [...previousSteps.keys()].filter((id) => !nextSteps.has(id));
|
|
33058
|
+
const changed = [...nextSteps].filter(([id, step]) => previousSteps.has(id) && !isDeepEqual(previousSteps.get(id), step)).map(([id]) => id);
|
|
33059
|
+
const sharedBefore = [...previousSteps.keys()].filter((id) => nextSteps.has(id));
|
|
33060
|
+
const sharedAfter = [...nextSteps.keys()].filter((id) => previousSteps.has(id));
|
|
33061
|
+
const reordered = sharedBefore.some((id, index) => sharedAfter[index] !== id);
|
|
33062
|
+
return {
|
|
33063
|
+
changedProperties,
|
|
33064
|
+
steps: { added, removed, changed, reordered },
|
|
33065
|
+
isEmpty: changedProperties.length === 0 && added.length === 0 && removed.length === 0 && changed.length === 0 && !reordered
|
|
33066
|
+
};
|
|
33067
|
+
}
|
|
33068
|
+
function asManifest(value) {
|
|
33069
|
+
return isManifestRecord(value) ? value : {};
|
|
33070
|
+
}
|
|
33071
|
+
function stepsById(steps) {
|
|
33072
|
+
const byId = /* @__PURE__ */ new Map();
|
|
33073
|
+
if (!Array.isArray(steps))
|
|
33074
|
+
return byId;
|
|
33075
|
+
steps.forEach((step, index) => {
|
|
33076
|
+
const id = isManifestRecord(step) && typeof step.id === "string" ? step.id : `#${index}`;
|
|
33077
|
+
byId.set(id, step);
|
|
33078
|
+
});
|
|
33079
|
+
return byId;
|
|
33080
|
+
}
|
|
33081
|
+
function sortKeys(value) {
|
|
33082
|
+
if (Array.isArray(value))
|
|
33083
|
+
return value.map(sortKeys);
|
|
33084
|
+
if (!isManifestRecord(value))
|
|
33085
|
+
return value;
|
|
33086
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortKeys(value[key])]));
|
|
33087
|
+
}
|
|
33088
|
+
|
|
33089
|
+
// ../../packages/sdk/dist/esm/drafts/publish-draft.js
|
|
33090
|
+
async function publishDraft(draftApi, { draftId, confirmed }) {
|
|
33091
|
+
const { summary, manifest } = await summarizeForPublish(draftApi, draftId);
|
|
33092
|
+
if (!confirmed) {
|
|
33093
|
+
return { action: "publish_preview", summary };
|
|
33094
|
+
}
|
|
33095
|
+
let published;
|
|
33096
|
+
try {
|
|
33097
|
+
published = await draftApi.finalize(draftId);
|
|
33098
|
+
} catch (error62) {
|
|
33099
|
+
const notReady = getDraftNotReadyError(error62);
|
|
33100
|
+
if (!notReady)
|
|
33101
|
+
throw error62;
|
|
33102
|
+
throw new DraftWorkflowError("draft_not_ready", notReady.message, {
|
|
33103
|
+
draftId,
|
|
33104
|
+
cause: error62
|
|
33105
|
+
});
|
|
33106
|
+
}
|
|
33107
|
+
let automation;
|
|
33108
|
+
try {
|
|
33109
|
+
automation = await draftApi.getAutomation(published.automation.id);
|
|
33110
|
+
} catch (error62) {
|
|
33111
|
+
return {
|
|
33112
|
+
action: "published",
|
|
33113
|
+
summary,
|
|
33114
|
+
automation: published.automation,
|
|
33115
|
+
verification: { status: "unavailable", reason: getErrorMessage(error62) }
|
|
33116
|
+
};
|
|
33117
|
+
}
|
|
33118
|
+
const expected = normaliseManifest(manifest);
|
|
33119
|
+
const actual = normaliseManifest(automation.manifest);
|
|
33120
|
+
return {
|
|
33121
|
+
action: "published",
|
|
33122
|
+
summary,
|
|
33123
|
+
automation,
|
|
33124
|
+
verification: isDeepEqual(expected, actual) ? { status: "matched" } : { status: "mismatched", mismatch: diffManifests(expected, actual) }
|
|
33125
|
+
};
|
|
33126
|
+
}
|
|
33127
|
+
async function summarizeForPublish(draftApi, draftId) {
|
|
33128
|
+
const [detail, connections] = await Promise.all([
|
|
33129
|
+
draftApi.get(draftId),
|
|
33130
|
+
draftApi.getConnectionStatus(draftId)
|
|
33131
|
+
]);
|
|
33132
|
+
const { draft } = detail;
|
|
33133
|
+
const target = toDraftTarget(draft);
|
|
33134
|
+
const published = target.kind === "automation" ? await draftApi.getAutomation(target.automationId) : null;
|
|
33135
|
+
const diff = published ? diffManifests(normaliseManifest(published.manifest), normaliseManifest(draft.partialManifest)) : null;
|
|
33136
|
+
const summary = {
|
|
33137
|
+
draftId,
|
|
33138
|
+
name: readManifestName(draft.partialManifest),
|
|
33139
|
+
scope: draft.workspaceId === null ? { kind: "personal" } : {
|
|
33140
|
+
kind: "workspace",
|
|
33141
|
+
workspaceId: draft.workspaceId,
|
|
33142
|
+
// A new workspace automation publishes team-visible; an
|
|
33143
|
+
// edit keeps whatever the automation already has.
|
|
33144
|
+
visibility: published?.visibility ?? "workspace"
|
|
33145
|
+
},
|
|
33146
|
+
target,
|
|
33147
|
+
enabled: published?.enabled ?? true,
|
|
33148
|
+
validation: { state: detail.state, issues: detail.issues },
|
|
33149
|
+
connections: {
|
|
33150
|
+
isValid: connections.isValid,
|
|
33151
|
+
connected: connections.connected.map(({ connectorId, connectionType, connectionId }) => ({
|
|
33152
|
+
connectorId,
|
|
33153
|
+
connectionType,
|
|
33154
|
+
connectionId
|
|
33155
|
+
})),
|
|
33156
|
+
missing: connections.missing
|
|
33157
|
+
},
|
|
33158
|
+
schedule: describeSchedule(draft.partialManifest),
|
|
33159
|
+
diff
|
|
33160
|
+
};
|
|
33161
|
+
return { summary, manifest: draft.partialManifest };
|
|
33162
|
+
}
|
|
33163
|
+
function describeSchedule(manifest) {
|
|
33164
|
+
if (!hasTriggerType(manifest))
|
|
33165
|
+
return null;
|
|
33166
|
+
const schedule = getManifestTriggers(manifest).find((trigger) => trigger.type === "schedule");
|
|
33167
|
+
if (!schedule || schedule.type !== "schedule")
|
|
33168
|
+
return null;
|
|
33169
|
+
return getScheduleTriggerDescription({ value: schedule.value, timeFormat: "24h" });
|
|
33170
|
+
}
|
|
33171
|
+
function normaliseManifest(manifest) {
|
|
33172
|
+
const parsed = manifestSchema.safeParse(manifest);
|
|
33173
|
+
return parsed.success ? parsed.data : manifest;
|
|
33174
|
+
}
|
|
33175
|
+
function readManifestName(manifest) {
|
|
33176
|
+
if (!isManifestRecord(manifest))
|
|
33177
|
+
return "(unnamed)";
|
|
33178
|
+
const { name } = manifest;
|
|
33179
|
+
return typeof name === "string" && name.trim() ? name : "(unnamed)";
|
|
33180
|
+
}
|
|
33181
|
+
|
|
32875
33182
|
// src/lib/auth-environment.ts
|
|
32876
33183
|
import { InvalidArgumentError } from "commander";
|
|
32877
33184
|
var ENVIRONMENTS = {
|
|
@@ -33095,7 +33402,7 @@ function createAutomationsTokenStore(options = {}) {
|
|
|
33095
33402
|
}
|
|
33096
33403
|
|
|
33097
33404
|
// src/lib/credentials.ts
|
|
33098
|
-
import { CliError, getConfigPath as getConfigPath3, getErrorMessage as
|
|
33405
|
+
import { CliError, getConfigPath as getConfigPath3, getErrorMessage as getErrorMessage4 } from "@doist/cli-core";
|
|
33099
33406
|
import { refreshAccessToken } from "@doist/cli-core/auth";
|
|
33100
33407
|
|
|
33101
33408
|
// src/lib/auth-scopes.ts
|
|
@@ -33185,7 +33492,7 @@ function formatScopesHelp() {
|
|
|
33185
33492
|
}
|
|
33186
33493
|
|
|
33187
33494
|
// src/lib/auth-provider.ts
|
|
33188
|
-
import { getErrorMessage } from "@doist/cli-core";
|
|
33495
|
+
import { getErrorMessage as getErrorMessage2 } from "@doist/cli-core";
|
|
33189
33496
|
import { createPkceProvider } from "@doist/cli-core/auth";
|
|
33190
33497
|
var ERROR_HINTS = ["Try again: tda auth login"];
|
|
33191
33498
|
function createAutomationsAuthProvider() {
|
|
@@ -33225,7 +33532,7 @@ async function fetchTodoistUser(token, todoistApiUrl) {
|
|
|
33225
33532
|
});
|
|
33226
33533
|
} catch (error62) {
|
|
33227
33534
|
throw new Error(
|
|
33228
|
-
`Could not reach Todoist to identify the account: ${
|
|
33535
|
+
`Could not reach Todoist to identify the account: ${getErrorMessage2(error62)}`
|
|
33229
33536
|
);
|
|
33230
33537
|
}
|
|
33231
33538
|
if (!response.ok) {
|
|
@@ -33238,7 +33545,7 @@ async function fetchTodoistUser(token, todoistApiUrl) {
|
|
|
33238
33545
|
user = await response.json();
|
|
33239
33546
|
} catch (error62) {
|
|
33240
33547
|
throw new Error(
|
|
33241
|
-
`Todoist returned an unreadable identity response: ${
|
|
33548
|
+
`Todoist returned an unreadable identity response: ${getErrorMessage2(error62)}`
|
|
33242
33549
|
);
|
|
33243
33550
|
}
|
|
33244
33551
|
return { id: requireUserId(user.id), email: typeof user.email === "string" ? user.email : "" };
|
|
@@ -33250,13 +33557,13 @@ function requireUserId(id) {
|
|
|
33250
33557
|
}
|
|
33251
33558
|
|
|
33252
33559
|
// src/lib/errors.ts
|
|
33253
|
-
import { getErrorMessage as
|
|
33560
|
+
import { getErrorMessage as getErrorMessage3 } from "@doist/cli-core";
|
|
33254
33561
|
function getErrorCode(error62) {
|
|
33255
33562
|
return typeof error62 === "object" && error62 !== null && "code" in error62 ? String(error62.code) : void 0;
|
|
33256
33563
|
}
|
|
33257
33564
|
function formatError2(error62) {
|
|
33258
33565
|
const hints = errorHints(error62);
|
|
33259
|
-
return [
|
|
33566
|
+
return [getErrorMessage3(error62), ...hints.map((hint) => ` - ${hint}`)].join("\n");
|
|
33260
33567
|
}
|
|
33261
33568
|
function errorHints(error62) {
|
|
33262
33569
|
if (typeof error62 !== "object" || error62 === null || !("hints" in error62)) return [];
|
|
@@ -33336,7 +33643,7 @@ function accessTokenAfterFailedRefresh(error62, snapshot) {
|
|
|
33336
33643
|
if (hasTokenLifeLeft(snapshot)) return snapshot.bundle.accessToken;
|
|
33337
33644
|
throw new CredentialError(
|
|
33338
33645
|
"REFRESH_FAILED",
|
|
33339
|
-
`Could not refresh your access token: ${
|
|
33646
|
+
`Could not refresh your access token: ${getErrorMessage4(error62)}`,
|
|
33340
33647
|
["Check your network connection and try again."]
|
|
33341
33648
|
);
|
|
33342
33649
|
}
|
|
@@ -33364,19 +33671,19 @@ function resolveAfterStoreFailure(error62) {
|
|
|
33364
33671
|
if (code !== "AUTH_STORE_READ_FAILED") {
|
|
33365
33672
|
throw new CredentialError(
|
|
33366
33673
|
"CREDENTIAL_UNREADABLE",
|
|
33367
|
-
`Could not read the stored credential: ${
|
|
33674
|
+
`Could not read the stored credential: ${getErrorMessage4(error62)}`,
|
|
33368
33675
|
["Run `tda auth logout` and then `tda auth login` to replace it."]
|
|
33369
33676
|
);
|
|
33370
33677
|
}
|
|
33371
33678
|
const fallback = fromEnvironment();
|
|
33372
33679
|
if (fallback) {
|
|
33373
33680
|
process.stderr.write(
|
|
33374
|
-
`Warning: could not read the stored credential (${
|
|
33681
|
+
`Warning: could not read the stored credential (${getErrorMessage4(error62)}). Using ${TOKEN_ENV_VAR}.
|
|
33375
33682
|
`
|
|
33376
33683
|
);
|
|
33377
33684
|
return fallback;
|
|
33378
33685
|
}
|
|
33379
|
-
throw new CredentialError("CREDENTIAL_UNREADABLE",
|
|
33686
|
+
throw new CredentialError("CREDENTIAL_UNREADABLE", getErrorMessage4(error62), [
|
|
33380
33687
|
`Set ${TOKEN_ENV_VAR} to bypass the credential store.`,
|
|
33381
33688
|
"Or re-run `tda auth login --credential-store plaintext`."
|
|
33382
33689
|
]);
|
|
@@ -34039,7 +34346,7 @@ function attachAutomationsLoginCommand(auth) {
|
|
|
34039
34346
|
}
|
|
34040
34347
|
|
|
34041
34348
|
// src/commands/auth/logout.ts
|
|
34042
|
-
import { getErrorMessage as
|
|
34349
|
+
import { getErrorMessage as getErrorMessage5 } from "@doist/cli-core";
|
|
34043
34350
|
import { attachLogoutCommand } from "@doist/cli-core/auth";
|
|
34044
34351
|
|
|
34045
34352
|
// src/lib/spinner.ts
|
|
@@ -34087,7 +34394,7 @@ async function revokeToken(token) {
|
|
|
34087
34394
|
});
|
|
34088
34395
|
return response.ok ? void 0 : `HTTP ${response.status}`;
|
|
34089
34396
|
} catch (error62) {
|
|
34090
|
-
return
|
|
34397
|
+
return getErrorMessage5(error62);
|
|
34091
34398
|
}
|
|
34092
34399
|
}
|
|
34093
34400
|
|
|
@@ -34218,7 +34525,7 @@ function parsePositiveInteger(value) {
|
|
|
34218
34525
|
}
|
|
34219
34526
|
|
|
34220
34527
|
// src/lib/command-error.ts
|
|
34221
|
-
import { formatJson as formatJson4, formatNdjson as formatNdjson4, getErrorMessage as
|
|
34528
|
+
import { formatJson as formatJson4, formatNdjson as formatNdjson4, getErrorMessage as getErrorMessage6 } from "@doist/cli-core";
|
|
34222
34529
|
|
|
34223
34530
|
// src/lib/billing-errors.ts
|
|
34224
34531
|
import { CliError as CliError2 } from "@doist/cli-core";
|
|
@@ -34297,7 +34604,7 @@ function renderFailure(error62, context = {}) {
|
|
|
34297
34604
|
const explained = explainBillingFailure(authExplained);
|
|
34298
34605
|
const code = getErrorCode(explained);
|
|
34299
34606
|
return {
|
|
34300
|
-
message:
|
|
34607
|
+
message: getErrorMessage6(explained),
|
|
34301
34608
|
humanMessage: formatError2(explained),
|
|
34302
34609
|
...code ? { code } : {}
|
|
34303
34610
|
};
|
|
@@ -36955,7 +37262,7 @@ function registerConnectorCommand(program) {
|
|
|
36955
37262
|
}
|
|
36956
37263
|
|
|
36957
37264
|
// src/lib/manifest-input.ts
|
|
36958
|
-
import { CliError as CliError3, getErrorMessage as
|
|
37265
|
+
import { CliError as CliError3, getErrorMessage as getErrorMessage7 } from "@doist/cli-core";
|
|
36959
37266
|
import { Option as Option6 } from "commander";
|
|
36960
37267
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
36961
37268
|
import { text } from "node:stream/consumers";
|
|
@@ -36971,20 +37278,10 @@ async function readManifestInput(options, input2 = process.stdin) {
|
|
|
36971
37278
|
} catch (error62) {
|
|
36972
37279
|
throw new CliError3(
|
|
36973
37280
|
"MANIFEST_UNREADABLE",
|
|
36974
|
-
`${source.label} is not valid JSON: ${
|
|
37281
|
+
`${source.label} is not valid JSON: ${getErrorMessage7(error62)}`
|
|
36975
37282
|
);
|
|
36976
37283
|
}
|
|
36977
37284
|
}
|
|
36978
|
-
function parsePartialManifestInput(value) {
|
|
36979
|
-
const validation = validatePartialManifest(value);
|
|
36980
|
-
if (!validation.isValid) {
|
|
36981
|
-
throw new CliError3(
|
|
36982
|
-
"MANIFEST_INVALID",
|
|
36983
|
-
`Manifest is invalid: ${validation.errors.join("; ")}`
|
|
36984
|
-
);
|
|
36985
|
-
}
|
|
36986
|
-
return validation.data;
|
|
36987
|
-
}
|
|
36988
37285
|
async function readSource(options, input2) {
|
|
36989
37286
|
if (options.file !== void 0) {
|
|
36990
37287
|
try {
|
|
@@ -36992,7 +37289,7 @@ async function readSource(options, input2) {
|
|
|
36992
37289
|
} catch (error62) {
|
|
36993
37290
|
throw new CliError3(
|
|
36994
37291
|
"MANIFEST_UNREADABLE",
|
|
36995
|
-
`Could not read ${options.file}: ${
|
|
37292
|
+
`Could not read ${options.file}: ${getErrorMessage7(error62)}`
|
|
36996
37293
|
);
|
|
36997
37294
|
}
|
|
36998
37295
|
}
|
|
@@ -37002,7 +37299,7 @@ async function readSource(options, input2) {
|
|
|
37002
37299
|
} catch (error62) {
|
|
37003
37300
|
throw new CliError3(
|
|
37004
37301
|
"MANIFEST_UNREADABLE",
|
|
37005
|
-
`Could not read standard input: ${
|
|
37302
|
+
`Could not read standard input: ${getErrorMessage7(error62)}`
|
|
37006
37303
|
);
|
|
37007
37304
|
}
|
|
37008
37305
|
}
|
|
@@ -37010,134 +37307,56 @@ async function readSource(options, input2) {
|
|
|
37010
37307
|
}
|
|
37011
37308
|
|
|
37012
37309
|
// src/commands/draft/draft-service.ts
|
|
37013
|
-
import { CliError as CliError4, getErrorMessage as
|
|
37310
|
+
import { CliError as CliError4, getErrorMessage as getErrorMessage8 } from "@doist/cli-core";
|
|
37014
37311
|
import { readFile as readFile3 } from "node:fs/promises";
|
|
37015
37312
|
import { setTimeout as wait2 } from "node:timers/promises";
|
|
37016
|
-
|
|
37017
|
-
|
|
37018
|
-
function stableStringify(value) {
|
|
37019
|
-
return JSON.stringify(sortKeys(value));
|
|
37313
|
+
function createDraft2(draftApi, input2) {
|
|
37314
|
+
return withRecoveryHints(draftApi, createDraft(draftApi, input2));
|
|
37020
37315
|
}
|
|
37021
|
-
function
|
|
37022
|
-
return
|
|
37316
|
+
function updateDraft2(draftApi, input2) {
|
|
37317
|
+
return withRecoveryHints(draftApi, updateDraft(draftApi, input2));
|
|
37023
37318
|
}
|
|
37024
|
-
function
|
|
37025
|
-
|
|
37026
|
-
const next = asManifest(after);
|
|
37027
|
-
const changedProperties = [.../* @__PURE__ */ new Set([...Object.keys(previous), ...Object.keys(next)])].filter((key) => key !== "steps").filter((key) => !isDeepEqual(previous[key], next[key])).sort();
|
|
37028
|
-
const previousSteps = stepsById(previous.steps);
|
|
37029
|
-
const nextSteps = stepsById(next.steps);
|
|
37030
|
-
const added = [...nextSteps.keys()].filter((id) => !previousSteps.has(id));
|
|
37031
|
-
const removed = [...previousSteps.keys()].filter((id) => !nextSteps.has(id));
|
|
37032
|
-
const changed = [...nextSteps].filter(([id, step]) => previousSteps.has(id) && !isDeepEqual(previousSteps.get(id), step)).map(([id]) => id);
|
|
37033
|
-
const sharedBefore = [...previousSteps.keys()].filter((id) => nextSteps.has(id));
|
|
37034
|
-
const sharedAfter = [...nextSteps.keys()].filter((id) => previousSteps.has(id));
|
|
37035
|
-
const reordered = sharedBefore.some((id, index) => sharedAfter[index] !== id);
|
|
37036
|
-
return {
|
|
37037
|
-
changedProperties,
|
|
37038
|
-
steps: { added, removed, changed, reordered },
|
|
37039
|
-
isEmpty: changedProperties.length === 0 && added.length === 0 && removed.length === 0 && changed.length === 0 && !reordered
|
|
37040
|
-
};
|
|
37041
|
-
}
|
|
37042
|
-
function asManifest(value) {
|
|
37043
|
-
return isRecord3(value) ? value : {};
|
|
37044
|
-
}
|
|
37045
|
-
function stepsById(steps) {
|
|
37046
|
-
const byId = /* @__PURE__ */ new Map();
|
|
37047
|
-
if (!Array.isArray(steps)) return byId;
|
|
37048
|
-
steps.forEach((step, index) => {
|
|
37049
|
-
const id = isRecord3(step) && typeof step.id === "string" ? step.id : `#${index}`;
|
|
37050
|
-
byId.set(id, step);
|
|
37051
|
-
});
|
|
37052
|
-
return byId;
|
|
37053
|
-
}
|
|
37054
|
-
function sortKeys(value) {
|
|
37055
|
-
if (Array.isArray(value)) return value.map(sortKeys);
|
|
37056
|
-
if (!isRecord3(value)) return value;
|
|
37057
|
-
return Object.fromEntries(
|
|
37058
|
-
Object.keys(value).sort().map((key) => [key, sortKeys(value[key])])
|
|
37059
|
-
);
|
|
37319
|
+
function connectDraft2(draftApi, input2) {
|
|
37320
|
+
return withRecoveryHints(draftApi, connectDraft(draftApi, input2));
|
|
37060
37321
|
}
|
|
37061
|
-
function
|
|
37062
|
-
|
|
37063
|
-
|
|
37064
|
-
|
|
37065
|
-
|
|
37066
|
-
function resolveDraftApi(api, workspaceId, signal) {
|
|
37067
|
-
const createOptions = { signal, translate: false };
|
|
37068
|
-
if (workspaceId === null) {
|
|
37069
|
-
return {
|
|
37070
|
-
scope: null,
|
|
37071
|
-
get: (draftId) => api.automationDrafts.get(draftId, { signal }),
|
|
37072
|
-
create: (manifest) => api.automationDrafts.create(manifest, createOptions),
|
|
37073
|
-
update: (draftId, manifest) => api.automationDrafts.update(draftId, manifest, { signal }),
|
|
37074
|
-
createAutomationDraft: (automationId) => api.automations.createDraft(automationId, { signal }),
|
|
37075
|
-
upsertConnection: (draftId, body) => api.automationDraftConnections.upsert(draftId, body, { signal }),
|
|
37076
|
-
getConnectionStatus: async (draftId) => (await api.automationDraftConnections.getStatus(draftId, { signal })).validation,
|
|
37077
|
-
finalize: (draftId) => api.automationDrafts.finalize(draftId, { signal }),
|
|
37078
|
-
getAutomation: (automationId) => api.automations.get(automationId, { signal }),
|
|
37079
|
-
test: (draftId, request2) => api.automationDrafts.test(draftId, request2, { signal }),
|
|
37080
|
-
getTestRun: (draftId, runId, args, requestSignal) => api.automationDrafts.getTestRun(draftId, runId, args, {
|
|
37081
|
-
signal: requestSignal ?? signal
|
|
37082
|
-
})
|
|
37083
|
-
};
|
|
37084
|
-
}
|
|
37322
|
+
async function publishDraft2(draftApi, input2) {
|
|
37323
|
+
const result = await withRecoveryHints(draftApi, publishDraft(draftApi, input2));
|
|
37324
|
+
if (result.action === "publish_preview") return result;
|
|
37325
|
+
const { verification } = result;
|
|
37326
|
+
if (verification.status !== "unavailable") return { ...result, verification };
|
|
37085
37327
|
return {
|
|
37086
|
-
|
|
37087
|
-
|
|
37088
|
-
|
|
37089
|
-
|
|
37090
|
-
|
|
37091
|
-
upsertConnection: (draftId, body) => api.workspaceAutomationDraftConnections.upsert(workspaceId, draftId, body, { signal }),
|
|
37092
|
-
getConnectionStatus: async (draftId) => (await api.workspaceAutomationDraftConnections.getStatus(workspaceId, draftId, {
|
|
37093
|
-
signal
|
|
37094
|
-
})).validation,
|
|
37095
|
-
finalize: (draftId) => api.workspaceAutomationDrafts.finalize(workspaceId, draftId, { signal }),
|
|
37096
|
-
getAutomation: (automationId) => api.workspaceAutomations.get(workspaceId, automationId, { signal }),
|
|
37097
|
-
test: (draftId, request2) => api.workspaceAutomationDrafts.test(workspaceId, draftId, request2, { signal }),
|
|
37098
|
-
getTestRun: (draftId, runId, args, requestSignal) => api.workspaceAutomationDrafts.getTestRun(workspaceId, draftId, runId, args, {
|
|
37099
|
-
signal: requestSignal ?? signal
|
|
37100
|
-
})
|
|
37328
|
+
...result,
|
|
37329
|
+
verification: {
|
|
37330
|
+
...verification,
|
|
37331
|
+
command: `tda automation view ${result.automation.id} ${scopeFlag(draftApi.workspaceId)}`
|
|
37332
|
+
}
|
|
37101
37333
|
};
|
|
37102
37334
|
}
|
|
37103
|
-
async function
|
|
37104
|
-
const partialManifest = parsePartialManifestInput(manifest);
|
|
37105
|
-
if (automationId === void 0) {
|
|
37106
|
-
const result = await draftApi.create(partialManifest);
|
|
37107
|
-
return { action: "created", target: toTarget(result.draft), ...result };
|
|
37108
|
-
}
|
|
37109
|
-
const { draft } = await openEditDraft(draftApi, automationId);
|
|
37335
|
+
async function withRecoveryHints(draftApi, operation) {
|
|
37110
37336
|
try {
|
|
37111
|
-
|
|
37112
|
-
return { action: "created", target: toTarget(result.draft), ...result };
|
|
37337
|
+
return await operation;
|
|
37113
37338
|
} catch (error62) {
|
|
37114
|
-
if (!
|
|
37115
|
-
|
|
37116
|
-
|
|
37117
|
-
|
|
37118
|
-
|
|
37119
|
-
|
|
37120
|
-
|
|
37121
|
-
|
|
37122
|
-
|
|
37123
|
-
|
|
37124
|
-
|
|
37125
|
-
|
|
37126
|
-
|
|
37127
|
-
|
|
37128
|
-
|
|
37129
|
-
|
|
37130
|
-
|
|
37131
|
-
|
|
37132
|
-
|
|
37133
|
-
|
|
37134
|
-
|
|
37135
|
-
if (!conflict) throw error62;
|
|
37136
|
-
throw new CliError4(
|
|
37137
|
-
"DRAFT_CONFLICT",
|
|
37138
|
-
`Automation ${automationId} already has an open draft ${conflict.draftId}.`,
|
|
37139
|
-
{ hints: draftHints(draftApi.scope, conflict.draftId) }
|
|
37140
|
-
);
|
|
37339
|
+
if (!(error62 instanceof DraftWorkflowError)) throw error62;
|
|
37340
|
+
const scope = draftApi.workspaceId;
|
|
37341
|
+
const draftId = error62.draftId ?? "<draft-id>";
|
|
37342
|
+
switch (error62.code) {
|
|
37343
|
+
case "manifest_invalid":
|
|
37344
|
+
throw new CliError4("MANIFEST_INVALID", error62.message);
|
|
37345
|
+
case "draft_conflict":
|
|
37346
|
+
throw new CliError4("DRAFT_CONFLICT", error62.message, {
|
|
37347
|
+
hints: draftHints(scope, draftId)
|
|
37348
|
+
});
|
|
37349
|
+
case "draft_manifest_rejected":
|
|
37350
|
+
throw new CliError4("DRAFT_MANIFEST_REJECTED", error62.message, {
|
|
37351
|
+
hints: draftHints(scope, draftId)
|
|
37352
|
+
});
|
|
37353
|
+
case "draft_not_ready":
|
|
37354
|
+
throw draftNotReadyError(error62.message, draftId, scope);
|
|
37355
|
+
case "connector_not_required":
|
|
37356
|
+
throw new Error(error62.message);
|
|
37357
|
+
default:
|
|
37358
|
+
throw error62;
|
|
37359
|
+
}
|
|
37141
37360
|
}
|
|
37142
37361
|
}
|
|
37143
37362
|
function draftHints(scope, draftId) {
|
|
@@ -37149,168 +37368,6 @@ function draftHints(scope, draftId) {
|
|
|
37149
37368
|
function scopeFlag(scope) {
|
|
37150
37369
|
return scope === null ? "--personal" : `--workspace ${scope}`;
|
|
37151
37370
|
}
|
|
37152
|
-
function toTarget(draft) {
|
|
37153
|
-
return draft.automationId === null ? { kind: "new" } : { kind: "automation", automationId: draft.automationId };
|
|
37154
|
-
}
|
|
37155
|
-
async function connectDraft(draftApi, api, {
|
|
37156
|
-
draftId,
|
|
37157
|
-
selections,
|
|
37158
|
-
auto
|
|
37159
|
-
}) {
|
|
37160
|
-
const bound = [];
|
|
37161
|
-
const required2 = selections.length > 0 ? getRequiredConnectorsFromManifest(
|
|
37162
|
-
(await draftApi.get(draftId)).draft.partialManifest
|
|
37163
|
-
) : /* @__PURE__ */ new Map();
|
|
37164
|
-
for (const selection of selections) {
|
|
37165
|
-
const types = required2.get(selection.connectorId);
|
|
37166
|
-
if (!types || selection.connectionType && !types.has(selection.connectionType)) {
|
|
37167
|
-
const slot = selection.connectionType ? `${selection.connectorId} (${selection.connectionType})` : selection.connectorId;
|
|
37168
|
-
throw new Error(
|
|
37169
|
-
`Connector ${slot} is not used by draft ${draftId}. Required: ${describeRequired(required2)}.`
|
|
37170
|
-
);
|
|
37171
|
-
}
|
|
37172
|
-
const connectionTypes = selection.connectionType ? [selection.connectionType] : [...types];
|
|
37173
|
-
for (const connectionType of connectionTypes) {
|
|
37174
|
-
await draftApi.upsertConnection(draftId, {
|
|
37175
|
-
connectorId: selection.connectorId,
|
|
37176
|
-
connectionType,
|
|
37177
|
-
connectionId: selection.connectionId
|
|
37178
|
-
});
|
|
37179
|
-
bound.push({ ...selection, connectionType, mode: "explicit" });
|
|
37180
|
-
}
|
|
37181
|
-
}
|
|
37182
|
-
const unresolved = [];
|
|
37183
|
-
if (auto) {
|
|
37184
|
-
const status = await draftApi.getConnectionStatus(draftId);
|
|
37185
|
-
for (const connector of status.connectors) {
|
|
37186
|
-
for (const connectionType of ["mcp", "trigger"]) {
|
|
37187
|
-
const slot = connector[connectionType];
|
|
37188
|
-
if (!slot.required || slot.status !== "missing") continue;
|
|
37189
|
-
const { connections } = await api.connections.list({
|
|
37190
|
-
connectorId: connector.id,
|
|
37191
|
-
capability: connectionType,
|
|
37192
|
-
status: "authorized"
|
|
37193
|
-
});
|
|
37194
|
-
const [only] = connections;
|
|
37195
|
-
if (connections.length === 1 && only) {
|
|
37196
|
-
await draftApi.upsertConnection(draftId, {
|
|
37197
|
-
connectorId: connector.id,
|
|
37198
|
-
connectionType,
|
|
37199
|
-
connectionId: only.id
|
|
37200
|
-
});
|
|
37201
|
-
bound.push({
|
|
37202
|
-
connectorId: connector.id,
|
|
37203
|
-
connectionType,
|
|
37204
|
-
connectionId: only.id,
|
|
37205
|
-
mode: "auto"
|
|
37206
|
-
});
|
|
37207
|
-
continue;
|
|
37208
|
-
}
|
|
37209
|
-
unresolved.push({
|
|
37210
|
-
connectorId: connector.id,
|
|
37211
|
-
connectionType,
|
|
37212
|
-
reason: connections.length === 0 ? "no_connection" : "multiple_connections",
|
|
37213
|
-
candidateConnectionIds: connections.map((connection) => connection.id)
|
|
37214
|
-
});
|
|
37215
|
-
}
|
|
37216
|
-
}
|
|
37217
|
-
}
|
|
37218
|
-
const { isValid, missing } = await draftApi.getConnectionStatus(draftId);
|
|
37219
|
-
return { action: "connected", draftId, bound, unresolved, isValid, missing };
|
|
37220
|
-
}
|
|
37221
|
-
function describeRequired(required2) {
|
|
37222
|
-
if (required2.size === 0) return "none";
|
|
37223
|
-
return [...required2].map(([connectorId, types]) => `${connectorId} (${[...types].join(", ")})`).join(", ");
|
|
37224
|
-
}
|
|
37225
|
-
async function publishDraft(draftApi, { draftId, confirmed }) {
|
|
37226
|
-
const { summary, manifest } = await summarizeForPublish(draftApi, draftId);
|
|
37227
|
-
if (!confirmed) {
|
|
37228
|
-
return { action: "publish_preview", summary };
|
|
37229
|
-
}
|
|
37230
|
-
let published;
|
|
37231
|
-
try {
|
|
37232
|
-
published = await draftApi.finalize(draftId);
|
|
37233
|
-
} catch (error62) {
|
|
37234
|
-
const notReady = getDraftNotReadyError(error62);
|
|
37235
|
-
if (!notReady) throw error62;
|
|
37236
|
-
throw draftNotReadyError(notReady.message, draftId, draftApi.scope);
|
|
37237
|
-
}
|
|
37238
|
-
const automationId = published.automation.id;
|
|
37239
|
-
let automation;
|
|
37240
|
-
try {
|
|
37241
|
-
automation = await draftApi.getAutomation(automationId);
|
|
37242
|
-
} catch (error62) {
|
|
37243
|
-
return {
|
|
37244
|
-
action: "published",
|
|
37245
|
-
summary,
|
|
37246
|
-
automation: published.automation,
|
|
37247
|
-
verification: {
|
|
37248
|
-
status: "unavailable",
|
|
37249
|
-
reason: getErrorMessage7(error62),
|
|
37250
|
-
command: `tda automation view ${automationId} ${scopeFlag(draftApi.scope)}`
|
|
37251
|
-
}
|
|
37252
|
-
};
|
|
37253
|
-
}
|
|
37254
|
-
const expected = normaliseManifest(manifest);
|
|
37255
|
-
const actual = normaliseManifest(automation.manifest);
|
|
37256
|
-
return {
|
|
37257
|
-
action: "published",
|
|
37258
|
-
summary,
|
|
37259
|
-
automation,
|
|
37260
|
-
verification: isDeepEqual(expected, actual) ? { status: "matched" } : { status: "mismatched", mismatch: diffManifests(expected, actual) }
|
|
37261
|
-
};
|
|
37262
|
-
}
|
|
37263
|
-
async function summarizeForPublish(draftApi, draftId) {
|
|
37264
|
-
const [detail, connections] = await Promise.all([
|
|
37265
|
-
draftApi.get(draftId),
|
|
37266
|
-
draftApi.getConnectionStatus(draftId)
|
|
37267
|
-
]);
|
|
37268
|
-
const { draft } = detail;
|
|
37269
|
-
const target = toTarget(draft);
|
|
37270
|
-
const published = target.kind === "automation" ? await draftApi.getAutomation(target.automationId) : null;
|
|
37271
|
-
const diff = published ? diffManifests(
|
|
37272
|
-
normaliseManifest(published.manifest),
|
|
37273
|
-
normaliseManifest(draft.partialManifest)
|
|
37274
|
-
) : null;
|
|
37275
|
-
const summary = {
|
|
37276
|
-
draftId,
|
|
37277
|
-
name: getResourceName(draft.partialManifest),
|
|
37278
|
-
scope: draft.workspaceId === null ? { kind: "personal" } : {
|
|
37279
|
-
kind: "workspace",
|
|
37280
|
-
workspaceId: draft.workspaceId,
|
|
37281
|
-
// A new workspace automation publishes team-visible; an
|
|
37282
|
-
// edit keeps whatever the automation already has.
|
|
37283
|
-
visibility: published?.visibility ?? "workspace"
|
|
37284
|
-
},
|
|
37285
|
-
target,
|
|
37286
|
-
enabled: published?.enabled ?? true,
|
|
37287
|
-
validation: { state: detail.state, issues: detail.issues },
|
|
37288
|
-
connections: {
|
|
37289
|
-
isValid: connections.isValid,
|
|
37290
|
-
connected: connections.connected.map(
|
|
37291
|
-
({ connectorId, connectionType, connectionId }) => ({
|
|
37292
|
-
connectorId,
|
|
37293
|
-
connectionType,
|
|
37294
|
-
connectionId
|
|
37295
|
-
})
|
|
37296
|
-
),
|
|
37297
|
-
missing: connections.missing
|
|
37298
|
-
},
|
|
37299
|
-
schedule: describeSchedule(draft.partialManifest),
|
|
37300
|
-
diff
|
|
37301
|
-
};
|
|
37302
|
-
return { summary, manifest: draft.partialManifest };
|
|
37303
|
-
}
|
|
37304
|
-
function describeSchedule(manifest) {
|
|
37305
|
-
if (!hasTriggerType(manifest)) return null;
|
|
37306
|
-
const schedule = getManifestTriggers(manifest).find((trigger) => trigger.type === "schedule");
|
|
37307
|
-
if (!schedule || schedule.type !== "schedule") return null;
|
|
37308
|
-
return getScheduleTriggerDescription({ value: schedule.value, timeFormat: "24h" });
|
|
37309
|
-
}
|
|
37310
|
-
function normaliseManifest(manifest) {
|
|
37311
|
-
const parsed = manifestSchema.safeParse(manifest);
|
|
37312
|
-
return parsed.success ? parsed.data : manifest;
|
|
37313
|
-
}
|
|
37314
37371
|
var DEFAULT_POLL_INTERVALS_MS = { first: 2e3, max: 1e4 };
|
|
37315
37372
|
var STATUS_REQUEST_GRACE_MS = 1e4;
|
|
37316
37373
|
var OPEN_RUN_STATUSES = /* @__PURE__ */ new Set([
|
|
@@ -37329,14 +37386,14 @@ async function startDraftTest(draftApi, {
|
|
|
37329
37386
|
} catch (error62) {
|
|
37330
37387
|
const refusal = getDraftTestRequestError(error62);
|
|
37331
37388
|
if (!refusal) throw error62;
|
|
37332
|
-
throw toDraftTestCliError(refusal, draftId, draftApi.
|
|
37389
|
+
throw toDraftTestCliError(refusal, draftId, draftApi.workspaceId);
|
|
37333
37390
|
}
|
|
37334
37391
|
const base = {
|
|
37335
37392
|
draftId,
|
|
37336
37393
|
testRunId: started.testRunId,
|
|
37337
37394
|
trigger: started.trigger,
|
|
37338
37395
|
connectorCalls: started.connectorCalls,
|
|
37339
|
-
command: `tda draft test-run ${draftId} ${started.testRunId} ${scopeFlag(draftApi.
|
|
37396
|
+
command: `tda draft test-run ${draftId} ${started.testRunId} ${scopeFlag(draftApi.workspaceId)}`
|
|
37340
37397
|
};
|
|
37341
37398
|
if (!waitFor) {
|
|
37342
37399
|
return { action: "test_started", ...base, status: started.status };
|
|
@@ -37429,7 +37486,7 @@ async function readTestPayloadFile(path) {
|
|
|
37429
37486
|
} catch (error62) {
|
|
37430
37487
|
throw new CliError4(
|
|
37431
37488
|
"PAYLOAD_UNREADABLE",
|
|
37432
|
-
`Could not read ${path}: ${
|
|
37489
|
+
`Could not read ${path}: ${getErrorMessage8(error62)}`
|
|
37433
37490
|
);
|
|
37434
37491
|
}
|
|
37435
37492
|
try {
|
|
@@ -37437,7 +37494,7 @@ async function readTestPayloadFile(path) {
|
|
|
37437
37494
|
} catch (error62) {
|
|
37438
37495
|
throw new CliError4(
|
|
37439
37496
|
"PAYLOAD_UNREADABLE",
|
|
37440
|
-
`${path} is not valid JSON: ${
|
|
37497
|
+
`${path} is not valid JSON: ${getErrorMessage8(error62)}`
|
|
37441
37498
|
);
|
|
37442
37499
|
}
|
|
37443
37500
|
}
|
|
@@ -37730,8 +37787,8 @@ function registerDraftCommand(program) {
|
|
|
37730
37787
|
command,
|
|
37731
37788
|
async ({ api, signal }) => {
|
|
37732
37789
|
const manifest = await readManifestInput(options);
|
|
37733
|
-
const draftApi =
|
|
37734
|
-
return
|
|
37790
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37791
|
+
return createDraft2(draftApi, { manifest, automationId: options.automation });
|
|
37735
37792
|
},
|
|
37736
37793
|
{ human: formatDraftChange },
|
|
37737
37794
|
{ spinner: "Creating draft..." }
|
|
@@ -37746,8 +37803,8 @@ function registerDraftCommand(program) {
|
|
|
37746
37803
|
command,
|
|
37747
37804
|
async ({ api, signal }) => {
|
|
37748
37805
|
const manifest = await readManifestInput(options);
|
|
37749
|
-
const draftApi =
|
|
37750
|
-
return
|
|
37806
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37807
|
+
return updateDraft2(draftApi, { draftId, manifest });
|
|
37751
37808
|
},
|
|
37752
37809
|
{ human: formatDraftChange },
|
|
37753
37810
|
{ spinner: "Updating draft..." }
|
|
@@ -37773,8 +37830,8 @@ function registerDraftCommand(program) {
|
|
|
37773
37830
|
);
|
|
37774
37831
|
}
|
|
37775
37832
|
const selections = options.connection.map(parseConnectionSelectionOption);
|
|
37776
|
-
const draftApi =
|
|
37777
|
-
return
|
|
37833
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37834
|
+
return connectDraft2(draftApi, {
|
|
37778
37835
|
draftId,
|
|
37779
37836
|
selections,
|
|
37780
37837
|
auto: options.auto === true
|
|
@@ -37790,8 +37847,8 @@ function registerDraftCommand(program) {
|
|
|
37790
37847
|
await runApiCommand(
|
|
37791
37848
|
command,
|
|
37792
37849
|
async ({ api, signal }) => {
|
|
37793
|
-
const draftApi =
|
|
37794
|
-
return
|
|
37850
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37851
|
+
return publishDraft2(draftApi, { draftId, confirmed: options.yes === true });
|
|
37795
37852
|
},
|
|
37796
37853
|
{ human: formatDraftPublish, json: summarizeDraftPublish },
|
|
37797
37854
|
{ spinner: options.yes === true ? "Publishing..." : "Loading draft..." }
|
|
@@ -37816,7 +37873,7 @@ function registerDraftCommand(program) {
|
|
|
37816
37873
|
throw new Error("--timeout only applies with --wait.");
|
|
37817
37874
|
}
|
|
37818
37875
|
const timeoutMs = parseTestTimeout(options.timeout ?? DEFAULT_TEST_WAIT);
|
|
37819
|
-
const draftApi =
|
|
37876
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37820
37877
|
return startDraftTest(draftApi, {
|
|
37821
37878
|
draftId,
|
|
37822
37879
|
request: {
|
|
@@ -37841,7 +37898,7 @@ function registerDraftCommand(program) {
|
|
|
37841
37898
|
await runApiCommand(
|
|
37842
37899
|
command,
|
|
37843
37900
|
async ({ api, signal }) => {
|
|
37844
|
-
const draftApi =
|
|
37901
|
+
const draftApi = bindDraftApi(api, await resolveWorkspaceScope(options), { signal });
|
|
37845
37902
|
return draftApi.getTestRun(draftId, runId, {
|
|
37846
37903
|
includeGeneratedCode: options.full === true,
|
|
37847
37904
|
includeToolCallPreviews: true
|