@doist/automations-cli 1.15.1 → 1.17.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 CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  collectSkillStatus,
8
8
  getInstaller,
9
9
  updateAllInstalledSkills
10
- } from "./chunk-N4YZJUMX.js";
10
+ } from "./chunk-DTY2LZDU.js";
11
11
 
12
12
  // ../../node_modules/ajv/dist/compile/codegen/code.js
13
13
  var require_code = __commonJS({
@@ -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.15.1",
6902
+ version: "1.17.0",
6903
6903
  description: "Command-line client for Todoist Automations",
6904
6904
  type: "module",
6905
6905
  bin: {
@@ -6953,7 +6953,7 @@ var package_default = {
6953
6953
  devDependencies: {
6954
6954
  "@doist/automations-core": "*",
6955
6955
  "@doist/automations-sdk": "*",
6956
- "@types/node": "24.13.5",
6956
+ "@types/node": "24.13.6",
6957
6957
  "conventional-changelog-conventionalcommits": "9.3.1",
6958
6958
  esbuild: "0.28.2",
6959
6959
  "semantic-release": "25.0.9",
@@ -26878,14 +26878,20 @@ var sendAdminTestEmailRequestSchema = external_exports.object({
26878
26878
  var sendAdminTestEmailResponseSchema = external_exports.object({
26879
26879
  messageId: external_exports.string()
26880
26880
  });
26881
- var MAX_ADMIT_USERS_PER_REQUEST = 5e3;
26881
+ var MAX_ADMIT_USERS_PER_REQUEST = 100;
26882
26882
  var MAX_TODOIST_USER_ID_LENGTH = 255;
26883
26883
  var admitUsersRequestSchema = external_exports.object({
26884
26884
  userIds: external_exports.array(external_exports.string().regex(/^\d+$/).max(MAX_TODOIST_USER_ID_LENGTH)).min(1).max(MAX_ADMIT_USERS_PER_REQUEST)
26885
26885
  });
26886
26886
  var admitUsersResponseSchema = external_exports.object({
26887
26887
  admitted: external_exports.number().int().nonnegative(),
26888
- alreadyAllowed: external_exports.number().int().nonnegative()
26888
+ alreadyAllowed: external_exports.number().int().nonnegative(),
26889
+ welcomeCredit: external_exports.object({
26890
+ granted: external_exports.number().int().nonnegative(),
26891
+ alreadyGranted: external_exports.number().int().nonnegative(),
26892
+ /** Users who got no credit, with the reason to show the admin. */
26893
+ notGranted: external_exports.array(external_exports.object({ userId: external_exports.string(), reason: external_exports.string() }))
26894
+ })
26889
26895
  });
26890
26896
 
26891
26897
  // ../../packages/core/dist/esm/types/failure-category.types.js
@@ -27656,6 +27662,9 @@ function hasTriggerType(value) {
27656
27662
  const triggers = getManifestTriggers(manifest);
27657
27663
  return triggers.length > 0 && typeof triggers[0]?.type === "string";
27658
27664
  }
27665
+ function isManifestRecord(value) {
27666
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
27667
+ }
27659
27668
  function isStringTypedSchema(schema) {
27660
27669
  if (!schema)
27661
27670
  return false;
@@ -29940,6 +29949,15 @@ var ReadUsageSummaryResponseSchema = external_exports.object({
29940
29949
  /** `charged_units` in integer microdollars. `0` on an account with no usage. */
29941
29950
  charged_amount: UsageBillingUnitsSchema
29942
29951
  });
29952
+ var GrantWelcomeCreditRequestSchema = external_exports.object({
29953
+ product: UsageBillingProductSchema,
29954
+ account: UsageBillingAccountSchema,
29955
+ operator: external_exports.email().max(254)
29956
+ });
29957
+ var GrantWelcomeCreditResponseSchema = external_exports.object({
29958
+ status: external_exports.enum(["granted", "already_granted"]),
29959
+ grant_id: external_exports.string().min(1)
29960
+ });
29943
29961
 
29944
29962
  // ../../packages/core/dist/esm/schemas/user-settings.schema.js
29945
29963
  var UserAccessStateSchema = external_exports.enum(["allowed", "waiting"]);
@@ -31037,6 +31055,14 @@ var WorkspaceAutomationDraftsClient = class extends BaseClient {
31037
31055
  });
31038
31056
  return automationDraftWithValidationSchema.parse(data);
31039
31057
  }
31058
+ /** Deletes the draft. Only its owner can; the API answers 404 otherwise. */
31059
+ async delete(workspaceId, draftId, options) {
31060
+ await this.request({
31061
+ method: "DELETE",
31062
+ path: workspaceAutomationDraftsEndpoints.detail(IdSchema.parse(workspaceId), IdSchema.parse(draftId)),
31063
+ options
31064
+ });
31065
+ }
31040
31066
  };
31041
31067
 
31042
31068
  // ../../packages/sdk/dist/esm/clients/workspace-chat/endpoints.js
@@ -31155,6 +31181,17 @@ var WorkspaceAutomationsClient = class extends BaseClient {
31155
31181
  options
31156
31182
  });
31157
31183
  }
31184
+ /**
31185
+ * Deletes the automation. Workspace admins may delete another member's
31186
+ * team-visible automation; a private one is only reachable by its creator.
31187
+ */
31188
+ async delete(workspaceId, id, options) {
31189
+ await this.request({
31190
+ method: "DELETE",
31191
+ path: workspaceAutomationsEndpoints.detail(IdSchema.parse(workspaceId), IdSchema.parse(id)),
31192
+ options
31193
+ });
31194
+ }
31158
31195
  };
31159
31196
 
31160
31197
  // ../../packages/sdk/dist/esm/clients/workspaces/endpoints.js
@@ -31933,6 +31970,93 @@ function summarizeRun(run) {
31933
31970
  };
31934
31971
  }
31935
31972
 
31973
+ // ../../packages/sdk/dist/esm/summaries/list-summaries.js
31974
+ function nonEmptyString(value) {
31975
+ return typeof value === "string" && value.trim() ? value : void 0;
31976
+ }
31977
+ function readManifestMetadata(dto) {
31978
+ if (!isManifestRecord(dto.manifest))
31979
+ return void 0;
31980
+ const name = nonEmptyString(dto.manifest.name);
31981
+ return {
31982
+ ...name ? { name } : {},
31983
+ ...typeof dto.manifest.description === "string" ? { description: dto.manifest.description } : {}
31984
+ };
31985
+ }
31986
+ function summarizeTrigger(trigger) {
31987
+ if (!isManifestRecord(trigger))
31988
+ return void 0;
31989
+ const type = trigger.type;
31990
+ if (type !== "schedule" && type !== "webhook" && type !== "api")
31991
+ return void 0;
31992
+ if (type === "webhook") {
31993
+ return { type, ...typeof trigger.event === "string" ? { event: trigger.event } : {} };
31994
+ }
31995
+ if (type === "api")
31996
+ return { type };
31997
+ const value = trigger.value;
31998
+ if (typeof value === "string")
31999
+ return { type, schedule: { interval: value } };
32000
+ const cron = isManifestRecord(value) ? value : void 0;
32001
+ return {
32002
+ type,
32003
+ schedule: {
32004
+ ...typeof cron?.expression === "string" ? { cron: cron.expression } : {},
32005
+ ...typeof cron?.timezone === "string" ? { timezone: cron.timezone } : {}
32006
+ }
32007
+ };
32008
+ }
32009
+ function summarizeAutomationListItem(dto) {
32010
+ const metadata = readManifestMetadata(dto);
32011
+ const triggers = isManifestRecord(dto.manifest) && Array.isArray(dto.manifest.triggers) ? dto.manifest.triggers : [];
32012
+ return {
32013
+ id: dto.id,
32014
+ name: metadata?.name ?? "(unnamed)",
32015
+ ...metadata?.description ? { description: metadata.description } : {},
32016
+ enabled: dto.enabled,
32017
+ status: dto.status.status,
32018
+ ...dto.status.lastRun ? { lastRun: dto.status.lastRun } : {},
32019
+ ...dto.status.status === "failed" && dto.status.failureReason ? { failureReason: dto.status.failureReason } : {},
32020
+ ...dto.status.status === "skipped" && dto.status.skipReason ? { skipReason: dto.status.skipReason } : {},
32021
+ connectionStatus: dto.connectionStatus,
32022
+ visibility: dto.visibility,
32023
+ isOwner: dto.isOwner,
32024
+ ...dto.workspaceId ? { workspaceId: dto.workspaceId } : {},
32025
+ ...dto.updatedBy ? { updatedBy: dto.updatedBy } : {},
32026
+ ...dto.disabledReason ? { disabledReason: dto.disabledReason } : {},
32027
+ triggers: triggers.flatMap((trigger) => summarizeTrigger(trigger) ?? []),
32028
+ connections: dto.connections.map((connection) => ({
32029
+ id: connection.id,
32030
+ name: connection.name,
32031
+ connectorId: connection.connectorId,
32032
+ ...connection.status ? { status: connection.status } : {}
32033
+ })),
32034
+ updatedAt: dto.updatedAt
32035
+ };
32036
+ }
32037
+ function summarizeAutomationListPage(page) {
32038
+ return { ...page, data: page.data.map(summarizeAutomationListItem) };
32039
+ }
32040
+ function summarizeDraftListItem(dto) {
32041
+ const manifest = isManifestRecord(dto.partialManifest) ? dto.partialManifest : {};
32042
+ const name = nonEmptyString(manifest.name);
32043
+ const description = nonEmptyString(manifest.description);
32044
+ return {
32045
+ id: dto.id,
32046
+ ...name ? { name } : {},
32047
+ ...description ? { description } : {},
32048
+ isComplete: dto.isComplete,
32049
+ ...dto.automationId ? { automationId: dto.automationId } : {},
32050
+ ...dto.conversationId ? { conversationId: dto.conversationId } : {},
32051
+ ...dto.workspaceId ? { workspaceId: dto.workspaceId } : {},
32052
+ createdAt: dto.createdAt,
32053
+ updatedAt: dto.updatedAt
32054
+ };
32055
+ }
32056
+ function summarizeDraftListPage(page) {
32057
+ return { ...page, data: page.data.map(summarizeDraftListItem) };
32058
+ }
32059
+
31936
32060
  // ../../packages/sdk/dist/esm/connectors/connector-catalog.js
31937
32061
  var ConnectorNotFoundError = class extends Error {
31938
32062
  connectorId;
@@ -33434,14 +33558,15 @@ function sanitizeTerminalText(value) {
33434
33558
  );
33435
33559
  }
33436
33560
  function writeResult(mode, result, presentation, stream = process.stdout) {
33437
- const jsonResult = presentation.json?.(result) ?? result;
33438
33561
  if (mode === "json") {
33439
- stream.write(`${formatJson3(jsonResult)}
33562
+ stream.write(`${formatJson3(presentation.json?.(result) ?? result)}
33440
33563
  `);
33441
33564
  return;
33442
33565
  }
33443
33566
  if (mode === "ndjson") {
33444
- const output3 = formatNdjson3(presentation.ndjson?.(result) ?? [jsonResult]);
33567
+ const output3 = formatNdjson3(
33568
+ presentation.ndjson?.(result) ?? [presentation.json?.(result) ?? result]
33569
+ );
33445
33570
  if (output3) stream.write(`${output3}
33446
33571
  `);
33447
33572
  return;
@@ -33748,6 +33873,15 @@ function summarizeAutomationChange(result) {
33748
33873
  function formatAutomationTrigger(result) {
33749
33874
  return `Triggered automation ${result.automationId}.`;
33750
33875
  }
33876
+ function formatAutomationDelete(result) {
33877
+ if (result.action === "delete_preview") {
33878
+ return [
33879
+ `Automation ${result.automationId} ("${result.name}") was not deleted.`,
33880
+ "Use --yes to confirm."
33881
+ ].join("\n");
33882
+ }
33883
+ return `Deleted automation ${result.automationId}.`;
33884
+ }
33751
33885
  function capitalize(value) {
33752
33886
  return `${value.charAt(0).toUpperCase()}${value.slice(1)}`;
33753
33887
  }
@@ -33756,7 +33890,9 @@ function capitalize(value) {
33756
33890
  function registerAutomationCommand(program) {
33757
33891
  const automation = program.command("automation").description("Inspect and manage published automations");
33758
33892
  addWorkspaceScopeOptions(
33759
- addCursorPaginationOptions(automation.command("list").description("List automations"))
33893
+ addCursorPaginationOptions(
33894
+ automation.command("list").description("List automations").option("--full", "Include manifests and connection details in machine output")
33895
+ )
33760
33896
  ).action(async (options, command) => {
33761
33897
  await runApiCommand(
33762
33898
  command,
@@ -33767,7 +33903,10 @@ function registerAutomationCommand(program) {
33767
33903
  (args) => workspaceId === null ? api.automations.list(args, { signal }) : api.workspaceAutomations.list(workspaceId, args, { signal })
33768
33904
  );
33769
33905
  },
33770
- { human: formatAutomationList, json: summarizeAutomationPage },
33906
+ {
33907
+ human: formatAutomationList,
33908
+ json: options.full ? summarizeAutomationPage : summarizeAutomationListPage
33909
+ },
33771
33910
  {
33772
33911
  spinner: "Loading automations...",
33773
33912
  streamNdjson: async function* ({ api, signal }) {
@@ -33822,6 +33961,34 @@ function registerAutomationCommand(program) {
33822
33961
  { spinner: "Triggering automation..." }
33823
33962
  );
33824
33963
  });
33964
+ addWorkspaceScopeOptions(
33965
+ automation.command("delete").description("Delete an automation after previewing which one it is").argument("<automation-id>", "Automation ID").option("--yes", "Confirm deletion")
33966
+ ).action(async (automationId, options, command) => {
33967
+ await runApiCommand(
33968
+ command,
33969
+ async ({ api, signal }) => {
33970
+ const workspaceId = await resolveWorkspaceScope(options);
33971
+ if (options.yes !== true) {
33972
+ const automation2 = workspaceId === null ? await api.automations.get(automationId, { signal }) : await api.workspaceAutomations.get(workspaceId, automationId, {
33973
+ signal
33974
+ });
33975
+ return {
33976
+ action: "delete_preview",
33977
+ automationId,
33978
+ name: getResourceName(automation2.manifest)
33979
+ };
33980
+ }
33981
+ if (workspaceId === null) {
33982
+ await api.automations.delete(automationId, { signal });
33983
+ } else {
33984
+ await api.workspaceAutomations.delete(workspaceId, automationId, { signal });
33985
+ }
33986
+ return { action: "deleted", automationId };
33987
+ },
33988
+ { human: formatAutomationDelete },
33989
+ { spinner: "Deleting automation..." }
33990
+ );
33991
+ });
33825
33992
  addWorkspaceScopeOptions(
33826
33993
  automation.command("update").description("Replace an automation name and description").argument("<automation-id>", "Automation ID").option("--name <name>", "New automation name (required)").option("--description <description>", "New automation description (required)")
33827
33994
  ).action(
@@ -33965,10 +34132,17 @@ function registerEnabledStateCommand(parent, name, enabled) {
33965
34132
  );
33966
34133
  });
33967
34134
  }
33968
- async function* streamAutomationList(options, fetchPage) {
33969
- for await (const item of streamCursorNdjsonItems(options, fetchPage)) {
33970
- yield "id" in item ? summarizeAutomation(item) : item;
34135
+ function streamAutomationList(options, fetchPage) {
34136
+ if (options.full) {
34137
+ return streamCursorNdjsonItems(
34138
+ options,
34139
+ async (args) => summarizeAutomationPage(await fetchPage(args))
34140
+ );
33971
34141
  }
34142
+ return streamCursorNdjsonItems(
34143
+ options,
34144
+ async (args) => summarizeAutomationListPage(await fetchPage(args))
34145
+ );
33972
34146
  }
33973
34147
  function resolveScheduleValue(options) {
33974
34148
  return resolveScheduleInput(options, {
@@ -35882,11 +36056,28 @@ function registerConnectorCommand(program) {
35882
36056
  registerConnectorMutationCommands(connector);
35883
36057
  }
35884
36058
 
36059
+ // src/commands/draft/format.ts
36060
+ function formatDraftDelete(result) {
36061
+ if (result.action === "delete_preview") {
36062
+ return [
36063
+ `Draft ${result.draftId} ("${result.name}") was not deleted.`,
36064
+ "Deleting the last draft in a conversation archives that conversation.",
36065
+ "Use --yes to confirm."
36066
+ ].join("\n");
36067
+ }
36068
+ return `Deleted draft ${result.draftId}.`;
36069
+ }
36070
+
35885
36071
  // src/commands/draft/index.ts
35886
36072
  function registerDraftCommand(program) {
35887
- const draft = program.command("draft").description("Inspect automation drafts");
36073
+ const draft = program.command("draft").description("Inspect and delete automation drafts");
35888
36074
  addWorkspaceScopeOptions(
35889
- addCursorPaginationOptions(draft.command("list").description("List drafts"))
36075
+ addCursorPaginationOptions(
36076
+ draft.command("list").description("List drafts").option(
36077
+ "--full",
36078
+ "Include partial manifests and connector details in machine output"
36079
+ )
36080
+ )
35890
36081
  ).action(async (options, command) => {
35891
36082
  await runApiCommand(
35892
36083
  command,
@@ -35897,12 +36088,12 @@ function registerDraftCommand(program) {
35897
36088
  (args) => workspaceId === null ? api.automationDrafts.list(args, { signal }) : api.workspaceAutomationDrafts.list(workspaceId, args, { signal })
35898
36089
  );
35899
36090
  },
35900
- { human: formatDraftList },
36091
+ { human: formatDraftList, json: options.full ? void 0 : summarizeDraftListPage },
35901
36092
  {
35902
36093
  spinner: "Loading drafts...",
35903
36094
  streamNdjson: async function* ({ api, signal }) {
35904
36095
  const workspaceId = await resolveWorkspaceScope(options);
35905
- yield* streamCursorNdjsonItems(
36096
+ yield* streamDraftList(
35906
36097
  options,
35907
36098
  (args) => workspaceId === null ? api.automationDrafts.list(args, { signal }) : api.workspaceAutomationDrafts.list(workspaceId, args, { signal })
35908
36099
  );
@@ -35923,6 +36114,41 @@ function registerDraftCommand(program) {
35923
36114
  { spinner: "Loading draft..." }
35924
36115
  );
35925
36116
  });
36117
+ addWorkspaceScopeOptions(
36118
+ draft.command("delete").description("Delete a draft after previewing which one it is").argument("<draft-id>", "Draft ID").option("--yes", "Confirm deletion")
36119
+ ).action(async (draftId, options, command) => {
36120
+ await runApiCommand(
36121
+ command,
36122
+ async ({ api, signal }) => {
36123
+ const workspaceId = await resolveWorkspaceScope(options);
36124
+ if (options.yes !== true) {
36125
+ const { draft: draft2 } = workspaceId === null ? await api.automationDrafts.get(draftId, { signal }) : await api.workspaceAutomationDrafts.get(workspaceId, draftId, {
36126
+ signal
36127
+ });
36128
+ return {
36129
+ action: "delete_preview",
36130
+ draftId,
36131
+ name: getResourceName(draft2.partialManifest)
36132
+ };
36133
+ }
36134
+ if (workspaceId === null) {
36135
+ await api.automationDrafts.delete(draftId, { signal });
36136
+ } else {
36137
+ await api.workspaceAutomationDrafts.delete(workspaceId, draftId, { signal });
36138
+ }
36139
+ return { action: "deleted", draftId };
36140
+ },
36141
+ { human: formatDraftDelete },
36142
+ { spinner: "Deleting draft..." }
36143
+ );
36144
+ });
36145
+ }
36146
+ function streamDraftList(options, fetchPage) {
36147
+ if (options.full) return streamCursorNdjsonItems(options, fetchPage);
36148
+ return streamCursorNdjsonItems(
36149
+ options,
36150
+ async (args) => summarizeDraftListPage(await fetchPage(args))
36151
+ );
35926
36152
  }
35927
36153
 
35928
36154
  // src/commands/run/index.ts