@claypi/cli 0.1.6 → 0.1.7

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
@@ -56789,6 +56789,7 @@ var AuthScopeSchema = external_exports.enum([
56789
56789
  "endpoints:blocklist-write",
56790
56790
  "endpoints:inngest",
56791
56791
  "endpoints:sync-app-account-types",
56792
+ "endpoints:sync-app-account-types-dry-run",
56792
56793
  // Read-only scope for infra scripts running on engineer laptops to pull
56793
56794
  // setup data (billing plans, action tiers) from staging.
56794
56795
  "endpoints:local-dev-setup-read",
@@ -83006,6 +83007,17 @@ var parseLimitFlag = parsePositiveIntegerFlag("--limit");
83006
83007
  function parseLimitFlagWithMax(max) {
83007
83008
  return parsePositiveIntegerFlag("--limit", max);
83008
83009
  }
83010
+ function parseDatetimeFlag(flagName) {
83011
+ return (value) => {
83012
+ const ms = Date.parse(value);
83013
+ if (Number.isNaN(ms)) {
83014
+ throw new InvalidArgumentError(
83015
+ `${flagName} must be a valid date or ISO 8601 datetime (e.g. 2026-06-01T00:00:00Z)`
83016
+ );
83017
+ }
83018
+ return new Date(ms).toISOString();
83019
+ };
83020
+ }
83009
83021
  function parseBooleanFlag(flagName) {
83010
83022
  return (value) => {
83011
83023
  if (value === "true") return true;
@@ -83395,7 +83407,7 @@ async function readApiKeyInteractive() {
83395
83407
  return trimmed;
83396
83408
  }
83397
83409
  function registerLogin(program3) {
83398
- program3.command("login").description(
83410
+ program3.command("login").summary("Save an API key to the config file.").description(
83399
83411
  "Save an API key to the config file. The key is required for all authenticated commands. Use --stdin in non-interactive contexts (CI, agents); otherwise the command prompts for the key on a TTY."
83400
83412
  ).option(
83401
83413
  "--stdin",
@@ -83450,7 +83462,7 @@ Examples:
83450
83462
 
83451
83463
  // src/commands/logout.ts
83452
83464
  function registerLogout(program3) {
83453
- program3.command("logout").description(
83465
+ program3.command("logout").summary("Remove the saved API key.").description(
83454
83466
  "Remove the saved API key from the config file. Idempotent \u2014 succeeds even if no key is currently saved. Subsequent authenticated commands will fail with auth_missing_api_key (exit 3) until you run `clay login` again \u2014 unless CLAY_API_KEY is set in the environment, which logout cannot remove and which keeps the CLI authenticated."
83455
83467
  ).addHelpText(
83456
83468
  "after",
@@ -83475,867 +83487,277 @@ Examples:
83475
83487
  });
83476
83488
  }
83477
83489
 
83478
- // ../../libs/api-contract/src/tables/summary/contract.ts
83479
- var TableSummary = external_exports.object({
83490
+ // ../../libs/shared/src/tables/base-types.ts
83491
+ var import_lodash6 = __toESM(require_lodash());
83492
+
83493
+ // ../../libs/shared/src/FormulaTypes.ts
83494
+ var FormulaMap = external_exports.record(external_exports.string(), external_exports.string().optional());
83495
+ var NestedFormulaMap = external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), FormulaMap]).optional());
83496
+
83497
+ // ../../libs/shared/src/actions/base-types.ts
83498
+ var ActionKeySchema = external_exports.string();
83499
+ var ActionPackageIdSchema = external_exports.string();
83500
+ var ActionPackage = external_exports.object({
83480
83501
  id: external_exports.string(),
83502
+ key: external_exports.string(),
83503
+ description: external_exports.string().optional(),
83504
+ displayName: external_exports.string(),
83505
+ icon: external_exports.string(),
83506
+ darkIcon: external_exports.string().optional(),
83507
+ categories: external_exports.array(external_exports.string()).optional(),
83508
+ termsAndConditions: external_exports.array(external_exports.string()).optional(),
83509
+ vpcLambdaOnly: external_exports.boolean().optional()
83510
+ });
83511
+ var InputsBinding = external_exports.object({
83481
83512
  name: external_exports.string(),
83482
- description: external_exports.string().nullable(),
83483
- workbook: external_exports.object({
83484
- id: external_exports.string(),
83485
- name: external_exports.string()
83486
- }).nullable(),
83487
- apiEnabled: external_exports.boolean()
83513
+ formulaText: external_exports.string().nullish(),
83514
+ formulaMap: FormulaMap.nullish(),
83515
+ optional: external_exports.boolean().optional()
83488
83516
  });
83489
- var tablesSummaryContract = {
83490
- listTablesSummary: {
83491
- method: "GET",
83492
- path: "/workspaces/:workspaceId/tables/summary",
83493
- pathParams: external_exports.object({ workspaceId: workspaceIdPathParam }),
83494
- query: external_exports.object({
83495
- cursor: external_exports.string().min(1).optional(),
83496
- limit: external_exports.coerce.number().int().min(1).max(100).optional().default(50),
83497
- // z.coerce.boolean() treats any non-empty string as true (including "false"),
83498
- // so accept the string literals explicitly and transform.
83499
- apiEnabled: external_exports.enum(["true", "false"]).optional().transform((v) => v === void 0 ? void 0 : v === "true")
83500
- }),
83501
- responses: {
83502
- 200: external_exports.object({
83503
- data: external_exports.array(TableSummary),
83504
- cursor: external_exports.string().optional()
83505
- })
83506
- },
83507
- summary: "List tables in the workspace with a slim CLI-friendly projection.",
83508
- metadata: { team: "integrations-team" /* IntegrationsTeam */ }
83509
- }
83510
- };
83511
-
83512
- // src/commands/tables/list.ts
83513
- function buildListCommand2() {
83514
- const cmd = new Command("list");
83515
- cmd.description(
83516
- "List tables in the workspace pinned to your API key. Each row carries an `apiEnabled` flag for whether the table is enabled for public-API sync."
83517
- ).option(
83518
- "--limit <n>",
83519
- `Max tables to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
83520
- parseLimitFlagWithMax(MAX_PAGE_LIMIT)
83521
- ).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").option("--api-enabled", "Only return tables enabled for the public API.").addHelpText(
83522
- "after",
83523
- `
83524
- Output (success, exit 0):
83525
- {
83526
- "data": [
83527
- {
83528
- "id": <string>,
83529
- "name": <string>,
83530
- "description": <string|null>,
83531
- "workbook": { "id": <string>, "name": <string> } | null,
83532
- "apiEnabled": <boolean>
83533
- }
83534
- ],
83535
- "cursor": <string|undefined>
83536
- }
83537
-
83538
- Pagination:
83539
- --limit <n> max tables per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
83540
- --cursor <token> resume from a previous response's \`cursor\`
83541
- When more results exist, the response includes a top-level \`cursor\`; pass it back via
83542
- --cursor to fetch the next page.
83543
-
83544
- Common errors:
83545
- validation_error (exit 2) --limit is not a positive integer or exceeds ${MAX_PAGE_LIMIT}.
83546
- auth_forbidden (exit 3) Key lacks the cli:all scope, or the workspace is not in the public-API beta.
83547
-
83548
- Examples:
83549
- $ clay tables list
83550
- $ clay tables list --api-enabled | jq -r '.data[].id'
83551
- $ clay tables list --limit 50 --cursor "$CURSOR"
83552
- $ clay tables list --api-enabled | jq -r '.data[] | select(.apiEnabled) | .name'
83553
- `
83554
- ).action(async (opts) => {
83555
- const workspaceId = await currentWorkspaceId();
83556
- const client = await v3Client(tablesSummaryContract);
83557
- const page = await unwrap(
83558
- client.listTablesSummary({
83559
- params: { workspaceId },
83560
- query: {
83561
- cursor: opts.cursor,
83562
- limit: opts.limit ?? DEFAULT_PAGE_LIMIT,
83563
- apiEnabled: opts.apiEnabled === true ? "true" : void 0
83564
- }
83565
- })
83566
- );
83567
- writeJson({
83568
- data: page.data.map((t) => ({
83569
- id: t.id,
83570
- name: t.name,
83571
- description: t.description,
83572
- workbook: t.workbook,
83573
- apiEnabled: t.apiEnabled
83574
- })),
83575
- cursor: page.cursor
83576
- });
83577
- });
83578
- return cmd;
83579
- }
83580
-
83581
- // ../../libs/api-contract/src/public-api-v0/structured-query-schema.ts
83582
- var FilterOp = external_exports.enum([
83583
- "=",
83584
- "!=",
83585
- ">",
83586
- ">=",
83587
- "<",
83588
- "<=",
83589
- "contains",
83590
- "not_contains",
83591
- "starts_with",
83592
- "ends_with",
83593
- "in",
83594
- "not_in",
83595
- "is_empty",
83596
- "is_not_empty"
83597
- ]);
83598
- var NestedPath = external_exports.array(external_exports.string().min(1)).min(1).max(5);
83599
- var OPS_WITHOUT_VALUE = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
83600
- var FilterPredicate = external_exports.object({
83601
- field: external_exports.string().min(1),
83602
- path: NestedPath.optional(),
83603
- op: FilterOp,
83604
- // `null` is intentionally excluded — `is_empty` / `is_not_empty` are the canonical
83605
- // way to test for absent/empty cells. Allowing `value: null` would invite the SQL
83606
- // three-valued-logic surprise (where `field = NULL` is always false) and force a
83607
- // choice about whether `=` means "match the JSON null literal" or "match any
83608
- // missing/null/empty cell". Punting that decision keeps the operator semantics clean.
83609
- value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.array(external_exports.union([external_exports.string(), external_exports.number()]))]).optional()
83610
- }).superRefine((data, ctx) => {
83611
- if (!OPS_WITHOUT_VALUE.has(data.op) && data.value === void 0) {
83612
- ctx.addIssue({
83613
- code: external_exports.ZodIssueCode.custom,
83614
- message: `Operator "${data.op}" requires a value`,
83615
- path: ["value"]
83616
- });
83617
- }
83517
+ var OnOpenPanelAction = external_exports.enum(["openMetaPrompter"]);
83518
+ var SidebarParamsSchema = external_exports.object({
83519
+ onOpenPanelAction: OnOpenPanelAction.optional()
83618
83520
  });
83619
- var FilterAnd = external_exports.lazy(
83620
- () => external_exports.object({ and: external_exports.array(FilterExpression).min(1).max(10) })
83621
- );
83622
- var FilterOr = external_exports.lazy(() => external_exports.object({ or: external_exports.array(FilterExpression).min(1).max(10) }));
83623
- var FilterNot = external_exports.lazy(() => external_exports.object({ not: FilterExpression }));
83624
- var FilterExpression = external_exports.lazy(
83625
- () => external_exports.union([FilterPredicate, FilterAnd, FilterOr, FilterNot])
83626
- );
83627
- var FieldSelect = external_exports.object({
83628
- field: external_exports.string().min(1),
83629
- path: NestedPath.optional(),
83630
- table: external_exports.string().optional(),
83631
- as: external_exports.string().optional()
83521
+ var ActionDisplayProps = external_exports.object({
83522
+ iconUri: external_exports.string().optional(),
83523
+ darkIconUri: external_exports.string().optional(),
83524
+ packageIcon: external_exports.string(),
83525
+ packageDarkIcon: external_exports.string().optional(),
83526
+ displayName: external_exports.string()
83632
83527
  });
83633
- var AggregateSelect = external_exports.object({
83634
- fn: external_exports.enum(["count", "sum", "avg", "max", "min"]),
83635
- field: external_exports.string().min(1),
83636
- path: NestedPath.optional(),
83637
- as: external_exports.string().min(1)
83528
+ var ActionLogInfo = external_exports.object({
83529
+ requestId: external_exports.string().nullable(),
83530
+ groupName: external_exports.string().nullable(),
83531
+ streamName: external_exports.string().nullable(),
83532
+ url: external_exports.string().nullable(),
83533
+ mezmoUrl: external_exports.string().nullable()
83638
83534
  });
83639
- var SelectItem = external_exports.union([AggregateSelect, FieldSelect]);
83640
- var TableRef = external_exports.object({
83641
- id: external_exports.string().min(1),
83642
- alias: external_exports.string().optional()
83535
+ var ActionTaskRunType = /* @__PURE__ */ ((ActionTaskRunType2) => {
83536
+ ActionTaskRunType2["Action"] = "action";
83537
+ ActionTaskRunType2["ActionPreview"] = "action-preview";
83538
+ ActionTaskRunType2["Source"] = "source";
83539
+ ActionTaskRunType2["SourcePreview"] = "source-preview";
83540
+ return ActionTaskRunType2;
83541
+ })(ActionTaskRunType || {});
83542
+ var ActionTaskRunTypeSchema = external_exports.nativeEnum(ActionTaskRunType);
83543
+
83544
+ // ../../libs/shared/src/attributes/attribute-enum.ts
83545
+ var AttributeEnum = /* @__PURE__ */ ((AttributeEnum2) => {
83546
+ AttributeEnum2["Person_FullName"] = "person/fullName";
83547
+ AttributeEnum2["Person_FirstName"] = "person/firstName";
83548
+ AttributeEnum2["Person_LastName"] = "person/lastName";
83549
+ AttributeEnum2["Person_MiddleName"] = "person/middleName";
83550
+ AttributeEnum2["Person_Location_Summary"] = "person/location/summary";
83551
+ AttributeEnum2["Person_Company"] = "person/company";
83552
+ AttributeEnum2["Person_JobTitle"] = "person/jobTitle";
83553
+ AttributeEnum2["Person_JobStartDate"] = "person/jobStartDate";
83554
+ AttributeEnum2["Person_PictureUrl"] = "person/pictureUrl";
83555
+ AttributeEnum2["Person_Bio"] = "person/bio";
83556
+ AttributeEnum2["Person_PersonalEmail"] = "person/personalEmail";
83557
+ AttributeEnum2["Person_WorkEmail"] = "person/workEmail";
83558
+ AttributeEnum2["Person_WorkEmailEnterprise"] = "person/workEmailEnterprise";
83559
+ AttributeEnum2["Person_InfluencerEmail"] = "person/influencerEmail";
83560
+ AttributeEnum2["Person_AdvertisingEmail"] = "person/advertisingEmail";
83561
+ AttributeEnum2["Person_Phone"] = "person/phone";
83562
+ AttributeEnum2["Person_PhoneEMEA"] = "person/phoneEMEA";
83563
+ AttributeEnum2["Person_PhoneAPAC"] = "person/phoneAPAC";
83564
+ AttributeEnum2["Person_PhoneGlobal"] = "person/phoneGlobal";
83565
+ AttributeEnum2["Person_Gender"] = "person/gender";
83566
+ AttributeEnum2["Person_LinkedIn_Url"] = "person/linkedIn/url";
83567
+ AttributeEnum2["Person_Facebook"] = "person/facebook";
83568
+ AttributeEnum2["Person_Instagram"] = "person/instagram";
83569
+ AttributeEnum2["Person_Twitter"] = "person/twitter";
83570
+ AttributeEnum2["Person_Github"] = "person/github";
83571
+ AttributeEnum2["Person_EducationLevel"] = "person/educationLevel";
83572
+ AttributeEnum2["Person_SchoolName"] = "person/schoolName";
83573
+ AttributeEnum2["Person_Industry"] = "person/industry";
83574
+ AttributeEnum2["Company_EmployeeCount"] = "company/employeeCount";
83575
+ AttributeEnum2["Company_Domain"] = "company/domain";
83576
+ AttributeEnum2["Company_Description"] = "company/description";
83577
+ AttributeEnum2["Company_Revenue"] = "company/revenue";
83578
+ AttributeEnum2["Company_Industry"] = "company/industry";
83579
+ AttributeEnum2["Company_FoundedDate"] = "company/foundedDate";
83580
+ AttributeEnum2["Company_Country"] = "company/country";
83581
+ AttributeEnum2["Company_Address"] = "company/address";
83582
+ AttributeEnum2["Company_FundingPrediction"] = "company/fundingPrediction";
83583
+ AttributeEnum2["Company_GrowthInsight"] = "company/growthInsight";
83584
+ AttributeEnum2["Company_Valuation"] = "company/valuation";
83585
+ AttributeEnum2["Company_FundingRound"] = "company/fundingRound";
83586
+ AttributeEnum2["Company_TotalFunding"] = "company/totalFunding";
83587
+ AttributeEnum2["Company_SiteTraffic"] = "company/siteTraffic";
83588
+ AttributeEnum2["Company_TechStack"] = "company/techStack";
83589
+ AttributeEnum2["Company_FullTechStack"] = "company/fullTechStack";
83590
+ AttributeEnum2["Company_CorporateStructure"] = "company/corporateStructure";
83591
+ AttributeEnum2["Company_JobOpenings"] = "company/jobOpenings";
83592
+ AttributeEnum2["Company_Logo"] = "company/logo";
83593
+ AttributeEnum2["Company_LinkedIn_Url"] = "company/linkedIn/url";
83594
+ AttributeEnum2["Company_Facebook"] = "company/facebook";
83595
+ AttributeEnum2["Company_Instagram"] = "company/instagram";
83596
+ AttributeEnum2["Company_Twitter"] = "company/twitter";
83597
+ AttributeEnum2["Company_Github"] = "company/github";
83598
+ AttributeEnum2["Company_Crunchbase"] = "company/crunchbase";
83599
+ AttributeEnum2["Company_OwnershipStatus"] = "company/ownershipStatus";
83600
+ AttributeEnum2["Company_Investors"] = "company/investors";
83601
+ AttributeEnum2["Company_Acquisitions"] = "company/acquisitions";
83602
+ AttributeEnum2["Company_Features"] = "company/features";
83603
+ AttributeEnum2["Company_Competitors"] = "company/competitors";
83604
+ AttributeEnum2["Company_PricingDetails"] = "company/pricingDetails";
83605
+ AttributeEnum2["Company_News"] = "company/news";
83606
+ AttributeEnum2["Company_LatestFundingDate"] = "company/latestFundingDate";
83607
+ AttributeEnum2["Company_LatestFunding"] = "company/latestFunding";
83608
+ AttributeEnum2["Company_NumberOfFundingRounds"] = "company/numberOfFundingRounds";
83609
+ AttributeEnum2["Company_EmployeeCountByCriteria"] = "company/employeeCountByCriteria";
83610
+ AttributeEnum2["Company_NumberOfFundsRaised"] = "company/numberOfFundsRaised";
83611
+ AttributeEnum2["Company_FundTotalAmountRaised"] = "company/fundTotalAmountRaised";
83612
+ AttributeEnum2["Company_FundInvestments"] = "company/fundInvestments";
83613
+ AttributeEnum2["Company_Phone"] = "company/phone";
83614
+ return AttributeEnum2;
83615
+ })(AttributeEnum || {});
83616
+ var AttributeEnumSchema = external_exports.nativeEnum(AttributeEnum);
83617
+
83618
+ // ../../libs/shared/src/campaigns/content-types.ts
83619
+ var AiSnippetAttrsSchema = external_exports.object({
83620
+ snippetId: external_exports.string().min(1),
83621
+ label: external_exports.string(),
83622
+ brief: external_exports.unknown().optional()
83643
83623
  });
83644
- var JoinSpec = external_exports.object({
83645
- table: external_exports.string().min(1),
83646
- on: external_exports.object({
83647
- left: external_exports.string().min(1),
83648
- right: external_exports.string().min(1)
83649
- }),
83650
- type: external_exports.enum(["inner", "left"]).default("inner")
83624
+ var MIN_SPINTAX_VARIANTS = 2;
83625
+ var MAX_SPINTAX_VARIANTS = 5;
83626
+ var SpintaxAttrsSchema = external_exports.object({
83627
+ variants: external_exports.array(external_exports.string().min(1)).min(MIN_SPINTAX_VARIANTS).max(MAX_SPINTAX_VARIANTS).refine((v) => new Set(v).size === v.length, { message: "Variants must be unique" })
83651
83628
  });
83652
- var OrderByItem = external_exports.object({
83653
- field: external_exports.string().min(1),
83654
- direction: external_exports.enum(["asc", "desc"]).default("asc")
83629
+ var SenderFieldAttrsSchema = external_exports.object({
83630
+ option: external_exports.enum(["senderFullName", "senderFirstName"])
83655
83631
  });
83656
- var FieldMode = external_exports.enum(["names", "ids"]);
83657
- var FILTER_MAX_DEPTH = 10;
83658
- function filterDepth(filter) {
83659
- const stack = [{ node: filter, depth: 0 }];
83660
- let max = 0;
83661
- while (stack.length > 0) {
83662
- const item = stack.pop();
83663
- if (item === void 0) break;
83664
- const { node: node2, depth } = item;
83665
- if (depth > max) max = depth;
83666
- if (!node2 || typeof node2 !== "object") continue;
83667
- const obj = node2;
83668
- if (Array.isArray(obj.and)) {
83669
- for (const c3 of obj.and) stack.push({ node: c3, depth: depth + 1 });
83670
- } else if (Array.isArray(obj.or)) {
83671
- for (const c3 of obj.or) stack.push({ node: c3, depth: depth + 1 });
83672
- } else if ("not" in obj) {
83673
- stack.push({ node: obj.not, depth: depth + 1 });
83674
- }
83675
- }
83676
- return max;
83677
- }
83678
- var StructuredQuery = external_exports.object({
83679
- tables: external_exports.array(TableRef).min(1).max(5),
83680
- select: external_exports.array(SelectItem).max(20).optional(),
83681
- filter: FilterExpression.optional(),
83682
- join: external_exports.array(JoinSpec).max(4).optional(),
83683
- group_by: external_exports.array(external_exports.string().min(1)).max(5).optional(),
83684
- order_by: external_exports.array(OrderByItem).max(3).optional(),
83685
- /** Controls whether response data keys use field IDs (default) or field names */
83686
- field_mode: FieldMode.optional()
83632
+ var LeadFieldFormatSchema = external_exports.enum(["none", "titleCase", "lowerCase", "upperCase", "sentenceCase"]);
83633
+ var LeadFieldAttrsSchema = external_exports.object({
83634
+ fieldId: external_exports.string().min(1),
83635
+ label: external_exports.string().min(1),
83636
+ required: external_exports.boolean(),
83637
+ format: LeadFieldFormatSchema,
83638
+ stripEmojis: external_exports.boolean(),
83639
+ fallback: external_exports.string().nullable()
83640
+ }).refine((a) => !a.required || a.fallback === null, {
83641
+ message: "Required variables should not have a fallback",
83642
+ path: ["fallback"]
83643
+ }).refine((a) => a.required || typeof a.fallback === "string" && a.fallback.length > 0, {
83644
+ message: "Non-required variables must have a fallback",
83645
+ path: ["fallback"]
83687
83646
  });
83688
- var paginationFields = {
83689
- limit: external_exports.number().int().min(1).max(100).default(50),
83690
- cursor: external_exports.string().optional()
83647
+ var FONT_FAMILY_OPTIONS = {
83648
+ SansSerif: "sans-serif",
83649
+ Serif: "times new roman, serif",
83650
+ FixedWidth: "monospace",
83651
+ Wide: "arial black, sans-serif",
83652
+ Narrow: "arial narrow, sans-serif",
83653
+ ComicSans: "Comic Sans MS, sans-serif",
83654
+ Garamond: "Garamond",
83655
+ Georgia: "Georgia",
83656
+ Tahoma: "Tahoma",
83657
+ TrebuchetMS: "Trebuchet MS",
83658
+ Verdana: "Verdana"
83691
83659
  };
83692
- var StructuredQueryRequestShape = external_exports.object({
83693
- query: StructuredQuery,
83694
- ...paginationFields
83660
+ var FONT_FAMILY_VALUES = Object.values(FONT_FAMILY_OPTIONS);
83661
+ var LinkAttrsSchema = external_exports.object({
83662
+ href: external_exports.lazy(() => CampaignDocumentSchema),
83663
+ label: external_exports.lazy(() => CampaignDocumentSchema)
83695
83664
  });
83696
- var StructuredQueryRequest = external_exports.preprocess((raw, ctx) => {
83697
- if (raw && typeof raw === "object" && !Array.isArray(raw)) {
83698
- const query = raw.query;
83699
- const filter = query && typeof query === "object" && !Array.isArray(query) ? query.filter : void 0;
83700
- if (filter !== void 0 && filterDepth(filter) > FILTER_MAX_DEPTH) {
83701
- ctx.addIssue({
83702
- code: external_exports.ZodIssueCode.custom,
83703
- message: `Filter nesting too deep (max ${FILTER_MAX_DEPTH})`,
83704
- path: ["query", "filter"]
83705
- });
83706
- return external_exports.NEVER;
83665
+ var CUSTOM_NODE_ATTRS = {
83666
+ leadField: LeadFieldAttrsSchema,
83667
+ senderField: SenderFieldAttrsSchema,
83668
+ spintax: SpintaxAttrsSchema,
83669
+ aiSnippet: AiSnippetAttrsSchema,
83670
+ link: LinkAttrsSchema
83671
+ };
83672
+ var CampaignNodeSchema = external_exports.lazy(
83673
+ () => external_exports.object({
83674
+ type: external_exports.string(),
83675
+ attrs: external_exports.record(external_exports.unknown()).optional(),
83676
+ content: external_exports.array(CampaignNodeSchema).optional(),
83677
+ text: external_exports.string().optional(),
83678
+ marks: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).optional()
83679
+ }).superRefine((node2, ctx) => {
83680
+ const attrsSchema = CUSTOM_NODE_ATTRS[node2.type];
83681
+ if (attrsSchema) {
83682
+ const result = attrsSchema.safeParse(node2.attrs);
83683
+ if (!result.success) {
83684
+ for (const issue of result.error.issues) {
83685
+ ctx.addIssue({ ...issue, path: ["attrs", ...issue.path] });
83686
+ }
83687
+ }
83707
83688
  }
83708
- }
83709
- return raw;
83710
- }, StructuredQueryRequestShape);
83711
-
83712
- // ../../libs/api-contract/src/public-api-v0/tables-contract.ts
83713
- var c = initContract();
83714
- var CellSuccessSchema = external_exports.object({
83715
- status: external_exports.literal("success"),
83716
- value: external_exports.unknown(),
83717
- fields: external_exports.record(external_exports.unknown()).nullable(),
83718
- is_stale: external_exports.literal(true).optional()
83719
- });
83720
- var CellErrorSchema = external_exports.object({
83721
- status: external_exports.literal("error"),
83722
- error: external_exports.string().optional()
83723
- });
83724
- var CellPendingSchema = external_exports.object({
83725
- status: external_exports.enum(["running", "queued", "retry", "rate_limited", "awaiting_callback"])
83726
- });
83727
- var CellEmptySchema = external_exports.object({
83728
- status: external_exports.literal("empty")
83689
+ })
83690
+ );
83691
+ var CampaignDocumentSchema = external_exports.object({
83692
+ type: external_exports.literal("doc"),
83693
+ content: external_exports.array(CampaignNodeSchema)
83729
83694
  });
83730
- var CellResultSchema = external_exports.discriminatedUnion("status", [
83731
- CellSuccessSchema,
83732
- CellErrorSchema,
83733
- CellPendingSchema,
83734
- CellEmptySchema
83695
+
83696
+ // ../../libs/shared/src/campaigns/content-utils.ts
83697
+ var isNonEmptyDoc = (doc) => {
83698
+ if (doc.content.length === 0) return false;
83699
+ return doc.content.some((node2) => {
83700
+ if (node2.type === "paragraph") {
83701
+ return Array.isArray(node2.content) && node2.content.length > 0;
83702
+ }
83703
+ return true;
83704
+ });
83705
+ };
83706
+
83707
+ // ../../libs/shared/src/campaigns/providers/smartlead-api-schemas.ts
83708
+ var SmartleadWebhookEventTypeSchema = external_exports.enum([
83709
+ "EMAIL_SENT",
83710
+ "EMAIL_REPLY",
83711
+ "EMAIL_BOUNCE",
83712
+ "EMAIL_OPEN",
83713
+ "EMAIL_LINK_CLICK",
83714
+ "LEAD_UNSUBSCRIBED",
83715
+ "LEAD_CATEGORY_UPDATED",
83716
+ "CAMPAIGN_STATUS_CHANGED",
83717
+ "MANUAL_STEP_REACHED",
83718
+ // Only here for completeness- we don't configure campaigns for this event type.
83719
+ // We only include this for legacy reasons- do NOT set this. Setting this causes emails sent beyond the
83720
+ // first one to no longer trigger webhook events, which is NOT what we want.
83721
+ "FIRST_EMAIL_SENT"
83735
83722
  ]);
83736
- var FieldMetaSchema = external_exports.object({
83737
- id: external_exports.string(),
83738
- name: external_exports.string(),
83739
- type: external_exports.string()
83740
- });
83741
- var QueryResponseSchema = paginatedResponse(external_exports.record(CellResultSchema)).extend({
83742
- fields: external_exports.record(FieldMetaSchema).optional()
83743
- });
83744
- var publicApiTablesContract = c.router({
83745
- query: {
83746
- method: "POST",
83747
- path: "/tables/query",
83748
- body: StructuredQueryRequest,
83749
- responses: {
83750
- 200: QueryResponseSchema,
83751
- 400: errorResponseSchema,
83752
- 401: errorResponseSchema,
83753
- 403: errorResponseSchema,
83754
- 404: errorResponseSchema,
83755
- 422: errorResponseSchema,
83756
- 429: errorResponseSchema
83757
- },
83758
- summary: "Run a structured query across one or more tables",
83759
- description: "Runs a structured query against Clay table data and returns records with field metadata."
83760
- }
83761
- });
83762
-
83763
- // src/commands/tables/projection.ts
83764
- function projectCell(cell) {
83765
- if (cell.status === "success") {
83766
- return {
83767
- status: "success",
83768
- value: cell.value,
83769
- fields: cell.fields,
83770
- ...cell.is_stale === true ? { isStale: true } : {}
83771
- };
83772
- }
83773
- if (cell.status === "error") {
83774
- return cell.error === void 0 ? { status: "error" } : { status: "error", error: cell.error };
83775
- }
83776
- if (cell.status === "empty") {
83777
- return { status: "empty" };
83778
- }
83779
- return { status: cell.status };
83780
- }
83781
- function projectRow(row) {
83782
- const out = {};
83783
- for (const [key, cell] of Object.entries(row)) {
83784
- out[key] = projectCell(cell);
83785
- }
83786
- return out;
83787
- }
83788
- function projectFields(fields) {
83789
- const out = {};
83790
- for (const [key, meta] of Object.entries(fields)) {
83791
- out[key] = { id: meta.id, name: meta.name, type: meta.type };
83792
- }
83793
- return out;
83794
- }
83795
- function projectQueryResponse(response) {
83796
- return {
83797
- data: response.data.map(projectRow),
83798
- ...response.cursor === void 0 ? {} : { cursor: response.cursor },
83799
- ...response.fields === void 0 ? {} : { fields: projectFields(response.fields) }
83800
- };
83801
- }
83802
-
83803
- // src/commands/tables/query.ts
83804
- function parseLimit(raw) {
83805
- const n2 = Number.parseInt(raw, 10);
83806
- if (!Number.isInteger(n2) || String(n2) !== raw.trim()) {
83807
- throw new InvalidArgumentError("must be an integer");
83808
- }
83809
- return n2;
83810
- }
83811
- function buildRequestBody(opts) {
83812
- const body = {
83813
- query: readJsonFlag("--query", opts.query),
83814
- ...opts.limit !== void 0 ? { limit: opts.limit } : {},
83815
- ...opts.cursor !== void 0 ? { cursor: opts.cursor } : {}
83816
- };
83817
- const result = StructuredQueryRequest.safeParse(body);
83818
- if (!result.success) {
83819
- const issue = result.error.issues[0];
83820
- const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
83821
- const message = issue === void 0 ? "invalid shape" : issue.message;
83822
- throw new InvalidArgumentError(`invalid request${path7}: ${message}`);
83823
- }
83824
- return body;
83825
- }
83826
- function buildQueryCommand() {
83827
- const cmd = new Command("query");
83828
- cmd.description(
83829
- "Run a structured query against one or more tables in the authenticated workspace. The query is read from --query; the response is written to stdout as JSON."
83830
- ).requiredOption(
83831
- "--query <file|->",
83832
- "Path to a JSON file containing the structured query. Use - to read from stdin."
83833
- ).option("--limit <n>", "Max rows to return (1-100, default 50).", parseLimit).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").addHelpText(
83834
- "after",
83835
- `
83836
- Output (success, exit 0):
83837
- {
83838
- "data": [ { "<fieldId>": <cell> } ],
83839
- "cursor": <string|undefined>,
83840
- "fields": <{ "<fieldId>": { "id": <string>, "name": <string>, "type": <string> } }|undefined>
83841
- }
83842
-
83843
- Each <cell> is one of:
83844
- { "status": "success", "value": <unknown>, "fields": <object|null>, "isStale": <true|undefined> }
83845
- { "status": "error", "error": <string|undefined> }
83846
- { "status": "running" | "queued" | "retry" | "rate_limited" | "awaiting_callback" }
83847
- { "status": "empty" }
83848
-
83849
- Query shape (--query):
83850
- The --query file is the query itself \u2014 what to fetch. Pagination is not part of it.
83851
- Minimal: { "tables": [{ "id": "tbl_..." }] }
83852
- Beyond \`tables\`, a query may also include \`filter\`, \`select\`, \`join\`, \`order_by\`,
83853
- \`group_by\`, and \`field_mode\`.
83854
- Field references can use ids or names; multi-table queries declare each table in \`tables\`.
83855
-
83856
- Pagination:
83857
- Page size and position are flags, not part of the query:
83858
- --limit <n> max rows per call (1-100, default 50)
83859
- --cursor <token> resume from a previous response's \`cursor\`
83860
- When more results exist, the response includes a top-level \`cursor\`; pass it back via
83861
- --cursor to fetch the next page.
83862
-
83863
- Common errors:
83864
- validation_error (exit 2) Missing --query, unreadable file, invalid JSON, or a request that does not match the schema.
83865
- auth_forbidden (exit 3) Key lacks the cli:all scope, or the workspace is not in the public-API beta.
83866
- not_found (exit 6) A referenced table or field does not exist.
83867
-
83868
- Examples:
83869
- $ clay tables query --query ./query.json | jq '.data | length'
83870
- $ echo '{"tables":[{"id":"tbl_..."}]}' | clay tables query --query - --limit 100
83871
- $ clay tables query --query ./query.json --limit 100 --cursor "$CURSOR"
83872
- `
83873
- ).action(async (opts) => {
83874
- const body = buildRequestBody(opts);
83875
- const client = await publicApiClient(publicApiTablesContract);
83876
- const response = await unwrap(client.query({ body }));
83877
- writeJson(projectQueryResponse(response));
83878
- });
83879
- return cmd;
83880
- }
83881
-
83882
- // ../../libs/api-contract/src/clayql/clayql-sync/interfaces.ts
83883
- var MAX_BULK_SYNC_ITEMS = 5;
83884
- var SyncStatusSchema = external_exports.enum(["in_progress", "success", "error"]);
83885
- var EnqueueRecordsSyncInput = external_exports.object({
83886
- workspaceId: external_exports.number(),
83887
- tableId: external_exports.string(),
83888
- // Set by the worker on recovery follow-ups; breaks the chain on empty batch.
83889
- isTailReenqueue: external_exports.boolean().optional()
83890
- });
83891
- var JobState = external_exports.enum([
83892
- "completed",
83893
- "failed",
83894
- "delayed",
83895
- "active",
83896
- "waiting",
83897
- "waiting-children",
83898
- "unknown",
83899
- "prioritized"
83900
- ]);
83901
- var EnqueueRecordsSyncResponse = external_exports.object({
83902
- jobId: external_exports.string(),
83903
- status: JobState,
83904
- enqueuedAt: external_exports.string().datetime()
83905
- });
83906
- var EnqueueTablesInput = external_exports.object({
83907
- workspaceId: external_exports.number(),
83908
- tableIds: external_exports.array(external_exports.string()).min(1).max(MAX_BULK_SYNC_ITEMS),
83909
- delayMs: external_exports.number().int().min(0).max(6e4).optional().describe(
83910
- "Debounce window in ms passed to BullMQ as job delay. While a job with the same dedup id is delayed, subsequent enqueues are collapsed into it \u2014 gives cluster-wide debouncing on top of any per-pod throttling."
83911
- )
83912
- });
83913
- var EnqueueTablesResponse = external_exports.object({
83914
- totalQueued: external_exports.number(),
83915
- errors: external_exports.array(
83916
- external_exports.object({
83917
- tableId: external_exports.string(),
83918
- workspaceId: external_exports.number(),
83919
- error: external_exports.string()
83920
- })
83921
- ).optional()
83922
- });
83923
- var ExecuteQueryInput = external_exports.object({
83924
- workspaceId: external_exports.number(),
83925
- query: external_exports.string(),
83926
- parameters: external_exports.record(external_exports.union([external_exports.string(), external_exports.number(), external_exports.array(external_exports.string())])),
83927
- conversationId: external_exports.string().optional()
83928
- });
83929
- var ExecuteQueryResponse = external_exports.array(external_exports.record(external_exports.any()));
83930
-
83931
- // ../../libs/api-contract/src/tables/clayql-sync/contract.ts
83932
- var ClayQLSyncStatusValue = external_exports.union([SyncStatusSchema, external_exports.literal("never_synced")]);
83933
- var ClayQLSyncErrorCode = external_exports.enum([
83934
- "INVALID_INPUT",
83935
- "DB_CONNECTION_ERROR",
83936
- "QUERY_ERROR",
83937
- "DATABASE_ERROR",
83938
- "RECORD_PROCESSING_ERROR",
83939
- "WATERMARK_ERROR",
83940
- "ORPHANED",
83941
- "UNKNOWN_ERROR"
83942
- ]);
83943
- var ClayQLSyncStatusResponse = external_exports.object({
83944
- status: ClayQLSyncStatusValue,
83945
- lastAttemptAt: external_exports.string().datetime().nullable(),
83946
- lastSuccessAt: external_exports.string().datetime().nullable(),
83947
- errorCode: ClayQLSyncErrorCode.nullable()
83948
- });
83949
- var ClayQLSyncUsageResponse = external_exports.object({
83950
- used: external_exports.number().int().nonnegative(),
83951
- limit: external_exports.number().int().nonnegative(),
83952
- slotTableIds: external_exports.array(external_exports.string())
83953
- });
83954
- var UpdateClayQLSyncRequest = external_exports.object({
83955
- enabled: external_exports.boolean()
83956
- });
83957
- var UpdateClayQLSyncResponse = external_exports.object({
83958
- id: external_exports.string(),
83959
- enabled: external_exports.boolean()
83960
- });
83961
- var clayqlSyncContract = {
83962
- getClayQLSyncStatus: {
83963
- method: "GET",
83964
- path: "/workspaces/:workspaceId/tables/:tableId/clayql-sync-status",
83965
- pathParams: external_exports.object({
83966
- workspaceId: workspaceIdPathParam,
83967
- tableId: external_exports.string()
83968
- }),
83969
- responses: {
83970
- 200: ClayQLSyncStatusResponse
83971
- },
83972
- summary: "Latest ClayQL sync attempt for a table",
83973
- metadata: { team: "rep-tools" /* RepTools */ }
83974
- },
83975
- getClayQLSyncUsage: {
83976
- method: "GET",
83977
- path: "/workspaces/:workspaceId/clayql-sync-usage",
83978
- pathParams: external_exports.object({
83979
- workspaceId: workspaceIdPathParam
83980
- }),
83981
- responses: {
83982
- 200: ClayQLSyncUsageResponse
83983
- },
83984
- summary: "Workspace synced-tables usage and limit",
83985
- metadata: { team: "rep-tools" /* RepTools */ }
83986
- },
83987
- updateTableClayQLSync: {
83988
- method: "PUT",
83989
- path: "/workspaces/:workspaceId/tables/:tableId/clayql-sync",
83990
- pathParams: external_exports.object({
83991
- workspaceId: workspaceIdPathParam,
83992
- tableId: external_exports.string()
83993
- }),
83994
- body: UpdateClayQLSyncRequest,
83995
- responses: {
83996
- 200: UpdateClayQLSyncResponse
83997
- },
83998
- summary: "Enable or disable ClayQL sync for a table",
83999
- metadata: { team: "rep-tools" /* RepTools */ }
84000
- }
84001
- };
84002
-
84003
- // src/commands/tables/update.ts
84004
- function buildUpdateCommand2() {
84005
- const cmd = new Command("update");
84006
- cmd.description(
84007
- "Enable or disable API query sync for a table in the authenticated workspace. A table must have sync enabled before it can be used with `clay tables query`."
84008
- ).argument("<tableId>", "Table id, e.g. tbl_abc123").requiredOption(
84009
- "--query-sync <true|false>",
84010
- "Enable (true) or disable (false) API query sync for the table.",
84011
- parseBooleanFlag("--query-sync")
84012
- ).addHelpText(
84013
- "after",
84014
- `
84015
- Output (success, exit 0):
84016
- {
84017
- "id": <string>,
84018
- "querySyncEnabled": <boolean>
84019
- }
84020
-
84021
- Common errors:
84022
- validation_error (exit 2) Missing or invalid --query-sync, or missing table id.
84023
- auth_forbidden (exit 3) Key lacks the cli:all scope (or all) or you lack access to the table.
84024
- not_found (exit 6) No table with that id in this workspace.
84025
-
84026
- Examples:
84027
- $ clay tables update tbl_abc123 --query-sync true
84028
- $ clay tables update tbl_abc123 --query-sync false | jq '.querySyncEnabled'
84029
- `
84030
- ).action(async (tableId, opts) => {
84031
- const workspaceId = await currentWorkspaceId();
84032
- const client = await v3Client(clayqlSyncContract);
84033
- const updated = await unwrap(
84034
- client.updateTableClayQLSync({
84035
- params: { workspaceId, tableId },
84036
- body: { enabled: opts.querySync }
84037
- })
84038
- );
84039
- writeJson({ id: updated.id, querySyncEnabled: updated.enabled });
84040
- });
84041
- return cmd;
84042
- }
84043
-
84044
- // src/commands/tables/index.ts
84045
- function registerTables(program3) {
84046
- const tables = applyClaySettings(
84047
- new Command("tables").description(
84048
- "Work with tables in the authenticated workspace. Subcommands: list, query, update."
84049
- )
84050
- );
84051
- tables.addHelpText(
84052
- "after",
84053
- `
84054
- Subcommands:
84055
- list List tables in the workspace.
84056
- query Run a structured query across one or more tables.
84057
- update Enable or disable API query sync for a table.
84058
-
84059
- See \`clay tables <subcommand> --help\` for per-subcommand JSON shape, error codes, and examples.
84060
- `
84061
- );
84062
- tables.addCommand(applyClaySettings(buildListCommand2()));
84063
- tables.addCommand(applyClaySettings(buildQueryCommand()));
84064
- tables.addCommand(applyClaySettings(buildUpdateCommand2()));
84065
- program3.addCommand(tables);
84066
- }
84067
-
84068
- // ../../libs/shared/src/tables/base-types.ts
84069
- var import_lodash6 = __toESM(require_lodash());
84070
-
84071
- // ../../libs/shared/src/FormulaTypes.ts
84072
- var FormulaMap = external_exports.record(external_exports.string(), external_exports.string().optional());
84073
- var NestedFormulaMap = external_exports.record(external_exports.string(), external_exports.union([external_exports.string(), FormulaMap]).optional());
84074
-
84075
- // ../../libs/shared/src/actions/base-types.ts
84076
- var ActionKeySchema = external_exports.string();
84077
- var ActionPackageIdSchema = external_exports.string();
84078
- var ActionPackage = external_exports.object({
84079
- id: external_exports.string(),
84080
- key: external_exports.string(),
84081
- description: external_exports.string().optional(),
84082
- displayName: external_exports.string(),
84083
- icon: external_exports.string(),
84084
- darkIcon: external_exports.string().optional(),
84085
- categories: external_exports.array(external_exports.string()).optional(),
84086
- termsAndConditions: external_exports.array(external_exports.string()).optional(),
84087
- vpcLambdaOnly: external_exports.boolean().optional()
84088
- });
84089
- var InputsBinding = external_exports.object({
84090
- name: external_exports.string(),
84091
- formulaText: external_exports.string().nullish(),
84092
- formulaMap: FormulaMap.nullish(),
84093
- optional: external_exports.boolean().optional()
84094
- });
84095
- var OnOpenPanelAction = external_exports.enum(["openMetaPrompter"]);
84096
- var SidebarParamsSchema = external_exports.object({
84097
- onOpenPanelAction: OnOpenPanelAction.optional()
84098
- });
84099
- var ActionDisplayProps = external_exports.object({
84100
- iconUri: external_exports.string().optional(),
84101
- darkIconUri: external_exports.string().optional(),
84102
- packageIcon: external_exports.string(),
84103
- packageDarkIcon: external_exports.string().optional(),
84104
- displayName: external_exports.string()
84105
- });
84106
- var ActionLogInfo = external_exports.object({
84107
- requestId: external_exports.string().nullable(),
84108
- groupName: external_exports.string().nullable(),
84109
- streamName: external_exports.string().nullable(),
84110
- url: external_exports.string().nullable(),
84111
- mezmoUrl: external_exports.string().nullable()
84112
- });
84113
- var ActionTaskRunType = /* @__PURE__ */ ((ActionTaskRunType2) => {
84114
- ActionTaskRunType2["Action"] = "action";
84115
- ActionTaskRunType2["ActionPreview"] = "action-preview";
84116
- ActionTaskRunType2["Source"] = "source";
84117
- ActionTaskRunType2["SourcePreview"] = "source-preview";
84118
- return ActionTaskRunType2;
84119
- })(ActionTaskRunType || {});
84120
- var ActionTaskRunTypeSchema = external_exports.nativeEnum(ActionTaskRunType);
84121
-
84122
- // ../../libs/shared/src/attributes/attribute-enum.ts
84123
- var AttributeEnum = /* @__PURE__ */ ((AttributeEnum2) => {
84124
- AttributeEnum2["Person_FullName"] = "person/fullName";
84125
- AttributeEnum2["Person_FirstName"] = "person/firstName";
84126
- AttributeEnum2["Person_LastName"] = "person/lastName";
84127
- AttributeEnum2["Person_MiddleName"] = "person/middleName";
84128
- AttributeEnum2["Person_Location_Summary"] = "person/location/summary";
84129
- AttributeEnum2["Person_Company"] = "person/company";
84130
- AttributeEnum2["Person_JobTitle"] = "person/jobTitle";
84131
- AttributeEnum2["Person_JobStartDate"] = "person/jobStartDate";
84132
- AttributeEnum2["Person_PictureUrl"] = "person/pictureUrl";
84133
- AttributeEnum2["Person_Bio"] = "person/bio";
84134
- AttributeEnum2["Person_PersonalEmail"] = "person/personalEmail";
84135
- AttributeEnum2["Person_WorkEmail"] = "person/workEmail";
84136
- AttributeEnum2["Person_WorkEmailEnterprise"] = "person/workEmailEnterprise";
84137
- AttributeEnum2["Person_InfluencerEmail"] = "person/influencerEmail";
84138
- AttributeEnum2["Person_AdvertisingEmail"] = "person/advertisingEmail";
84139
- AttributeEnum2["Person_Phone"] = "person/phone";
84140
- AttributeEnum2["Person_PhoneEMEA"] = "person/phoneEMEA";
84141
- AttributeEnum2["Person_PhoneAPAC"] = "person/phoneAPAC";
84142
- AttributeEnum2["Person_PhoneGlobal"] = "person/phoneGlobal";
84143
- AttributeEnum2["Person_Gender"] = "person/gender";
84144
- AttributeEnum2["Person_LinkedIn_Url"] = "person/linkedIn/url";
84145
- AttributeEnum2["Person_Facebook"] = "person/facebook";
84146
- AttributeEnum2["Person_Instagram"] = "person/instagram";
84147
- AttributeEnum2["Person_Twitter"] = "person/twitter";
84148
- AttributeEnum2["Person_Github"] = "person/github";
84149
- AttributeEnum2["Person_EducationLevel"] = "person/educationLevel";
84150
- AttributeEnum2["Person_SchoolName"] = "person/schoolName";
84151
- AttributeEnum2["Person_Industry"] = "person/industry";
84152
- AttributeEnum2["Company_EmployeeCount"] = "company/employeeCount";
84153
- AttributeEnum2["Company_Domain"] = "company/domain";
84154
- AttributeEnum2["Company_Description"] = "company/description";
84155
- AttributeEnum2["Company_Revenue"] = "company/revenue";
84156
- AttributeEnum2["Company_Industry"] = "company/industry";
84157
- AttributeEnum2["Company_FoundedDate"] = "company/foundedDate";
84158
- AttributeEnum2["Company_Country"] = "company/country";
84159
- AttributeEnum2["Company_Address"] = "company/address";
84160
- AttributeEnum2["Company_FundingPrediction"] = "company/fundingPrediction";
84161
- AttributeEnum2["Company_GrowthInsight"] = "company/growthInsight";
84162
- AttributeEnum2["Company_Valuation"] = "company/valuation";
84163
- AttributeEnum2["Company_FundingRound"] = "company/fundingRound";
84164
- AttributeEnum2["Company_TotalFunding"] = "company/totalFunding";
84165
- AttributeEnum2["Company_SiteTraffic"] = "company/siteTraffic";
84166
- AttributeEnum2["Company_TechStack"] = "company/techStack";
84167
- AttributeEnum2["Company_FullTechStack"] = "company/fullTechStack";
84168
- AttributeEnum2["Company_CorporateStructure"] = "company/corporateStructure";
84169
- AttributeEnum2["Company_JobOpenings"] = "company/jobOpenings";
84170
- AttributeEnum2["Company_Logo"] = "company/logo";
84171
- AttributeEnum2["Company_LinkedIn_Url"] = "company/linkedIn/url";
84172
- AttributeEnum2["Company_Facebook"] = "company/facebook";
84173
- AttributeEnum2["Company_Instagram"] = "company/instagram";
84174
- AttributeEnum2["Company_Twitter"] = "company/twitter";
84175
- AttributeEnum2["Company_Github"] = "company/github";
84176
- AttributeEnum2["Company_Crunchbase"] = "company/crunchbase";
84177
- AttributeEnum2["Company_OwnershipStatus"] = "company/ownershipStatus";
84178
- AttributeEnum2["Company_Investors"] = "company/investors";
84179
- AttributeEnum2["Company_Acquisitions"] = "company/acquisitions";
84180
- AttributeEnum2["Company_Features"] = "company/features";
84181
- AttributeEnum2["Company_Competitors"] = "company/competitors";
84182
- AttributeEnum2["Company_PricingDetails"] = "company/pricingDetails";
84183
- AttributeEnum2["Company_News"] = "company/news";
84184
- AttributeEnum2["Company_LatestFundingDate"] = "company/latestFundingDate";
84185
- AttributeEnum2["Company_LatestFunding"] = "company/latestFunding";
84186
- AttributeEnum2["Company_NumberOfFundingRounds"] = "company/numberOfFundingRounds";
84187
- AttributeEnum2["Company_EmployeeCountByCriteria"] = "company/employeeCountByCriteria";
84188
- AttributeEnum2["Company_NumberOfFundsRaised"] = "company/numberOfFundsRaised";
84189
- AttributeEnum2["Company_FundTotalAmountRaised"] = "company/fundTotalAmountRaised";
84190
- AttributeEnum2["Company_FundInvestments"] = "company/fundInvestments";
84191
- AttributeEnum2["Company_Phone"] = "company/phone";
84192
- return AttributeEnum2;
84193
- })(AttributeEnum || {});
84194
- var AttributeEnumSchema = external_exports.nativeEnum(AttributeEnum);
84195
-
84196
- // ../../libs/shared/src/campaigns/content-types.ts
84197
- var AiSnippetAttrsSchema = external_exports.object({
84198
- snippetId: external_exports.string().min(1),
84199
- label: external_exports.string(),
84200
- brief: external_exports.unknown().optional()
84201
- });
84202
- var MIN_SPINTAX_VARIANTS = 2;
84203
- var MAX_SPINTAX_VARIANTS = 5;
84204
- var SpintaxAttrsSchema = external_exports.object({
84205
- variants: external_exports.array(external_exports.string().min(1)).min(MIN_SPINTAX_VARIANTS).max(MAX_SPINTAX_VARIANTS).refine((v) => new Set(v).size === v.length, { message: "Variants must be unique" })
84206
- });
84207
- var SenderFieldAttrsSchema = external_exports.object({
84208
- option: external_exports.enum(["senderFullName", "senderFirstName"])
84209
- });
84210
- var LeadFieldFormatSchema = external_exports.enum(["none", "titleCase", "lowerCase", "upperCase", "sentenceCase"]);
84211
- var LeadFieldAttrsSchema = external_exports.object({
84212
- fieldId: external_exports.string().min(1),
84213
- label: external_exports.string().min(1),
84214
- required: external_exports.boolean(),
84215
- format: LeadFieldFormatSchema,
84216
- stripEmojis: external_exports.boolean(),
84217
- fallback: external_exports.string().nullable()
84218
- }).refine((a) => !a.required || a.fallback === null, {
84219
- message: "Required variables should not have a fallback",
84220
- path: ["fallback"]
84221
- }).refine((a) => a.required || typeof a.fallback === "string" && a.fallback.length > 0, {
84222
- message: "Non-required variables must have a fallback",
84223
- path: ["fallback"]
84224
- });
84225
- var FONT_FAMILY_OPTIONS = {
84226
- SansSerif: "sans-serif",
84227
- Serif: "times new roman, serif",
84228
- FixedWidth: "monospace",
84229
- Wide: "arial black, sans-serif",
84230
- Narrow: "arial narrow, sans-serif",
84231
- ComicSans: "Comic Sans MS, sans-serif",
84232
- Garamond: "Garamond",
84233
- Georgia: "Georgia",
84234
- Tahoma: "Tahoma",
84235
- TrebuchetMS: "Trebuchet MS",
84236
- Verdana: "Verdana"
84237
- };
84238
- var FONT_FAMILY_VALUES = Object.values(FONT_FAMILY_OPTIONS);
84239
- var LinkAttrsSchema = external_exports.object({
84240
- href: external_exports.lazy(() => CampaignDocumentSchema),
84241
- label: external_exports.lazy(() => CampaignDocumentSchema)
84242
- });
84243
- var CUSTOM_NODE_ATTRS = {
84244
- leadField: LeadFieldAttrsSchema,
84245
- senderField: SenderFieldAttrsSchema,
84246
- spintax: SpintaxAttrsSchema,
84247
- aiSnippet: AiSnippetAttrsSchema,
84248
- link: LinkAttrsSchema
84249
- };
84250
- var CampaignNodeSchema = external_exports.lazy(
84251
- () => external_exports.object({
84252
- type: external_exports.string(),
84253
- attrs: external_exports.record(external_exports.unknown()).optional(),
84254
- content: external_exports.array(CampaignNodeSchema).optional(),
84255
- text: external_exports.string().optional(),
84256
- marks: external_exports.array(external_exports.object({ type: external_exports.string() }).passthrough()).optional()
84257
- }).superRefine((node2, ctx) => {
84258
- const attrsSchema = CUSTOM_NODE_ATTRS[node2.type];
84259
- if (attrsSchema) {
84260
- const result = attrsSchema.safeParse(node2.attrs);
84261
- if (!result.success) {
84262
- for (const issue of result.error.issues) {
84263
- ctx.addIssue({ ...issue, path: ["attrs", ...issue.path] });
84264
- }
84265
- }
84266
- }
84267
- })
84268
- );
84269
- var CampaignDocumentSchema = external_exports.object({
84270
- type: external_exports.literal("doc"),
84271
- content: external_exports.array(CampaignNodeSchema)
84272
- });
84273
-
84274
- // ../../libs/shared/src/campaigns/content-utils.ts
84275
- var isNonEmptyDoc = (doc) => {
84276
- if (doc.content.length === 0) return false;
84277
- return doc.content.some((node2) => {
84278
- if (node2.type === "paragraph") {
84279
- return Array.isArray(node2.content) && node2.content.length > 0;
84280
- }
84281
- return true;
84282
- });
84283
- };
84284
-
84285
- // ../../libs/shared/src/campaigns/providers/smartlead-api-schemas.ts
84286
- var SmartleadWebhookEventTypeSchema = external_exports.enum([
84287
- "EMAIL_SENT",
84288
- "EMAIL_REPLY",
84289
- "EMAIL_BOUNCE",
84290
- "EMAIL_OPEN",
84291
- "EMAIL_LINK_CLICK",
84292
- "LEAD_UNSUBSCRIBED",
84293
- "LEAD_CATEGORY_UPDATED",
84294
- "CAMPAIGN_STATUS_CHANGED",
84295
- "MANUAL_STEP_REACHED",
84296
- // Only here for completeness- we don't configure campaigns for this event type.
84297
- // We only include this for legacy reasons- do NOT set this. Setting this causes emails sent beyond the
84298
- // first one to no longer trigger webhook events, which is NOT what we want.
84299
- "FIRST_EMAIL_SENT"
84300
- ]);
84301
- var SmartleadWebhookEventType = SmartleadWebhookEventTypeSchema.Enum;
84302
- var SmartleadCampaignStatusTransitionSchema = external_exports.enum(["START", "PAUSED", "STOPPED"]);
84303
- var SmartleadCampaignStatusTransition = SmartleadCampaignStatusTransitionSchema.Enum;
84304
- var SmartleadCampaignStatusSchema = external_exports.enum([
84305
- "DRAFTED",
84306
- "ACTIVE",
84307
- "PAUSED",
84308
- "STOPPED",
84309
- "COMPLETED",
84310
- "ARCHIVED"
84311
- ]);
84312
- var SmartleadCampaignStatus = SmartleadCampaignStatusSchema.Enum;
84313
- var SmartleadEmailAccountTypeSchema = external_exports.enum(["GMAIL", "OUTLOOK", "SMTP"]);
84314
- var SmartleadEmailAccountType = SmartleadEmailAccountTypeSchema.Enum;
84315
- var SMARTLEAD_EMAIL_ACCOUNT_TYPE_LABELS = {
84316
- [SmartleadEmailAccountType.GMAIL]: "Gmail",
84317
- [SmartleadEmailAccountType.OUTLOOK]: "Outlook",
84318
- [SmartleadEmailAccountType.SMTP]: "SMTP/IMAP"
84319
- };
84320
- var EmailAccountSourceSchema = external_exports.enum(["OAUTH", "SMART_SENDERS", "MANUAL"]);
84321
- var EmailAccountSource = EmailAccountSourceSchema.Enum;
84322
- var SmartleadSmtpEmailAccountSettings = external_exports.object({
84323
- from_name: external_exports.string(),
84324
- // e.g. "John Doe"
84325
- from_email: external_exports.string(),
84326
- // e.g. "john.doe@example.com"
84327
- user_name: external_exports.string(),
84328
- // e.g. "john.doe@example.com"
84329
- password: external_exports.string(),
84330
- // e.g. "password"
84331
- smtp_host: external_exports.string(),
84332
- // e.g. "smtp.gmail.com"
84333
- smtp_port: external_exports.number(),
84334
- // e.g. 465 for SSL, 587 for TLS, 25 for unencrypted
84335
- imap_host: external_exports.string(),
84336
- // e.g. "imap.gmail.com"
84337
- imap_port: external_exports.number()
84338
- // e.g. 993 for SSL/TLS, 143 for unencrypted
83723
+ var SmartleadWebhookEventType = SmartleadWebhookEventTypeSchema.Enum;
83724
+ var SmartleadCampaignStatusTransitionSchema = external_exports.enum(["START", "PAUSED", "STOPPED"]);
83725
+ var SmartleadCampaignStatusTransition = SmartleadCampaignStatusTransitionSchema.Enum;
83726
+ var SmartleadCampaignStatusSchema = external_exports.enum([
83727
+ "DRAFTED",
83728
+ "ACTIVE",
83729
+ "PAUSED",
83730
+ "STOPPED",
83731
+ "COMPLETED",
83732
+ "ARCHIVED"
83733
+ ]);
83734
+ var SmartleadCampaignStatus = SmartleadCampaignStatusSchema.Enum;
83735
+ var SmartleadEmailAccountTypeSchema = external_exports.enum(["GMAIL", "OUTLOOK", "SMTP"]);
83736
+ var SmartleadEmailAccountType = SmartleadEmailAccountTypeSchema.Enum;
83737
+ var SMARTLEAD_EMAIL_ACCOUNT_TYPE_LABELS = {
83738
+ [SmartleadEmailAccountType.GMAIL]: "Gmail",
83739
+ [SmartleadEmailAccountType.OUTLOOK]: "Outlook",
83740
+ [SmartleadEmailAccountType.SMTP]: "SMTP/IMAP"
83741
+ };
83742
+ var EmailAccountSourceSchema = external_exports.enum(["OAUTH", "SMART_SENDERS", "MANUAL"]);
83743
+ var EmailAccountSource = EmailAccountSourceSchema.Enum;
83744
+ var SmartleadSmtpEmailAccountSettings = external_exports.object({
83745
+ from_name: external_exports.string(),
83746
+ // e.g. "John Doe"
83747
+ from_email: external_exports.string(),
83748
+ // e.g. "john.doe@example.com"
83749
+ user_name: external_exports.string(),
83750
+ // e.g. "john.doe@example.com"
83751
+ password: external_exports.string(),
83752
+ // e.g. "password"
83753
+ smtp_host: external_exports.string(),
83754
+ // e.g. "smtp.gmail.com"
83755
+ smtp_port: external_exports.number(),
83756
+ // e.g. 465 for SSL, 587 for TLS, 25 for unencrypted
83757
+ imap_host: external_exports.string(),
83758
+ // e.g. "imap.gmail.com"
83759
+ imap_port: external_exports.number()
83760
+ // e.g. 993 for SSL/TLS, 143 for unencrypted
84339
83761
  });
84340
83762
  var SmartleadEmailAccount = external_exports.object({
84341
83763
  id: external_exports.number(),
@@ -84651,14 +84073,14 @@ var FunnelStageSchema = external_exports.enum(["cold", "warm"]);
84651
84073
  var FunnelStage = FunnelStageSchema.Enum;
84652
84074
  var CampaignStatusSchema = external_exports.enum(["draft", "active", "paused", "completed"]);
84653
84075
  var CampaignStatus = CampaignStatusSchema.Enum;
84654
- var CampaignLeadOriginTypeSchema = external_exports.enum(["audience"]);
84655
- var CampaignLeadOriginType = CampaignLeadOriginTypeSchema.Enum;
84656
84076
  var CampaignProviderTypeSchema = external_exports.enum(["smartlead"]);
84657
84077
  var CampaignProviderType = CampaignProviderTypeSchema.Enum;
84658
84078
  var DayOfWeekSchema = external_exports.enum(["mon", "tue", "wed", "thu", "fri", "sat", "sun"]);
84659
84079
  var DayOfWeek = DayOfWeekSchema.Enum;
84660
84080
  var ScheduleTypeSchema = external_exports.enum(["prioritize_deliverability", "asap", "custom"]);
84661
84081
  var ScheduleType = ScheduleTypeSchema.Enum;
84082
+ var SenderAssignmentTypeSchema = external_exports.enum(["none", "direct", "rep_round_robin"]);
84083
+ var SenderAssignmentType = SenderAssignmentTypeSchema.Enum;
84662
84084
  var CampaignSequenceStepBaseSchema = external_exports.object({
84663
84085
  id: external_exports.string(),
84664
84086
  subject: CampaignDocumentSchema,
@@ -84702,11 +84124,19 @@ var CampaignSettingsSchema = external_exports.object({
84702
84124
  scheduleSettings: ScheduleSettingsSchema,
84703
84125
  senderAccountIds: external_exports.array(external_exports.string()),
84704
84126
  senderEmailAccountAudienceFieldId: external_exports.string().nullable(),
84127
+ senderAssignmentType: SenderAssignmentTypeSchema.optional().default("none"),
84128
+ skipLeadIfSenderNotInAccounts: external_exports.boolean().optional().default(false),
84705
84129
  webhooks: external_exports.array(CampaignWebhookSchema).default([]),
84706
84130
  isHtmlEnabled: external_exports.boolean().default(false),
84707
84131
  // When true, Smartlead pauses other leads sharing a replying lead's email domain.
84708
84132
  autoPauseDomainLeadsOnReply: external_exports.boolean().default(false),
84709
- autoPauseLeadOnSegmentExit: external_exports.boolean().optional().default(false)
84133
+ autoPauseLeadOnSegmentExit: external_exports.boolean().optional().default(false),
84134
+ // cooldownBlocksOthers: this campaign's enrollments make leads ineligible for other campaigns.
84135
+ // Defaults on so every campaign contributes once any campaign sets a cooldown window; until a
84136
+ // window is set this has no effect.
84137
+ // cooldownWindowDays: exclude leads enrolled in such a campaign within the last N days (unset/0 = off).
84138
+ cooldownBlocksOthers: external_exports.boolean().default(true),
84139
+ cooldownWindowDays: external_exports.number().int().nonnegative().max(365).optional()
84710
84140
  });
84711
84141
  var CampaignProviderFailedSchema = external_exports.object({
84712
84142
  campaignId: external_exports.null(),
@@ -84750,7 +84180,7 @@ var CampaignContentBaseSchema = external_exports.object({
84750
84180
  sequence: external_exports.array(CampaignSequenceStepSchema),
84751
84181
  settings: CampaignSettingsSchema,
84752
84182
  claygentContext: ClaygentContextSchema.optional(),
84753
- leadOriginId: external_exports.string().optional()
84183
+ leadBaseSegmentId: external_exports.string().nullish()
84754
84184
  });
84755
84185
  var CampaignContentSchema = CampaignContentBaseSchema.superRefine((data, ctx) => {
84756
84186
  if (data.sequence.length > 0 && data.sequence[0]?.emailType !== EmailType.NEW_EMAIL_THREAD) {
@@ -84785,8 +84215,8 @@ var CampaignContentSchema = CampaignContentBaseSchema.superRefine((data, ctx) =>
84785
84215
  }
84786
84216
  });
84787
84217
  var CampaignLaunchSchema = CampaignContentSchema.superRefine((data, ctx) => {
84788
- if (!data.leadOriginId) {
84789
- ctx.addIssue({ code: "custom", message: "Add a lead list", path: ["leadOriginId"] });
84218
+ if (!data.leadBaseSegmentId) {
84219
+ ctx.addIssue({ code: "custom", message: "Add a lead list", path: ["leadBaseSegmentId"] });
84790
84220
  }
84791
84221
  if (data.sequence.length === 0) {
84792
84222
  ctx.addIssue({ code: "custom", message: "Add at least one sequence step", path: ["sequence"] });
@@ -84798,6 +84228,13 @@ var CampaignLaunchSchema = CampaignContentSchema.superRefine((data, ctx) => {
84798
84228
  path: ["settings", "senderAccountIds"]
84799
84229
  });
84800
84230
  }
84231
+ if (data.settings.senderAssignmentType !== "none" && !data.settings.senderEmailAccountAudienceFieldId) {
84232
+ ctx.addIssue({
84233
+ code: "custom",
84234
+ message: "Select a sender field or set assignment to none",
84235
+ path: ["settings", "senderEmailAccountAudienceFieldId"]
84236
+ });
84237
+ }
84801
84238
  });
84802
84239
 
84803
84240
  // ../../libs/shared/src/SemanticType.ts
@@ -92488,6 +91925,8 @@ var SmartleadSettings = external_exports.object({
92488
91925
  showUnsubscribeLink: external_exports.boolean().default(false),
92489
91926
  trackSettings: external_exports.array(external_exports.nativeEnum(TrackingSettingsEnum)).nullable().optional(),
92490
91927
  senderEmailAccountColumnFormula: external_exports.string().nullable().optional(),
91928
+ senderAssignmentType: SenderAssignmentTypeSchema.optional(),
91929
+ skipLeadIfSenderNotInAccounts: external_exports.boolean().optional(),
92491
91930
  // When true, Smartlead pauses other leads sharing a replying lead's email domain.
92492
91931
  autoPauseDomainLeadsOnReply: external_exports.boolean().optional().default(false)
92493
91932
  });
@@ -92893,242 +92332,75 @@ var FunctionUpdateToolInput = FunctionUpdateToolRequest.extend({
92893
92332
  outputFormat: MCPOutputFormat.optional()
92894
92333
  });
92895
92334
  var EnrichmentUpsertToolRequest = UpsertToolBase.extend({
92896
- type: external_exports.literal("enrichment"),
92897
- actionPackageId: external_exports.string(),
92898
- actionKey: external_exports.string(),
92899
- appAccountId: external_exports.string().nullable().optional()
92900
- });
92901
- var EnrichmentUpdateToolRequest = UpdateToolBase.extend({
92902
- type: external_exports.literal("enrichment")
92903
- });
92904
- var EnrichmentCreateToolInput = external_exports.object({
92905
- workspaceId: external_exports.number(),
92906
- type: external_exports.literal("enrichment"),
92907
- id: external_exports.string(),
92908
- name: external_exports.string().max(100).nullable().optional(),
92909
- description: external_exports.string().max(500).nullable().optional(),
92910
- access: ToolAccess
92911
- });
92912
- var EnrichmentUpsertToolInput = UpsertToolBase.extend({
92913
- type: external_exports.literal("enrichment"),
92914
- workspaceId: external_exports.number(),
92915
- id: external_exports.string()
92916
- });
92917
- var EnrichmentUpdateToolInput = EnrichmentUpdateToolRequest.extend({
92918
- workspaceId: external_exports.number(),
92919
- toolId: external_exports.string()
92920
- });
92921
- var WorkflowCreateToolRequest = CreateToolBase.extend({
92922
- type: external_exports.literal("workflow"),
92923
- id: external_exports.string(),
92924
- name: CreateToolBase.shape.name.optional()
92925
- });
92926
- var WorkflowUpsertToolRequest = UpsertToolBase.extend({
92927
- type: external_exports.literal("workflow"),
92928
- id: external_exports.string()
92929
- });
92930
- var WorkflowUpdateToolRequest = UpdateToolBase.extend({
92931
- type: external_exports.literal("workflow")
92932
- });
92933
- var WorkflowCreateToolInput = WorkflowCreateToolRequest.extend({
92934
- workspaceId: external_exports.number()
92935
- });
92936
- var WorkflowUpsertToolInput = WorkflowUpsertToolRequest.extend({
92937
- workspaceId: external_exports.number()
92938
- });
92939
- var WorkflowUpdateToolInput = WorkflowUpdateToolRequest.extend({
92940
- workspaceId: external_exports.number(),
92941
- toolId: external_exports.string()
92942
- });
92943
- var CreateToolInputSchema = external_exports.discriminatedUnion("type", [
92944
- FunctionCreateToolInput,
92945
- EnrichmentCreateToolInput,
92946
- WorkflowCreateToolInput
92947
- ]);
92948
- var UpsertToolInputSchema = external_exports.discriminatedUnion("type", [
92949
- FunctionUpsertToolInput,
92950
- EnrichmentUpsertToolInput,
92951
- WorkflowUpsertToolInput
92952
- ]);
92953
- var UpdateToolInputSchema = external_exports.discriminatedUnion("type", [
92954
- FunctionUpdateToolInput,
92955
- EnrichmentUpdateToolInput,
92956
- WorkflowUpdateToolInput
92957
- ]);
92958
-
92959
- // ../../libs/api-contract/src/public-api-v0/tools-contract.ts
92960
- var c2 = initContract();
92961
- var MAX_ID_LENGTH = 64;
92962
- var RunToolItemSchema = external_exports.object({
92963
- id: external_exports.string().min(1).max(MAX_ID_LENGTH),
92964
- inputs: external_exports.record(external_exports.unknown())
92965
- });
92966
- var MAX_RUN_ITEMS = 100;
92967
- var WEBHOOK_ID_DESCRIPTION = "ID of a registered Clay webhook to notify when the run finishes.";
92968
- var RunToolRequestSchema = external_exports.object({
92969
- items: external_exports.array(RunToolItemSchema).min(1).max(MAX_RUN_ITEMS),
92970
- webhook_id: external_exports.string().min(1).max(MAX_ID_LENGTH).optional().describe(WEBHOOK_ID_DESCRIPTION)
92971
- });
92972
- var RunToolResponseSchema = external_exports.object({
92973
- tool_run_id: external_exports.string(),
92974
- status: external_exports.literal("in_progress")
92975
- });
92976
- var RunResultItemSchema = external_exports.object({
92977
- id: external_exports.string(),
92978
- status: external_exports.enum(["complete", "failed"]),
92979
- result: external_exports.record(external_exports.unknown()).optional(),
92980
- error: external_exports.object({ message: external_exports.string() }).optional()
92981
- });
92982
- var ToolRunProgressFieldsSchema = external_exports.object({
92983
- tool_run_id: external_exports.string(),
92984
- total: external_exports.number(),
92985
- finished: external_exports.number()
92986
- });
92987
- var RunResultsInProgressSchema = ToolRunProgressFieldsSchema.extend({
92988
- status: external_exports.literal("in_progress")
92989
- });
92990
- var RunResultsCompleteSchema = ToolRunProgressFieldsSchema.extend({
92991
- status: external_exports.literal("complete"),
92992
- data: external_exports.array(RunResultItemSchema),
92993
- cursor: external_exports.string().optional()
92994
- });
92995
- var RunResultsResponseSchema = external_exports.discriminatedUnion("status", [
92996
- RunResultsInProgressSchema,
92997
- RunResultsCompleteSchema
92998
- ]);
92999
- var BatchUploadUrlResponseSchema = external_exports.object({
93000
- upload_url: external_exports.string().url(),
93001
- file_id: external_exports.string()
93002
- });
93003
- var StartBatchRequestSchema = external_exports.object({
93004
- file_id: external_exports.string(),
93005
- webhook_id: external_exports.string().min(1).max(MAX_ID_LENGTH).optional().describe(WEBHOOK_ID_DESCRIPTION)
93006
- });
93007
- var StartBatchResponseSchema = external_exports.object({
93008
- tool_run_id: external_exports.string(),
93009
- status: external_exports.literal("in_progress")
93010
- });
93011
- var BatchResultsInProgressSchema = ToolRunProgressFieldsSchema.extend({
93012
- status: external_exports.literal("in_progress")
93013
- });
93014
- var BatchValidationErrorDetailSchema = external_exports.object({
93015
- line_number: external_exports.number(),
93016
- field: external_exports.string(),
93017
- message: external_exports.string()
93018
- });
93019
- var BatchValidationErrorSchema = external_exports.object({
93020
- message: external_exports.string(),
93021
- total_invalid_rows: external_exports.number(),
93022
- details: external_exports.array(BatchValidationErrorDetailSchema).max(100)
93023
- });
93024
- var BatchResultsValidationFailedSchema = external_exports.object({
93025
- tool_run_id: external_exports.string(),
93026
- status: external_exports.literal("validation_failed"),
93027
- error: BatchValidationErrorSchema
93028
- });
93029
- var BatchResultsCompleteSchema = ToolRunProgressFieldsSchema.extend({
93030
- status: external_exports.literal("complete"),
93031
- result_url: external_exports.string().url()
93032
- });
93033
- var BatchResultsTerminalSchema = external_exports.discriminatedUnion("status", [
93034
- BatchResultsValidationFailedSchema,
93035
- BatchResultsCompleteSchema
93036
- ]);
93037
- var publicApiToolsContract = c2.router({
93038
- runTool: {
93039
- method: "POST",
93040
- path: "/tools/:tool_id/run",
93041
- pathParams: external_exports.object({
93042
- tool_id: external_exports.string()
93043
- }),
93044
- body: RunToolRequestSchema,
93045
- responses: {
93046
- 202: RunToolResponseSchema,
93047
- 400: errorResponseSchema,
93048
- 401: errorResponseSchema,
93049
- 403: errorResponseSchema,
93050
- 404: errorResponseSchema,
93051
- 429: errorResponseSchema
93052
- },
93053
- summary: "Execute a tool against 1-100 items",
93054
- description: "Starts an asynchronous tool run for up to 100 input items.",
93055
- metadata: { team: "rep-tools" /* RepTools */ }
93056
- },
93057
- getRunResults: {
93058
- method: "GET",
93059
- path: "/tools/run/:tool_run_id/results",
93060
- pathParams: external_exports.object({
93061
- tool_run_id: external_exports.string()
93062
- }),
93063
- query: paginatedQuerySchema(),
93064
- responses: {
93065
- 200: RunResultsCompleteSchema,
93066
- 202: RunResultsInProgressSchema,
93067
- 401: errorResponseSchema,
93068
- 404: errorResponseSchema,
93069
- 429: errorResponseSchema
93070
- },
93071
- summary: "Fetch progress and results for a tool run",
93072
- description: "Returns current status and paginated results for an asynchronous tool run.",
93073
- metadata: { team: "rep-tools" /* RepTools */ }
93074
- },
93075
- runToolBatchUploadUrl: {
93076
- method: "POST",
93077
- path: "/tools/:tool_id/run-batch/upload-url",
93078
- pathParams: external_exports.object({
93079
- tool_id: external_exports.string()
93080
- }),
93081
- body: c2.noBody(),
93082
- responses: {
93083
- 200: BatchUploadUrlResponseSchema,
93084
- 401: errorResponseSchema,
93085
- 403: errorResponseSchema,
93086
- 404: errorResponseSchema,
93087
- 429: errorResponseSchema
93088
- },
93089
- summary: "Issue a presigned PUT URL for uploading a batch input JSONL",
93090
- description: "Creates a presigned URL for uploading a JSONL file used by a batch tool run.",
93091
- metadata: { team: "rep-tools" /* RepTools */ }
93092
- },
93093
- startToolRunBatch: {
93094
- method: "POST",
93095
- path: "/tools/:tool_id/run-batch/start",
93096
- pathParams: external_exports.object({
93097
- tool_id: external_exports.string()
93098
- }),
93099
- body: StartBatchRequestSchema,
93100
- responses: {
93101
- 202: StartBatchResponseSchema,
93102
- 400: errorResponseSchema,
93103
- 401: errorResponseSchema,
93104
- 403: errorResponseSchema,
93105
- 404: errorResponseSchema,
93106
- 429: errorResponseSchema
93107
- },
93108
- summary: "Start an async tool run-batch over an uploaded JSONL file",
93109
- description: "Starts an asynchronous batch tool run over a previously uploaded JSONL file.",
93110
- metadata: { team: "rep-tools" /* RepTools */ }
93111
- },
93112
- getToolRunBatchResults: {
93113
- method: "GET",
93114
- path: "/tools/run-batch/:tool_run_id/results",
93115
- pathParams: external_exports.object({
93116
- tool_run_id: external_exports.string()
93117
- }),
93118
- responses: {
93119
- 200: BatchResultsTerminalSchema,
93120
- 202: BatchResultsInProgressSchema,
93121
- 401: errorResponseSchema,
93122
- 404: errorResponseSchema,
93123
- 429: errorResponseSchema
93124
- },
93125
- summary: "Fetch progress and results for a batch run",
93126
- description: "Returns current status and results for an asynchronous batch tool run.",
93127
- metadata: { team: "rep-tools" /* RepTools */ }
93128
- }
92335
+ type: external_exports.literal("enrichment"),
92336
+ actionPackageId: external_exports.string(),
92337
+ actionKey: external_exports.string(),
92338
+ appAccountId: external_exports.string().nullable().optional()
92339
+ });
92340
+ var EnrichmentUpdateToolRequest = UpdateToolBase.extend({
92341
+ type: external_exports.literal("enrichment")
92342
+ });
92343
+ var EnrichmentCreateToolInput = external_exports.object({
92344
+ workspaceId: external_exports.number(),
92345
+ type: external_exports.literal("enrichment"),
92346
+ id: external_exports.string(),
92347
+ name: external_exports.string().max(100).nullable().optional(),
92348
+ description: external_exports.string().max(500).nullable().optional(),
92349
+ access: ToolAccess
92350
+ });
92351
+ var EnrichmentUpsertToolInput = UpsertToolBase.extend({
92352
+ type: external_exports.literal("enrichment"),
92353
+ workspaceId: external_exports.number(),
92354
+ id: external_exports.string()
92355
+ });
92356
+ var EnrichmentUpdateToolInput = EnrichmentUpdateToolRequest.extend({
92357
+ workspaceId: external_exports.number(),
92358
+ toolId: external_exports.string()
92359
+ });
92360
+ var WorkflowCreateToolRequest = CreateToolBase.extend({
92361
+ type: external_exports.literal("workflow"),
92362
+ id: external_exports.string(),
92363
+ name: CreateToolBase.shape.name.optional()
92364
+ });
92365
+ var WorkflowUpsertToolRequest = UpsertToolBase.extend({
92366
+ type: external_exports.literal("workflow"),
92367
+ id: external_exports.string()
92368
+ });
92369
+ var WorkflowUpdateToolRequest = UpdateToolBase.extend({
92370
+ type: external_exports.literal("workflow")
92371
+ });
92372
+ var WorkflowCreateToolInput = WorkflowCreateToolRequest.extend({
92373
+ workspaceId: external_exports.number()
92374
+ });
92375
+ var WorkflowUpsertToolInput = WorkflowUpsertToolRequest.extend({
92376
+ workspaceId: external_exports.number()
92377
+ });
92378
+ var WorkflowUpdateToolInput = WorkflowUpdateToolRequest.extend({
92379
+ workspaceId: external_exports.number(),
92380
+ toolId: external_exports.string()
93129
92381
  });
92382
+ var CreateToolInputSchema = external_exports.discriminatedUnion("type", [
92383
+ FunctionCreateToolInput,
92384
+ EnrichmentCreateToolInput,
92385
+ WorkflowCreateToolInput
92386
+ ]);
92387
+ var UpsertToolInputSchema = external_exports.discriminatedUnion("type", [
92388
+ FunctionUpsertToolInput,
92389
+ EnrichmentUpsertToolInput,
92390
+ WorkflowUpsertToolInput
92391
+ ]);
92392
+ var UpdateToolInputSchema = external_exports.discriminatedUnion("type", [
92393
+ FunctionUpdateToolInput,
92394
+ EnrichmentUpdateToolInput,
92395
+ WorkflowUpdateToolInput
92396
+ ]);
93130
92397
 
93131
92398
  // ../../libs/api-contract/src/tools/contract.ts
92399
+ var ToolRunProgressFieldsSchema = external_exports.object({
92400
+ tool_run_id: external_exports.string(),
92401
+ total: external_exports.number(),
92402
+ finished: external_exports.number()
92403
+ });
93132
92404
  var ToolAccess2 = external_exports.object({
93133
92405
  integrations: external_exports.array(ToolSurface).transform((arr) => [...new Set(arr)])
93134
92406
  });
@@ -93317,14 +92589,14 @@ var toolsContract = {
93317
92589
  }
93318
92590
  };
93319
92591
 
93320
- // src/commands/tools/integrations.ts
92592
+ // src/commands/routines/integrations.ts
93321
92593
  var TOOL_INTEGRATION_VALUES = ToolSurface.options;
93322
92594
  var TOOL_INTEGRATION_CSV = TOOL_INTEGRATION_VALUES.join(",");
93323
92595
  var TOOL_INTEGRATION_CLEAR_VALUE = "none";
93324
92596
  var TOOL_INTEGRATION_DESCRIPTIONS = {
93325
- api: "Public API and CLI tool execution.",
92597
+ api: "Public API and CLI routine execution.",
93326
92598
  mcp: "MCP clients such as ChatGPT.",
93327
- claygent: "Claygent tool selection."
92599
+ claygent: "Claygent routine selection."
93328
92600
  };
93329
92601
  var TOOL_INTEGRATION_VALUES_HELP = [
93330
92602
  "Integration values:",
@@ -93348,11 +92620,11 @@ function parseToolIntegrationCsv(value) {
93348
92620
  return parts.map(parseToolIntegration);
93349
92621
  }
93350
92622
 
93351
- // src/commands/tools/projection.ts
92623
+ // src/commands/routines/projection.ts
93352
92624
  function projectTool(tool) {
93353
92625
  if (tool.type !== "function" && tool.type !== "workflow") {
93354
92626
  throw new IncompatibleApiServerError(
93355
- `Clay API returned a tool of type "${tool.type}", which this CLI doesn't yet support. Please update the CLI.`
92627
+ `Clay API returned a routine of type "${tool.type}", which this CLI doesn't yet support. Please update the CLI.`
93356
92628
  );
93357
92629
  }
93358
92630
  return {
@@ -93366,10 +92638,10 @@ function projectTool(tool) {
93366
92638
  };
93367
92639
  }
93368
92640
 
93369
- // src/commands/tools/get.ts
92641
+ // src/commands/routines/get.ts
93370
92642
  function buildGetCommand() {
93371
92643
  const cmd = new Command("get");
93372
- cmd.description("Fetch a tool by id, with full config, integrations, and input schema.").argument("<toolId>", "Tool id, e.g. function:tbl_abc123 or workflow:wf_abc123").addHelpText(
92644
+ cmd.description("Fetch a routine by id, with full config, integrations, and input schema.").argument("<routineId>", "Routine id, e.g. function:tbl_abc123 or workflow:wf_abc123").addHelpText(
93373
92645
  "after",
93374
92646
  `
93375
92647
  Output (success, exit 0):
@@ -93383,38 +92655,47 @@ Output (success, exit 0):
93383
92655
  "inputSchema": <object|undefined>
93384
92656
  }
93385
92657
 
93386
- "entityType" is omitted for workflow tools.
92658
+ "entityType" is omitted for workflow routines.
93387
92659
 
93388
92660
  ${TOOL_INTEGRATION_VALUES_HELP}
93389
92661
 
93390
92662
  Common errors:
93391
- not_found (exit 6) No tool with that id in this workspace.
92663
+ not_found (exit 6) No routine with that id in this workspace.
93392
92664
  auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
93393
92665
 
93394
92666
  Examples:
93395
- $ clay tools get function:tbl_abc123
93396
- $ clay tools get workflow:wf_abc123
93397
- $ clay tools list | jq -r '.data[0].id' | xargs clay tools get
92667
+ $ clay routines get function:tbl_abc123
92668
+ $ clay routines get workflow:wf_abc123
92669
+ $ clay routines list | jq -r '.data[0].id' | xargs clay routines get
93398
92670
  `
93399
- ).action(async (toolId) => {
92671
+ ).action(async (routineId) => {
93400
92672
  const workspaceId = await currentWorkspaceId();
93401
92673
  const client = await v3Client(toolsContract);
93402
- const tool = await unwrap(client.getTool({ params: { workspaceId, toolId } }));
92674
+ const tool = await unwrap(client.getTool({ params: { workspaceId, toolId: routineId } }));
93403
92675
  writeJson(projectTool(tool));
93404
92676
  });
93405
92677
  return cmd;
93406
92678
  }
93407
92679
 
93408
- // src/commands/tools/list.ts
93409
- function buildListCommand3() {
92680
+ // src/commands/routines/list.ts
92681
+ var TOOL_TYPE_VALUES = ToolType.options.filter((value) => value !== "enrichment");
92682
+ var TOOL_TYPE_DESCRIPTIONS = {
92683
+ function: "Function-backed routines.",
92684
+ workflow: "Workflow-backed routines."
92685
+ };
92686
+ var TOOL_TYPE_VALUES_HELP = [
92687
+ "Routine type values:",
92688
+ ...TOOL_TYPE_VALUES.map((value) => ` ${value.padEnd(9)} ${TOOL_TYPE_DESCRIPTIONS[value]}`)
92689
+ ].join("\n");
92690
+ function buildListCommand2() {
93410
92691
  const cmd = new Command("list");
93411
- cmd.description("List tools in the workspace pinned to your API key \u2014 name + description only.").addOption(
93412
- new Option("--integration <name>", "Restrict to tools exposed on the given integration value.").choices([
92692
+ cmd.description("List routines in the workspace pinned to your API key \u2014 name + description only.").addOption(new Option("--type <type>", "Restrict to routines of the given type.").choices([...TOOL_TYPE_VALUES])).addOption(
92693
+ new Option("--integration <name>", "Restrict to routines exposed on the given integration value.").choices([
93413
92694
  ...TOOL_INTEGRATION_VALUES
93414
92695
  ])
93415
92696
  ).option(
93416
92697
  "--limit <n>",
93417
- `Max tools to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
92698
+ `Max routines to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
93418
92699
  parseLimitFlagWithMax(MAX_PAGE_LIMIT)
93419
92700
  ).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").addHelpText(
93420
92701
  "after",
@@ -93427,24 +92708,28 @@ Output (success, exit 0):
93427
92708
  "cursor": <string|undefined>
93428
92709
  }
93429
92710
 
92711
+ ${TOOL_TYPE_VALUES_HELP}
92712
+
93430
92713
  ${TOOL_INTEGRATION_VALUES_HELP}
93431
92714
 
93432
92715
  Pagination:
93433
- --limit <n> max tools per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
92716
+ --limit <n> max routines per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
93434
92717
  --cursor <token> resume from a previous response's \`cursor\`
93435
92718
  When more results exist, the response includes a top-level \`cursor\`; pass it back via
93436
92719
  --cursor to fetch the next page.
93437
92720
 
93438
92721
  Common errors:
93439
- validation_error (exit 2) --limit is not a positive integer or exceeds ${MAX_PAGE_LIMIT}.
92722
+ validation_error (exit 2) --limit is not a positive integer or exceeds ${MAX_PAGE_LIMIT}; --type or --integration is not one of the allowed values.
93440
92723
  auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
93441
92724
 
93442
92725
  Examples:
93443
- $ clay tools list
93444
- $ clay tools list --integration api
93445
- $ clay tools list --integration mcp
93446
- $ clay tools list --limit 10 | jq -r '.data[].id'
93447
- $ clay tools list --limit 10 --cursor "$CURSOR"
92726
+ $ clay routines list
92727
+ $ clay routines list --type function
92728
+ $ clay routines list --integration api
92729
+ $ clay routines list --integration mcp
92730
+ $ clay routines list --type workflow --integration mcp
92731
+ $ clay routines list --limit 10 | jq -r '.data[].id'
92732
+ $ clay routines list --limit 10 --cursor "$CURSOR"
93448
92733
  `
93449
92734
  ).action(async (opts) => {
93450
92735
  const workspaceId = await currentWorkspaceId();
@@ -93454,6 +92739,7 @@ Examples:
93454
92739
  params: { workspaceId },
93455
92740
  query: {
93456
92741
  integration: opts.integration,
92742
+ toolType: opts.type,
93457
92743
  cursor: opts.cursor,
93458
92744
  limit: opts.limit ?? DEFAULT_PAGE_LIMIT
93459
92745
  }
@@ -93471,6 +92757,191 @@ Examples:
93471
92757
  return cmd;
93472
92758
  }
93473
92759
 
92760
+ // ../../libs/api-contract/src/public-api-v0/routines-contract.ts
92761
+ var c = initContract();
92762
+ var MAX_ID_LENGTH = 64;
92763
+ var RunRoutineItemSchema = external_exports.object({
92764
+ id: external_exports.string().min(1).max(MAX_ID_LENGTH),
92765
+ inputs: external_exports.record(external_exports.unknown())
92766
+ });
92767
+ var MAX_RUN_ITEMS = 100;
92768
+ var WEBHOOK_ID_DESCRIPTION = "ID of a registered Clay webhook to notify when the run finishes.";
92769
+ var RunRoutineRequestSchema = external_exports.object({
92770
+ items: external_exports.array(RunRoutineItemSchema).min(1).max(MAX_RUN_ITEMS),
92771
+ webhook_id: external_exports.string().min(1).max(MAX_ID_LENGTH).optional().describe(WEBHOOK_ID_DESCRIPTION)
92772
+ });
92773
+ var RunRoutineResponseSchema = external_exports.object({
92774
+ routine_run_id: external_exports.string(),
92775
+ status: external_exports.literal("in_progress")
92776
+ });
92777
+ var RunResultItemSchema = external_exports.object({
92778
+ id: external_exports.string(),
92779
+ status: external_exports.enum(["complete", "failed"]),
92780
+ result: external_exports.record(external_exports.unknown()).optional(),
92781
+ error: external_exports.object({ message: external_exports.string() }).optional()
92782
+ });
92783
+ var RoutineRunProgressFieldsSchema = external_exports.object({
92784
+ routine_run_id: external_exports.string(),
92785
+ total: external_exports.number(),
92786
+ finished: external_exports.number()
92787
+ });
92788
+ var RunResultsInProgressSchema = RoutineRunProgressFieldsSchema.extend({
92789
+ status: external_exports.literal("in_progress")
92790
+ });
92791
+ var RunResultsCompleteSchema = RoutineRunProgressFieldsSchema.extend({
92792
+ status: external_exports.literal("complete"),
92793
+ data: external_exports.array(RunResultItemSchema),
92794
+ cursor: external_exports.string().optional()
92795
+ });
92796
+ var RunResultsResponseSchema = external_exports.discriminatedUnion("status", [
92797
+ RunResultsInProgressSchema,
92798
+ RunResultsCompleteSchema
92799
+ ]);
92800
+ var BatchUploadUrlResponseSchema = external_exports.object({
92801
+ upload_url: external_exports.string().url(),
92802
+ file_id: external_exports.string()
92803
+ });
92804
+ var StartBatchRequestSchema = external_exports.object({
92805
+ file_id: external_exports.string(),
92806
+ webhook_id: external_exports.string().min(1).max(MAX_ID_LENGTH).optional().describe(WEBHOOK_ID_DESCRIPTION)
92807
+ });
92808
+ var StartBatchResponseSchema = external_exports.object({
92809
+ routine_run_id: external_exports.string(),
92810
+ status: external_exports.literal("in_progress")
92811
+ });
92812
+ var BatchResultsInProgressSchema = RoutineRunProgressFieldsSchema.extend({
92813
+ status: external_exports.literal("in_progress")
92814
+ });
92815
+ var BatchValidationErrorDetailSchema = external_exports.object({
92816
+ line_number: external_exports.number(),
92817
+ field: external_exports.string(),
92818
+ message: external_exports.string()
92819
+ });
92820
+ var BatchValidationErrorSchema = external_exports.object({
92821
+ message: external_exports.string(),
92822
+ total_invalid_rows: external_exports.number(),
92823
+ details: external_exports.array(BatchValidationErrorDetailSchema).max(100)
92824
+ });
92825
+ var BatchResultsValidationFailedSchema = external_exports.object({
92826
+ routine_run_id: external_exports.string(),
92827
+ status: external_exports.literal("validation_failed"),
92828
+ error: BatchValidationErrorSchema
92829
+ });
92830
+ var BatchResultsCompleteSchema = RoutineRunProgressFieldsSchema.extend({
92831
+ status: external_exports.literal("complete"),
92832
+ result_url: external_exports.string().url()
92833
+ });
92834
+ var BatchResultsTerminalSchema = external_exports.discriminatedUnion("status", [
92835
+ BatchResultsValidationFailedSchema,
92836
+ BatchResultsCompleteSchema
92837
+ ]);
92838
+ var runRoutineRoute = {
92839
+ method: "POST",
92840
+ pathParams: external_exports.object({
92841
+ routine_id: external_exports.string()
92842
+ }),
92843
+ body: RunRoutineRequestSchema,
92844
+ responses: {
92845
+ 202: RunRoutineResponseSchema,
92846
+ 400: errorResponseSchema,
92847
+ 401: errorResponseSchema,
92848
+ 403: errorResponseSchema,
92849
+ 404: errorResponseSchema,
92850
+ 429: errorResponseSchema
92851
+ },
92852
+ summary: "Execute a routine against 1-100 items",
92853
+ description: "Starts an asynchronous routine run for up to 100 input items.",
92854
+ metadata: { team: "rep-tools" /* RepTools */ }
92855
+ };
92856
+ var getRunResultsRoute = {
92857
+ method: "GET",
92858
+ pathParams: external_exports.object({
92859
+ routine_run_id: external_exports.string()
92860
+ }),
92861
+ query: paginatedQuerySchema(),
92862
+ responses: {
92863
+ 200: RunResultsCompleteSchema,
92864
+ 202: RunResultsInProgressSchema,
92865
+ 401: errorResponseSchema,
92866
+ 404: errorResponseSchema,
92867
+ 429: errorResponseSchema
92868
+ },
92869
+ summary: "Fetch progress and results for a routine run",
92870
+ description: "Returns current status and paginated results for an asynchronous routine run.",
92871
+ metadata: { team: "rep-tools" /* RepTools */ }
92872
+ };
92873
+ var runRoutineBatchUploadUrlRoute = {
92874
+ method: "POST",
92875
+ pathParams: external_exports.object({
92876
+ routine_id: external_exports.string()
92877
+ }),
92878
+ body: c.noBody(),
92879
+ responses: {
92880
+ 200: BatchUploadUrlResponseSchema,
92881
+ 401: errorResponseSchema,
92882
+ 403: errorResponseSchema,
92883
+ 404: errorResponseSchema,
92884
+ 429: errorResponseSchema
92885
+ },
92886
+ summary: "Issue a presigned PUT URL for uploading a batch input JSONL",
92887
+ description: "Creates a presigned URL for uploading a JSONL file used by a batch routine run.",
92888
+ metadata: { team: "rep-tools" /* RepTools */ }
92889
+ };
92890
+ var startRoutineRunBatchRoute = {
92891
+ method: "POST",
92892
+ pathParams: external_exports.object({
92893
+ routine_id: external_exports.string()
92894
+ }),
92895
+ body: StartBatchRequestSchema,
92896
+ responses: {
92897
+ 202: StartBatchResponseSchema,
92898
+ 400: errorResponseSchema,
92899
+ 401: errorResponseSchema,
92900
+ 403: errorResponseSchema,
92901
+ 404: errorResponseSchema,
92902
+ 429: errorResponseSchema
92903
+ },
92904
+ summary: "Start an async routine run-batch over an uploaded JSONL file",
92905
+ description: "Starts an asynchronous batch routine run over a previously uploaded JSONL file.",
92906
+ metadata: { team: "rep-tools" /* RepTools */ }
92907
+ };
92908
+ var getRoutineRunBatchResultsRoute = {
92909
+ method: "GET",
92910
+ pathParams: external_exports.object({
92911
+ routine_run_id: external_exports.string()
92912
+ }),
92913
+ responses: {
92914
+ 200: BatchResultsTerminalSchema,
92915
+ 202: BatchResultsInProgressSchema,
92916
+ 401: errorResponseSchema,
92917
+ 404: errorResponseSchema,
92918
+ 429: errorResponseSchema
92919
+ },
92920
+ summary: "Fetch progress and results for a batch run",
92921
+ description: "Returns current status and results for an asynchronous batch routine run.",
92922
+ metadata: { team: "rep-tools" /* RepTools */ }
92923
+ };
92924
+ var publicApiRoutinesContract = c.router({
92925
+ runRoutine: { ...runRoutineRoute, path: "/routines/:routine_id/run" },
92926
+ getRunResults: { ...getRunResultsRoute, path: "/routines/run/:routine_run_id/results" },
92927
+ runRoutineBatchUploadUrl: { ...runRoutineBatchUploadUrlRoute, path: "/routines/:routine_id/run-batch/upload-url" },
92928
+ startRoutineRunBatch: { ...startRoutineRunBatchRoute, path: "/routines/:routine_id/run-batch/start" },
92929
+ getRoutineRunBatchResults: {
92930
+ ...getRoutineRunBatchResultsRoute,
92931
+ path: "/routines/run-batch/:routine_run_id/results"
92932
+ }
92933
+ });
92934
+ var publicApiLegacyToolsContract = c.router({
92935
+ runRoutine: { ...runRoutineRoute, path: "/tools/:routine_id/run" },
92936
+ getRunResults: { ...getRunResultsRoute, path: "/tools/run/:routine_run_id/results" },
92937
+ runRoutineBatchUploadUrl: { ...runRoutineBatchUploadUrlRoute, path: "/tools/:routine_id/run-batch/upload-url" },
92938
+ startRoutineRunBatch: { ...startRoutineRunBatchRoute, path: "/tools/:routine_id/run-batch/start" },
92939
+ getRoutineRunBatchResults: {
92940
+ ...getRoutineRunBatchResultsRoute,
92941
+ path: "/tools/run-batch/:routine_run_id/results"
92942
+ }
92943
+ });
92944
+
93474
92945
  // src/commands/pagination.ts
93475
92946
  var MAX_AUTO_PAGINATE_ITEMS = 1e4;
93476
92947
  var MAX_AUTO_PAGINATE_PAGES = 500;
@@ -93481,555 +92952,1147 @@ var CursorPager = class {
93481
92952
  get cursor() {
93482
92953
  return this.currentCursor;
93483
92954
  }
93484
- advance(nextCursor, pageItemCount) {
93485
- if (nextCursor === this.currentCursor) {
93486
- throw new IncompatibleApiServerError(
93487
- "Clay API returned the same pagination cursor twice in a row; aborting auto-pagination."
93488
- );
93489
- }
93490
- this.itemsFetched += pageItemCount;
93491
- this.pagesFetched += 1;
93492
- if (this.itemsFetched >= MAX_AUTO_PAGINATE_ITEMS) {
93493
- throw new IncompatibleApiServerError(
93494
- `Auto-pagination stopped after ${MAX_AUTO_PAGINATE_ITEMS} items without reaching the end of the result set; narrow the request to fetch fewer rows.`
93495
- );
93496
- }
93497
- if (this.pagesFetched >= MAX_AUTO_PAGINATE_PAGES) {
93498
- throw new IncompatibleApiServerError(
93499
- `Clay API returned ${MAX_AUTO_PAGINATE_PAGES} pages without reaching the end of the result set; aborting auto-pagination.`
93500
- );
92955
+ advance(nextCursor, pageItemCount) {
92956
+ if (nextCursor === this.currentCursor) {
92957
+ throw new IncompatibleApiServerError(
92958
+ "Clay API returned the same pagination cursor twice in a row; aborting auto-pagination."
92959
+ );
92960
+ }
92961
+ this.itemsFetched += pageItemCount;
92962
+ this.pagesFetched += 1;
92963
+ if (this.itemsFetched >= MAX_AUTO_PAGINATE_ITEMS) {
92964
+ throw new IncompatibleApiServerError(
92965
+ `Auto-pagination stopped after ${MAX_AUTO_PAGINATE_ITEMS} items without reaching the end of the result set; narrow the request to fetch fewer rows.`
92966
+ );
92967
+ }
92968
+ if (this.pagesFetched >= MAX_AUTO_PAGINATE_PAGES) {
92969
+ throw new IncompatibleApiServerError(
92970
+ `Clay API returned ${MAX_AUTO_PAGINATE_PAGES} pages without reaching the end of the result set; aborting auto-pagination.`
92971
+ );
92972
+ }
92973
+ this.currentCursor = nextCursor;
92974
+ }
92975
+ };
92976
+
92977
+ // src/commands/routines/runs/projection.ts
92978
+ function projectInlineStart(response) {
92979
+ return {
92980
+ routineRunId: response.routine_run_id,
92981
+ mode: "inline",
92982
+ status: response.status
92983
+ };
92984
+ }
92985
+ function projectRunListItem(response) {
92986
+ return {
92987
+ routineRunId: response.tool_run_id,
92988
+ routineId: response.tool_id,
92989
+ status: response.status,
92990
+ total: response.total,
92991
+ finished: response.finished
92992
+ };
92993
+ }
92994
+ function projectBulkStart(response, fileId) {
92995
+ return {
92996
+ routineRunId: response.routine_run_id,
92997
+ mode: "bulk",
92998
+ status: response.status,
92999
+ fileId
93000
+ };
93001
+ }
93002
+ function projectInlineResults(response) {
93003
+ const base = {
93004
+ routineRunId: response.routine_run_id,
93005
+ mode: "inline",
93006
+ total: response.total,
93007
+ finished: response.finished
93008
+ };
93009
+ if (response.status === "in_progress") {
93010
+ return {
93011
+ ...base,
93012
+ status: "in_progress"
93013
+ };
93014
+ }
93015
+ return {
93016
+ ...base,
93017
+ status: "complete",
93018
+ data: response.data.map((item) => ({
93019
+ id: item.id,
93020
+ status: item.status,
93021
+ ...item.result !== void 0 ? { result: item.result } : {},
93022
+ ...item.error !== void 0 ? { error: item.error } : {}
93023
+ })),
93024
+ ...response.cursor !== void 0 ? { cursor: response.cursor } : {}
93025
+ };
93026
+ }
93027
+ function projectBulkResults(response) {
93028
+ const base = {
93029
+ routineRunId: response.routine_run_id,
93030
+ mode: "bulk"
93031
+ };
93032
+ if (response.status === "in_progress") {
93033
+ return {
93034
+ ...base,
93035
+ status: "in_progress",
93036
+ total: response.total,
93037
+ finished: response.finished
93038
+ };
93039
+ }
93040
+ if (response.status === "complete") {
93041
+ return {
93042
+ ...base,
93043
+ status: "complete",
93044
+ total: response.total,
93045
+ finished: response.finished,
93046
+ resultUrl: response.result_url
93047
+ };
93048
+ }
93049
+ return {
93050
+ ...base,
93051
+ status: "validation_failed",
93052
+ error: {
93053
+ message: response.error.message,
93054
+ totalInvalidRows: response.error.total_invalid_rows,
93055
+ details: response.error.details.map((detail) => ({
93056
+ lineNumber: detail.line_number,
93057
+ field: detail.field,
93058
+ message: detail.message
93059
+ }))
93060
+ }
93061
+ };
93062
+ }
93063
+
93064
+ // src/commands/routines/runs/get.ts
93065
+ function buildGetCommand2() {
93066
+ const cmd = new Command("get");
93067
+ cmd.description("Fetch status and results for an inline or bulk routine run.").argument("<routineRunId>", "Routine run id, e.g. run_abc123").option(
93068
+ "--limit <n>",
93069
+ "Cap the number of inline results returned. By default the command auto-paginates and returns all results.",
93070
+ parseLimitFlag
93071
+ ).addHelpText(
93072
+ "after",
93073
+ `
93074
+ Output (success, exit 0):
93075
+ Inline in progress:
93076
+ { "routineRunId": <string>, "mode": "inline", "status": "in_progress", "total": <number>, "finished": <number> }
93077
+
93078
+ Inline complete:
93079
+ { "routineRunId": <string>, "mode": "inline", "status": "complete", "total": <number>, "finished": <number>, "data": [ ... ] }
93080
+
93081
+ Bulk in progress:
93082
+ { "routineRunId": <string>, "mode": "bulk", "status": "in_progress", "total": <number>, "finished": <number> }
93083
+
93084
+ Bulk complete:
93085
+ { "routineRunId": <string>, "mode": "bulk", "status": "complete", "total": <number>, "finished": <number>, "resultUrl": <string> }
93086
+
93087
+ Bulk validation failed:
93088
+ { "routineRunId": <string>, "mode": "bulk", "status": "validation_failed", "error": { "message": <string>, "totalInvalidRows": <number>, "details": [{ "lineNumber": <number>, "field": <string>, "message": <string> }] } }
93089
+
93090
+ Common errors:
93091
+ not_found (exit 6) No inline or bulk run with that id.
93092
+
93093
+ Examples:
93094
+ $ clay routines runs get run_abc | jq -r '.status'
93095
+ $ clay routines runs get run_abc | jq -r '.mode'
93096
+ $ clay routines runs get run_abc --limit 10 | jq '.data | length'
93097
+ `
93098
+ ).action(async (routineRunId, opts) => {
93099
+ const client = await publicApiClient(publicApiRoutinesContract);
93100
+ const accumulated = [];
93101
+ let lastComplete;
93102
+ const pager = new CursorPager();
93103
+ let inlineNotFound = false;
93104
+ for (; ; ) {
93105
+ const remaining = opts.limit === void 0 ? MAX_PAGE_LIMIT : opts.limit - accumulated.length;
93106
+ const pageSize = Math.min(MAX_PAGE_LIMIT, remaining);
93107
+ const inline = await client.getRunResults({
93108
+ params: { routine_run_id: routineRunId },
93109
+ query: { ...pager.cursor !== void 0 ? { cursor: pager.cursor } : {}, limit: pageSize }
93110
+ });
93111
+ if (inline.status === 404) {
93112
+ if (accumulated.length > 0) {
93113
+ throw toHttpStatusError(inline);
93114
+ }
93115
+ inlineNotFound = true;
93116
+ break;
93117
+ }
93118
+ if (inline.status === 202) {
93119
+ writeJson(projectInlineResults(inline.body));
93120
+ return;
93121
+ }
93122
+ if (inline.status !== 200) {
93123
+ throw toHttpStatusError(inline);
93124
+ }
93125
+ lastComplete = inline.body;
93126
+ accumulated.push(...inline.body.data);
93127
+ if (inline.body.cursor === void 0) break;
93128
+ if (opts.limit !== void 0 && accumulated.length >= opts.limit) break;
93129
+ pager.advance(inline.body.cursor, inline.body.data.length);
93130
+ }
93131
+ if (!inlineNotFound) {
93132
+ if (lastComplete === void 0) {
93133
+ throw new IncompatibleApiServerError(
93134
+ "Clay API /public/v0/routines/run/:id/results returned no complete page before pagination ended."
93135
+ );
93136
+ }
93137
+ const trimmed = opts.limit === void 0 ? accumulated : accumulated.slice(0, opts.limit);
93138
+ writeJson(projectInlineResults({ ...lastComplete, data: trimmed, cursor: void 0 }));
93139
+ return;
93140
+ }
93141
+ const bulk = await client.getRoutineRunBatchResults({ params: { routine_run_id: routineRunId } });
93142
+ if (bulk.status === 200 || bulk.status === 202) {
93143
+ writeJson(projectBulkResults(bulk.body));
93144
+ return;
93145
+ }
93146
+ throw toHttpStatusError(bulk);
93147
+ });
93148
+ return cmd;
93149
+ }
93150
+
93151
+ // src/commands/routines/runs/list.ts
93152
+ function buildListCommand3() {
93153
+ const cmd = new Command("list");
93154
+ cmd.description("List recent async routine runs and their statuses.").option(
93155
+ "--limit <n>",
93156
+ `Max runs to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
93157
+ parseLimitFlagWithMax(MAX_PAGE_LIMIT)
93158
+ ).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").addHelpText(
93159
+ "after",
93160
+ `
93161
+ Output (success, exit 0):
93162
+ {
93163
+ "data": [
93164
+ {
93165
+ "routineRunId": <string>,
93166
+ "routineId": <string>,
93167
+ "status": "in_progress" | "complete" | "validation_failed",
93168
+ "total": <number>,
93169
+ "finished": <number>
93170
+ }
93171
+ ],
93172
+ "cursor": <string|undefined>
93173
+ }
93174
+
93175
+ Pagination:
93176
+ --limit <n> max runs per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
93177
+ --cursor <token> resume from a previous response's \`cursor\`
93178
+ When more results exist, the response includes a top-level \`cursor\`; pass it back via
93179
+ --cursor to fetch the next page.
93180
+
93181
+ Common errors:
93182
+ validation_error (exit 2) --limit is not a positive integer or exceeds ${MAX_PAGE_LIMIT}.
93183
+ auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
93184
+
93185
+ Examples:
93186
+ $ clay routines runs list
93187
+ $ clay routines runs list --limit 10 | jq -r '.data[].routineRunId'
93188
+ $ clay routines runs list --limit 10 --cursor "$CURSOR"
93189
+ $ clay routines runs list | jq '.data[] | select(.status == "in_progress")'
93190
+ `
93191
+ ).action(async (opts) => {
93192
+ const workspaceId = await currentWorkspaceId();
93193
+ const client = await v3Client(toolsContract);
93194
+ const result = await unwrap(
93195
+ client.listToolRuns({
93196
+ params: { workspaceId },
93197
+ query: {
93198
+ cursor: opts.cursor,
93199
+ limit: opts.limit ?? DEFAULT_PAGE_LIMIT
93200
+ }
93201
+ })
93202
+ );
93203
+ writeJson({
93204
+ data: result.data.map(projectRunListItem),
93205
+ cursor: result.cursor
93206
+ });
93207
+ });
93208
+ return cmd;
93209
+ }
93210
+
93211
+ // src/commands/routines/runs/input.ts
93212
+ var import_node_fs11 = require("fs");
93213
+ function readRunRoutineRequest(source) {
93214
+ const raw = readUtf8Source("--input", source);
93215
+ let parsed;
93216
+ try {
93217
+ parsed = JSON.parse(raw);
93218
+ } catch (err) {
93219
+ throw new InvalidArgumentError(`--input: not valid JSON (${err.message})`);
93220
+ }
93221
+ const request2 = RunRoutineRequestSchema.pick({ items: true }).safeParse(parsed);
93222
+ if (!request2.success) {
93223
+ const issue = request2.error.issues[0];
93224
+ const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
93225
+ const message = issue === void 0 ? "invalid shape" : issue.message;
93226
+ throw new InvalidArgumentError(
93227
+ `--input: must match { "items": [{ "id": <string>, "inputs": <object> }] }${path7}: ${message}`
93228
+ );
93229
+ }
93230
+ return request2.data;
93231
+ }
93232
+ function readJsonlFile(source) {
93233
+ let buf;
93234
+ try {
93235
+ buf = (0, import_node_fs11.readFileSync)(source);
93236
+ } catch (err) {
93237
+ throw new InvalidArgumentError(`--bulk: could not read ${source} (${err.message})`);
93238
+ }
93239
+ validateJsonl(buf);
93240
+ return buf;
93241
+ }
93242
+ function validateJsonl(buf) {
93243
+ const text = buf.toString("utf8");
93244
+ const lines = text.split("\n");
93245
+ let parsedRows = 0;
93246
+ for (let i = 0; i < lines.length; i++) {
93247
+ const trimmed = (lines[i] ?? "").trim();
93248
+ if (trimmed === "") continue;
93249
+ const lineNumber = i + 1;
93250
+ let parsed;
93251
+ try {
93252
+ parsed = JSON.parse(trimmed);
93253
+ } catch (err) {
93254
+ throw new InvalidArgumentError(
93255
+ `--bulk: line ${String(lineNumber)} is not valid JSON (${err.message})`
93256
+ );
93257
+ }
93258
+ const result = RunRoutineItemSchema.safeParse(parsed);
93259
+ if (!result.success) {
93260
+ const issue = result.error.issues[0];
93261
+ const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
93262
+ const message = issue === void 0 ? "invalid shape" : issue.message;
93263
+ throw new InvalidArgumentError(
93264
+ `--bulk: line ${String(lineNumber)} must match { "id": <string>, "inputs": <object> }${path7}: ${message}`
93265
+ );
93266
+ }
93267
+ parsedRows++;
93268
+ }
93269
+ if (parsedRows === 0) {
93270
+ throw new InvalidArgumentError("--bulk: file is empty (no JSON lines found)");
93271
+ }
93272
+ }
93273
+ function readUtf8Source(flagName, source) {
93274
+ const display = source === "-" ? "stdin" : source;
93275
+ if (isInlineJson(source)) {
93276
+ return source;
93277
+ }
93278
+ try {
93279
+ return source === "-" ? (0, import_node_fs11.readFileSync)(0, "utf8") : (0, import_node_fs11.readFileSync)(source, "utf8");
93280
+ } catch (err) {
93281
+ throw new InvalidArgumentError(`${flagName}: could not read ${display} (${err.message})`);
93282
+ }
93283
+ }
93284
+
93285
+ // src/commands/routines/runs/start.ts
93286
+ function buildStartCommand() {
93287
+ const cmd = new Command("start");
93288
+ cmd.description(
93289
+ "Start an async routine run through the API & CLI integration. Returns immediately; this command does not poll or wait."
93290
+ ).argument("<routineId>", "Routine id, e.g. function:tbl_abc123").option("--input <json|file|->", "Run body JSON: inline JSON, a file path, or - to read from stdin.").option("--bulk <file.jsonl>", 'Batch run input JSONL file. Each line is { "id": <string>, "inputs": <object> }.').option("--webhook-id <id>", "Registered webhook id (wh_...) to notify when the run finishes.").addHelpText(
93291
+ "after",
93292
+ `
93293
+ Output (success, exit 0):
93294
+ Inline:
93295
+ { "routineRunId": <string>, "mode": "inline", "status": "in_progress" }
93296
+
93297
+ Bulk:
93298
+ { "routineRunId": <string>, "mode": "bulk", "status": "in_progress", "fileId": <string> }
93299
+
93300
+ --input values:
93301
+ { "items": [{ "id": <string>, "inputs": <object> }] }
93302
+ items requires 1 to 100 entries; for larger batches use --bulk.
93303
+
93304
+ Common errors:
93305
+ validation_error (exit 2) Missing/conflicting input flags, unreadable file, invalid JSON body, or a JSONL row that fails the { "id": <string>, "inputs": <object> } shape (error names the line number).
93306
+ not_found (exit 6) No routine with that id in this workspace, or the routine is not enabled for API & CLI.
93307
+ auth_forbidden (exit 3) Key lacks access to run this routine through API & CLI.
93308
+ server_error (exit 1) Bulk input upload to storage failed; safe to retry the command.
93309
+
93310
+ Examples:
93311
+ $ clay routines update function:tbl_x --integrations api
93312
+ $ cat input.json | clay routines runs start function:tbl_x --input -
93313
+ $ clay routines runs start function:tbl_x --input '{"items":[{"id":"r1","inputs":{}}]}' | jq -r '.routineRunId'
93314
+ $ clay routines runs start function:tbl_x --input input.json | jq -r '.routineRunId'
93315
+ $ clay routines runs start function:tbl_x --input input.json --webhook-id wh_abc123 | jq -r '.routineRunId'
93316
+ $ clay routines runs start function:tbl_x --bulk rows.jsonl
93317
+ $ clay routines runs start function:tbl_x --bulk rows.jsonl --webhook-id wh_abc123
93318
+ `
93319
+ ).action(async (routineId, opts) => {
93320
+ const hasInput = opts.input !== void 0;
93321
+ const hasBulk = opts.bulk !== void 0;
93322
+ if (hasInput === hasBulk) {
93323
+ throw new InvalidArgumentError("exactly one of --input or --bulk is required");
93324
+ }
93325
+ const client = await publicApiClient(publicApiRoutinesContract);
93326
+ if (opts.input !== void 0) {
93327
+ const body2 = readRunRoutineRequest(opts.input);
93328
+ body2.webhook_id = opts.webhookId;
93329
+ const response2 = await unwrap(client.runRoutine({ params: { routine_id: routineId }, body: body2 }));
93330
+ writeJson(projectInlineStart(response2));
93331
+ return;
93332
+ }
93333
+ if (opts.bulk === void 0) {
93334
+ throw new InvalidArgumentError("exactly one of --input or --bulk is required");
93335
+ }
93336
+ const body = readJsonlFile(opts.bulk);
93337
+ const upload = await unwrap(client.runRoutineBatchUploadUrl({ params: { routine_id: routineId } }));
93338
+ await uploadJsonl(upload.upload_url, body);
93339
+ const response = await unwrap(
93340
+ client.startRoutineRunBatch({
93341
+ params: { routine_id: routineId },
93342
+ body: { file_id: upload.file_id, webhook_id: opts.webhookId }
93343
+ })
93344
+ );
93345
+ writeJson(projectBulkStart(response, upload.file_id));
93346
+ });
93347
+ return cmd;
93348
+ }
93349
+ async function uploadJsonl(uploadUrl, body) {
93350
+ const response = await fetchWithTimeout(
93351
+ uploadUrl,
93352
+ {
93353
+ method: "PUT",
93354
+ headers: { "content-type": "application/x-ndjson" },
93355
+ body: Uint8Array.from(body)
93356
+ },
93357
+ uploadTimeoutMs()
93358
+ );
93359
+ if (response.ok) return;
93360
+ throw new UploadFailedError(`Bulk input upload to storage failed: ${await uploadFailureMessage(response)}`);
93361
+ }
93362
+ async function uploadFailureMessage(response) {
93363
+ let text = "";
93364
+ try {
93365
+ text = await response.text();
93366
+ } catch {
93367
+ return `HTTP ${String(response.status)}`;
93368
+ }
93369
+ if (text.length === 0) {
93370
+ return `HTTP ${String(response.status)}`;
93371
+ }
93372
+ try {
93373
+ const parsed = JSON.parse(text);
93374
+ if (typeof parsed === "object" && parsed !== null && "message" in parsed) {
93375
+ const message = parsed.message;
93376
+ if (typeof message === "string" && message.length > 0) return message;
93501
93377
  }
93502
- this.currentCursor = nextCursor;
93378
+ } catch {
93379
+ return `HTTP ${String(response.status)}: ${text.slice(0, 200)}`;
93503
93380
  }
93504
- };
93505
-
93506
- // src/commands/tools/runs/projection.ts
93507
- function projectInlineStart(response) {
93508
- return {
93509
- toolRunId: response.tool_run_id,
93510
- mode: "inline",
93511
- status: response.status
93512
- };
93513
- }
93514
- function projectRunListItem(response) {
93515
- return {
93516
- toolRunId: response.tool_run_id,
93517
- toolId: response.tool_id,
93518
- status: response.status,
93519
- total: response.total,
93520
- finished: response.finished
93521
- };
93381
+ return `HTTP ${String(response.status)}: ${text.slice(0, 200)}`;
93522
93382
  }
93523
- function projectBulkStart(response, fileId) {
93524
- return {
93525
- toolRunId: response.tool_run_id,
93526
- mode: "bulk",
93527
- status: response.status,
93528
- fileId
93529
- };
93383
+
93384
+ // src/commands/routines/runs/index.ts
93385
+ function buildRunsCommand() {
93386
+ const cmd = new Command("runs");
93387
+ cmd.description("Start async routine runs and fetch run status/results.").addHelpText(
93388
+ "after",
93389
+ `
93390
+ Subcommands:
93391
+ list List recent async routine runs and their statuses.
93392
+ start Start an inline or bulk async routine run.
93393
+ get Fetch status/results for an inline or bulk run.
93394
+
93395
+ Examples:
93396
+ $ clay routines runs list
93397
+ $ cat input.json | clay routines runs start function:tbl_x --input -
93398
+ $ clay routines runs start function:tbl_x --bulk rows.jsonl
93399
+ $ clay routines runs get run_abc | jq -r '.status'
93400
+ `
93401
+ );
93402
+ cmd.addCommand(applyClaySettings(buildListCommand3()));
93403
+ cmd.addCommand(applyClaySettings(buildStartCommand()));
93404
+ cmd.addCommand(applyClaySettings(buildGetCommand2()));
93405
+ return cmd;
93530
93406
  }
93531
- function projectInlineResults(response) {
93532
- const base = {
93533
- toolRunId: response.tool_run_id,
93534
- mode: "inline",
93535
- total: response.total,
93536
- finished: response.finished
93537
- };
93538
- if (response.status === "in_progress") {
93539
- return {
93540
- ...base,
93541
- status: "in_progress"
93542
- };
93543
- }
93544
- return {
93545
- ...base,
93546
- status: "complete",
93547
- data: response.data.map((item) => ({
93548
- id: item.id,
93549
- status: item.status,
93550
- ...item.result !== void 0 ? { result: item.result } : {},
93551
- ...item.error !== void 0 ? { error: item.error } : {}
93552
- })),
93553
- ...response.cursor !== void 0 ? { cursor: response.cursor } : {}
93554
- };
93407
+
93408
+ // src/commands/routines/update.ts
93409
+ function parseEntityType(value) {
93410
+ if (value === "contact" || value === "company") return value;
93411
+ throw new InvalidArgumentError("entity-type must be contact or company");
93555
93412
  }
93556
- function projectBulkResults(response) {
93557
- const base = {
93558
- toolRunId: response.tool_run_id,
93559
- mode: "bulk"
93560
- };
93561
- if (response.status === "in_progress") {
93562
- return {
93563
- ...base,
93564
- status: "in_progress",
93565
- total: response.total,
93566
- finished: response.finished
93567
- };
93568
- }
93569
- if (response.status === "complete") {
93570
- return {
93571
- ...base,
93572
- status: "complete",
93573
- total: response.total,
93574
- finished: response.finished,
93575
- resultUrl: response.result_url
93576
- };
93413
+ function parseToolType(value) {
93414
+ try {
93415
+ return parseToolId(value).toolType;
93416
+ } catch {
93417
+ throw new InvalidArgumentError("tool id is in an invalid format");
93577
93418
  }
93578
- return {
93579
- ...base,
93580
- status: "validation_failed",
93581
- error: {
93582
- message: response.error.message,
93583
- totalInvalidRows: response.error.total_invalid_rows,
93584
- details: response.error.details.map((detail) => ({
93585
- lineNumber: detail.line_number,
93586
- field: detail.field,
93587
- message: detail.message
93588
- }))
93589
- }
93590
- };
93591
93419
  }
93592
-
93593
- // src/commands/tools/runs/get.ts
93594
- function buildGetCommand2() {
93595
- const cmd = new Command("get");
93596
- cmd.description("Fetch status and results for an inline or bulk tool run.").argument("<toolRunId>", "Tool run id, e.g. run_abc123").option(
93597
- "--limit <n>",
93598
- "Cap the number of inline results returned. By default the command auto-paginates and returns all results.",
93599
- parseLimitFlag
93420
+ function buildUpdateCommand2() {
93421
+ const cmd = new Command("update");
93422
+ cmd.description("Update a routine \u2014 name, description, integrations, or entity-type.").argument("<routineId>", "Routine id, e.g. function:tbl_abc123 or workflow:wf_abc123").option("--name <name>", "Set the routine name (max 100 chars).").option("--description <description>", "Set the description. Pass an empty string to clear it.").option(
93423
+ "--entity-type <type>",
93424
+ "Set the MCP entity type: contact or company. Not valid for workflow routines",
93425
+ parseEntityType
93426
+ ).option(
93427
+ "--integrations <csv>",
93428
+ `Override all existing integrations. Pass comma-separated values (${TOOL_INTEGRATION_CSV}) or ${TOOL_INTEGRATION_CLEAR_VALUE} to clear.`,
93429
+ parseToolIntegrationCsv
93600
93430
  ).addHelpText(
93601
93431
  "after",
93602
93432
  `
93603
93433
  Output (success, exit 0):
93604
- Inline in progress:
93605
- { "toolRunId": <string>, "mode": "inline", "status": "in_progress", "total": <number>, "finished": <number> }
93606
-
93607
- Inline complete:
93608
- { "toolRunId": <string>, "mode": "inline", "status": "complete", "total": <number>, "finished": <number>, "data": [ ... ] }
93434
+ Same shape as \`clay routines get\` \u2014 the updated routine with access.integrations.
93609
93435
 
93610
- Bulk in progress:
93611
- { "toolRunId": <string>, "mode": "bulk", "status": "in_progress", "total": <number>, "finished": <number> }
93612
-
93613
- Bulk complete:
93614
- { "toolRunId": <string>, "mode": "bulk", "status": "complete", "total": <number>, "finished": <number>, "resultUrl": <string> }
93436
+ ${TOOL_INTEGRATION_VALUES_HELP}
93615
93437
 
93616
- Bulk validation failed:
93617
- { "toolRunId": <string>, "mode": "bulk", "status": "validation_failed", "error": { "message": <string>, "totalInvalidRows": <number>, "details": [{ "lineNumber": <number>, "field": <string>, "message": <string> }] } }
93438
+ --entity-type applies to function routines only; passing it for a workflow routine is rejected.
93618
93439
 
93619
93440
  Common errors:
93620
- not_found (exit 6) No inline or bulk run with that id.
93441
+ validation_error (exit 2) Missing update flags, invalid entity type, --entity-type on a workflow routine, or invalid integration value.
93442
+ not_found (exit 6) No routine with that id in this workspace.
93443
+ auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
93621
93444
 
93622
93445
  Examples:
93623
- $ clay tools runs get run_abc | jq -r '.status'
93624
- $ clay tools runs get run_abc | jq -r '.mode'
93625
- $ clay tools runs get run_abc --limit 10 | jq '.data | length'
93446
+ $ clay routines update function:tbl_x --name "Renamed routine"
93447
+ $ clay routines update function:tbl_x --description "" --entity-type company
93448
+ $ clay routines update function:tbl_x --integrations api,mcp
93449
+ $ clay routines update function:tbl_x --integrations none
93450
+ $ clay routines update workflow:wf_x --name "Renamed workflow" --integrations api
93626
93451
  `
93627
- ).action(async (toolRunId, opts) => {
93628
- const client = await publicApiClient(publicApiToolsContract);
93629
- const accumulated = [];
93630
- let lastComplete;
93631
- const pager = new CursorPager();
93632
- let inlineNotFound = false;
93633
- for (; ; ) {
93634
- const remaining = opts.limit === void 0 ? MAX_PAGE_LIMIT : opts.limit - accumulated.length;
93635
- const pageSize = Math.min(MAX_PAGE_LIMIT, remaining);
93636
- const inline = await client.getRunResults({
93637
- params: { tool_run_id: toolRunId },
93638
- query: { ...pager.cursor !== void 0 ? { cursor: pager.cursor } : {}, limit: pageSize }
93639
- });
93640
- if (inline.status === 404) {
93641
- if (accumulated.length > 0) {
93642
- throw toHttpStatusError(inline);
93643
- }
93644
- inlineNotFound = true;
93645
- break;
93646
- }
93647
- if (inline.status === 202) {
93648
- writeJson(projectInlineResults(inline.body));
93649
- return;
93650
- }
93651
- if (inline.status !== 200) {
93652
- throw toHttpStatusError(inline);
93653
- }
93654
- lastComplete = inline.body;
93655
- accumulated.push(...inline.body.data);
93656
- if (inline.body.cursor === void 0) break;
93657
- if (opts.limit !== void 0 && accumulated.length >= opts.limit) break;
93658
- pager.advance(inline.body.cursor, inline.body.data.length);
93452
+ ).action(async (routineId, opts) => {
93453
+ const hasUpdate = opts.name !== void 0 || opts.description !== void 0 || opts.entityType !== void 0 || opts.integrations !== void 0;
93454
+ if (!hasUpdate) {
93455
+ throw new InvalidArgumentError(
93456
+ "at least one of --name, --description, --entity-type, or --integrations is required"
93457
+ );
93659
93458
  }
93660
- if (!inlineNotFound) {
93661
- if (lastComplete === void 0) {
93662
- throw new IncompatibleApiServerError(
93663
- "Clay API /public/v0/tools/run/:id/results returned no complete page before pagination ended."
93664
- );
93665
- }
93666
- const trimmed = opts.limit === void 0 ? accumulated : accumulated.slice(0, opts.limit);
93667
- writeJson(projectInlineResults({ ...lastComplete, data: trimmed, cursor: void 0 }));
93668
- return;
93459
+ const toolType = parseToolType(routineId);
93460
+ if (toolType !== "function" && toolType !== "workflow") {
93461
+ throw new InvalidArgumentError(`Routines of type "${toolType}" are not yet supported by CLI.`);
93669
93462
  }
93670
- const bulk = await client.getToolRunBatchResults({ params: { tool_run_id: toolRunId } });
93671
- if (bulk.status === 200 || bulk.status === 202) {
93672
- writeJson(projectBulkResults(bulk.body));
93673
- return;
93463
+ if (toolType === "workflow" && opts.entityType !== void 0) {
93464
+ throw new InvalidArgumentError("--entity-type is only valid for function routines");
93674
93465
  }
93675
- throw toHttpStatusError(bulk);
93466
+ const workspaceId = await currentWorkspaceId();
93467
+ const client = await v3Client(toolsContract);
93468
+ const body = {
93469
+ type: toolType,
93470
+ ...opts.name !== void 0 ? { name: opts.name } : {},
93471
+ ...opts.description !== void 0 ? { description: opts.description === "" ? null : opts.description } : {},
93472
+ ...toolType === "function" && opts.entityType !== void 0 ? { entityType: opts.entityType } : {},
93473
+ ...opts.integrations !== void 0 ? { access: { integrations: opts.integrations } } : {}
93474
+ };
93475
+ const updated = await unwrap(
93476
+ client.updateTool({ params: { workspaceId, toolId: routineId }, body })
93477
+ );
93478
+ writeJson(projectTool(updated));
93676
93479
  });
93677
93480
  return cmd;
93678
93481
  }
93679
93482
 
93680
- // src/commands/tools/runs/list.ts
93483
+ // src/commands/routines/index.ts
93484
+ function registerRoutines(program3) {
93485
+ const routines = applyClaySettings(
93486
+ new Command("routines").description("Manage Clay routines (list, get, update, runs).")
93487
+ );
93488
+ routines.addHelpText(
93489
+ "after",
93490
+ `
93491
+ Subcommands:
93492
+ list List routines in the workspace (id + name + description).
93493
+ get Fetch a routine by id with full config, integrations, and input schema.
93494
+ update Update name, description, entity-type, or integrations.
93495
+ runs Start async routine runs and fetch run status/results.
93496
+
93497
+ These are workspace routines (function and workflow types). For workflow building blocks
93498
+ (actions you add to a node\u2019s "tools"), see \`clay workflows actions\` instead.
93499
+
93500
+ See \`clay routines <subcommand> --help\` for per-subcommand JSON shape, error codes, and examples.
93501
+ `
93502
+ );
93503
+ routines.addCommand(applyClaySettings(buildListCommand2()));
93504
+ routines.addCommand(applyClaySettings(buildGetCommand()));
93505
+ routines.addCommand(applyClaySettings(buildUpdateCommand2()));
93506
+ routines.addCommand(applyClaySettings(buildRunsCommand()));
93507
+ program3.addCommand(routines);
93508
+ }
93509
+
93510
+ // ../../libs/api-contract/src/tables/summary/contract.ts
93511
+ var TableSummary = external_exports.object({
93512
+ id: external_exports.string(),
93513
+ name: external_exports.string(),
93514
+ description: external_exports.string().nullable(),
93515
+ workbook: external_exports.object({
93516
+ id: external_exports.string(),
93517
+ name: external_exports.string()
93518
+ }).nullable(),
93519
+ apiEnabled: external_exports.boolean()
93520
+ });
93521
+ var tablesSummaryContract = {
93522
+ listTablesSummary: {
93523
+ method: "GET",
93524
+ path: "/workspaces/:workspaceId/tables/summary",
93525
+ pathParams: external_exports.object({ workspaceId: workspaceIdPathParam }),
93526
+ query: external_exports.object({
93527
+ cursor: external_exports.string().min(1).optional(),
93528
+ limit: external_exports.coerce.number().int().min(1).max(100).optional().default(50),
93529
+ // z.coerce.boolean() treats any non-empty string as true (including "false"),
93530
+ // so accept the string literals explicitly and transform.
93531
+ apiEnabled: external_exports.enum(["true", "false"]).optional().transform((v) => v === void 0 ? void 0 : v === "true")
93532
+ }),
93533
+ responses: {
93534
+ 200: external_exports.object({
93535
+ data: external_exports.array(TableSummary),
93536
+ cursor: external_exports.string().optional()
93537
+ })
93538
+ },
93539
+ summary: "List tables in the workspace with a slim CLI-friendly projection.",
93540
+ metadata: { team: "integrations-team" /* IntegrationsTeam */ }
93541
+ }
93542
+ };
93543
+
93544
+ // src/commands/tables/list.ts
93681
93545
  function buildListCommand4() {
93682
93546
  const cmd = new Command("list");
93683
- cmd.description("List recent async tool runs and their statuses.").option(
93547
+ cmd.description(
93548
+ "List tables in the workspace pinned to your API key. Each row carries an `apiEnabled` flag for whether the table is enabled for public-API sync."
93549
+ ).option(
93684
93550
  "--limit <n>",
93685
- `Max runs to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
93551
+ `Max tables to return per page. Defaults to ${DEFAULT_PAGE_LIMIT}.`,
93686
93552
  parseLimitFlagWithMax(MAX_PAGE_LIMIT)
93687
- ).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").addHelpText(
93553
+ ).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").option("--api-enabled", "Only return tables enabled for the public API.").addHelpText(
93688
93554
  "after",
93689
93555
  `
93690
93556
  Output (success, exit 0):
93691
93557
  {
93692
93558
  "data": [
93693
93559
  {
93694
- "toolRunId": <string>,
93695
- "toolId": <string>,
93696
- "status": "in_progress" | "complete" | "validation_failed",
93697
- "total": <number>,
93698
- "finished": <number>
93560
+ "id": <string>,
93561
+ "name": <string>,
93562
+ "description": <string|null>,
93563
+ "workbook": { "id": <string>, "name": <string> } | null,
93564
+ "apiEnabled": <boolean>
93699
93565
  }
93700
93566
  ],
93701
93567
  "cursor": <string|undefined>
93702
93568
  }
93703
93569
 
93704
93570
  Pagination:
93705
- --limit <n> max runs per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
93571
+ --limit <n> max tables per call. Defaults to ${DEFAULT_PAGE_LIMIT}.
93706
93572
  --cursor <token> resume from a previous response's \`cursor\`
93707
93573
  When more results exist, the response includes a top-level \`cursor\`; pass it back via
93708
93574
  --cursor to fetch the next page.
93709
93575
 
93710
93576
  Common errors:
93711
93577
  validation_error (exit 2) --limit is not a positive integer or exceeds ${MAX_PAGE_LIMIT}.
93712
- auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
93578
+ auth_forbidden (exit 3) Key lacks the cli:all scope, or the workspace is not in the public-API beta.
93713
93579
 
93714
93580
  Examples:
93715
- $ clay tools runs list
93716
- $ clay tools runs list --limit 10 | jq -r '.data[].toolRunId'
93717
- $ clay tools runs list --limit 10 --cursor "$CURSOR"
93718
- $ clay tools runs list | jq '.data[] | select(.status == "in_progress")'
93581
+ $ clay tables list
93582
+ $ clay tables list --api-enabled | jq -r '.data[].id'
93583
+ $ clay tables list --limit 50 --cursor "$CURSOR"
93584
+ $ clay tables list --api-enabled | jq -r '.data[] | select(.apiEnabled) | .name'
93719
93585
  `
93720
93586
  ).action(async (opts) => {
93721
93587
  const workspaceId = await currentWorkspaceId();
93722
- const client = await v3Client(toolsContract);
93723
- const result = await unwrap(
93724
- client.listToolRuns({
93588
+ const client = await v3Client(tablesSummaryContract);
93589
+ const page = await unwrap(
93590
+ client.listTablesSummary({
93725
93591
  params: { workspaceId },
93726
93592
  query: {
93727
93593
  cursor: opts.cursor,
93728
- limit: opts.limit ?? DEFAULT_PAGE_LIMIT
93594
+ limit: opts.limit ?? DEFAULT_PAGE_LIMIT,
93595
+ apiEnabled: opts.apiEnabled === true ? "true" : void 0
93729
93596
  }
93730
93597
  })
93731
93598
  );
93732
93599
  writeJson({
93733
- data: result.data.map(projectRunListItem),
93734
- cursor: result.cursor
93600
+ data: page.data.map((t) => ({
93601
+ id: t.id,
93602
+ name: t.name,
93603
+ description: t.description,
93604
+ workbook: t.workbook,
93605
+ apiEnabled: t.apiEnabled
93606
+ })),
93607
+ cursor: page.cursor
93735
93608
  });
93736
93609
  });
93737
93610
  return cmd;
93738
93611
  }
93739
93612
 
93740
- // src/commands/tools/runs/input.ts
93741
- var import_node_fs11 = require("fs");
93742
- function readRunToolRequest(source) {
93743
- const raw = readUtf8Source("--input", source);
93744
- let parsed;
93745
- try {
93746
- parsed = JSON.parse(raw);
93747
- } catch (err) {
93748
- throw new InvalidArgumentError(`--input: not valid JSON (${err.message})`);
93613
+ // ../../libs/api-contract/src/public-api-v0/structured-query-schema.ts
93614
+ var FilterOp = external_exports.enum([
93615
+ "=",
93616
+ "!=",
93617
+ ">",
93618
+ ">=",
93619
+ "<",
93620
+ "<=",
93621
+ "contains",
93622
+ "not_contains",
93623
+ "starts_with",
93624
+ "ends_with",
93625
+ "in",
93626
+ "not_in",
93627
+ "is_empty",
93628
+ "is_not_empty"
93629
+ ]);
93630
+ var NestedPath = external_exports.array(external_exports.string().min(1)).min(1).max(5);
93631
+ var OPS_WITHOUT_VALUE = /* @__PURE__ */ new Set(["is_empty", "is_not_empty"]);
93632
+ var FilterPredicate = external_exports.object({
93633
+ field: external_exports.string().min(1),
93634
+ path: NestedPath.optional(),
93635
+ op: FilterOp,
93636
+ // `null` is intentionally excluded — `is_empty` / `is_not_empty` are the canonical
93637
+ // way to test for absent/empty cells. Allowing `value: null` would invite the SQL
93638
+ // three-valued-logic surprise (where `field = NULL` is always false) and force a
93639
+ // choice about whether `=` means "match the JSON null literal" or "match any
93640
+ // missing/null/empty cell". Punting that decision keeps the operator semantics clean.
93641
+ value: external_exports.union([external_exports.string(), external_exports.number(), external_exports.boolean(), external_exports.array(external_exports.union([external_exports.string(), external_exports.number()]))]).optional()
93642
+ }).superRefine((data, ctx) => {
93643
+ if (!OPS_WITHOUT_VALUE.has(data.op) && data.value === void 0) {
93644
+ ctx.addIssue({
93645
+ code: external_exports.ZodIssueCode.custom,
93646
+ message: `Operator "${data.op}" requires a value`,
93647
+ path: ["value"]
93648
+ });
93749
93649
  }
93750
- const request2 = RunToolRequestSchema.pick({ items: true }).safeParse(parsed);
93751
- if (!request2.success) {
93752
- const issue = request2.error.issues[0];
93753
- const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
93754
- const message = issue === void 0 ? "invalid shape" : issue.message;
93755
- throw new InvalidArgumentError(
93756
- `--input: must match { "items": [{ "id": <string>, "inputs": <object> }] }${path7}: ${message}`
93757
- );
93650
+ });
93651
+ var FilterAnd = external_exports.lazy(
93652
+ () => external_exports.object({ and: external_exports.array(FilterExpression).min(1).max(10) })
93653
+ );
93654
+ var FilterOr = external_exports.lazy(() => external_exports.object({ or: external_exports.array(FilterExpression).min(1).max(10) }));
93655
+ var FilterNot = external_exports.lazy(() => external_exports.object({ not: FilterExpression }));
93656
+ var FilterExpression = external_exports.lazy(
93657
+ () => external_exports.union([FilterPredicate, FilterAnd, FilterOr, FilterNot])
93658
+ );
93659
+ var FieldSelect = external_exports.object({
93660
+ field: external_exports.string().min(1),
93661
+ path: NestedPath.optional(),
93662
+ table: external_exports.string().optional(),
93663
+ as: external_exports.string().optional()
93664
+ });
93665
+ var AggregateSelect = external_exports.object({
93666
+ fn: external_exports.enum(["count", "sum", "avg", "max", "min"]),
93667
+ field: external_exports.string().min(1),
93668
+ path: NestedPath.optional(),
93669
+ as: external_exports.string().min(1)
93670
+ });
93671
+ var SelectItem = external_exports.union([AggregateSelect, FieldSelect]);
93672
+ var TableRef = external_exports.object({
93673
+ id: external_exports.string().min(1),
93674
+ alias: external_exports.string().optional()
93675
+ });
93676
+ var JoinSpec = external_exports.object({
93677
+ table: external_exports.string().min(1),
93678
+ on: external_exports.object({
93679
+ left: external_exports.string().min(1),
93680
+ right: external_exports.string().min(1)
93681
+ }),
93682
+ type: external_exports.enum(["inner", "left"]).default("inner")
93683
+ });
93684
+ var OrderByItem = external_exports.object({
93685
+ field: external_exports.string().min(1),
93686
+ direction: external_exports.enum(["asc", "desc"]).default("asc")
93687
+ });
93688
+ var FieldMode = external_exports.enum(["names", "ids"]);
93689
+ var FILTER_MAX_DEPTH = 10;
93690
+ function filterDepth(filter) {
93691
+ const stack = [{ node: filter, depth: 0 }];
93692
+ let max = 0;
93693
+ while (stack.length > 0) {
93694
+ const item = stack.pop();
93695
+ if (item === void 0) break;
93696
+ const { node: node2, depth } = item;
93697
+ if (depth > max) max = depth;
93698
+ if (!node2 || typeof node2 !== "object") continue;
93699
+ const obj = node2;
93700
+ if (Array.isArray(obj.and)) {
93701
+ for (const c3 of obj.and) stack.push({ node: c3, depth: depth + 1 });
93702
+ } else if (Array.isArray(obj.or)) {
93703
+ for (const c3 of obj.or) stack.push({ node: c3, depth: depth + 1 });
93704
+ } else if ("not" in obj) {
93705
+ stack.push({ node: obj.not, depth: depth + 1 });
93706
+ }
93707
+ }
93708
+ return max;
93709
+ }
93710
+ var StructuredQuery = external_exports.object({
93711
+ tables: external_exports.array(TableRef).min(1).max(5),
93712
+ select: external_exports.array(SelectItem).max(20).optional(),
93713
+ filter: FilterExpression.optional(),
93714
+ join: external_exports.array(JoinSpec).max(4).optional(),
93715
+ group_by: external_exports.array(external_exports.string().min(1)).max(5).optional(),
93716
+ order_by: external_exports.array(OrderByItem).max(3).optional(),
93717
+ /** Controls whether response data keys use field IDs (default) or field names */
93718
+ field_mode: FieldMode.optional()
93719
+ });
93720
+ var paginationFields = {
93721
+ limit: external_exports.number().int().min(1).max(100).default(50),
93722
+ cursor: external_exports.string().optional()
93723
+ };
93724
+ var StructuredQueryRequestShape = external_exports.object({
93725
+ query: StructuredQuery,
93726
+ ...paginationFields
93727
+ });
93728
+ var StructuredQueryRequest = external_exports.preprocess((raw, ctx) => {
93729
+ if (raw && typeof raw === "object" && !Array.isArray(raw)) {
93730
+ const query = raw.query;
93731
+ const filter = query && typeof query === "object" && !Array.isArray(query) ? query.filter : void 0;
93732
+ if (filter !== void 0 && filterDepth(filter) > FILTER_MAX_DEPTH) {
93733
+ ctx.addIssue({
93734
+ code: external_exports.ZodIssueCode.custom,
93735
+ message: `Filter nesting too deep (max ${FILTER_MAX_DEPTH})`,
93736
+ path: ["query", "filter"]
93737
+ });
93738
+ return external_exports.NEVER;
93739
+ }
93740
+ }
93741
+ return raw;
93742
+ }, StructuredQueryRequestShape);
93743
+
93744
+ // ../../libs/api-contract/src/public-api-v0/tables-contract.ts
93745
+ var c2 = initContract();
93746
+ var CellSuccessSchema = external_exports.object({
93747
+ status: external_exports.literal("success"),
93748
+ value: external_exports.unknown(),
93749
+ fields: external_exports.record(external_exports.unknown()).nullable(),
93750
+ is_stale: external_exports.literal(true).optional()
93751
+ });
93752
+ var CellErrorSchema = external_exports.object({
93753
+ status: external_exports.literal("error"),
93754
+ error: external_exports.string().optional()
93755
+ });
93756
+ var CellPendingSchema = external_exports.object({
93757
+ status: external_exports.enum(["running", "queued", "retry", "rate_limited", "awaiting_callback"])
93758
+ });
93759
+ var CellEmptySchema = external_exports.object({
93760
+ status: external_exports.literal("empty")
93761
+ });
93762
+ var CellResultSchema = external_exports.discriminatedUnion("status", [
93763
+ CellSuccessSchema,
93764
+ CellErrorSchema,
93765
+ CellPendingSchema,
93766
+ CellEmptySchema
93767
+ ]);
93768
+ var FieldMetaSchema = external_exports.object({
93769
+ id: external_exports.string(),
93770
+ name: external_exports.string(),
93771
+ type: external_exports.string()
93772
+ });
93773
+ var QueryResponseSchema = paginatedResponse(external_exports.record(CellResultSchema)).extend({
93774
+ fields: external_exports.record(FieldMetaSchema).optional()
93775
+ });
93776
+ var publicApiTablesContract = c2.router({
93777
+ query: {
93778
+ method: "POST",
93779
+ path: "/tables/query",
93780
+ body: StructuredQueryRequest,
93781
+ responses: {
93782
+ 200: QueryResponseSchema,
93783
+ 400: errorResponseSchema,
93784
+ 401: errorResponseSchema,
93785
+ 403: errorResponseSchema,
93786
+ 404: errorResponseSchema,
93787
+ 422: errorResponseSchema,
93788
+ 429: errorResponseSchema
93789
+ },
93790
+ summary: "Run a structured query across one or more tables",
93791
+ description: "Runs a structured query against Clay table data and returns records with field metadata."
93792
+ }
93793
+ });
93794
+
93795
+ // src/commands/tables/projection.ts
93796
+ function projectCell(cell) {
93797
+ if (cell.status === "success") {
93798
+ return {
93799
+ status: "success",
93800
+ value: cell.value,
93801
+ fields: cell.fields,
93802
+ ...cell.is_stale === true ? { isStale: true } : {}
93803
+ };
93804
+ }
93805
+ if (cell.status === "error") {
93806
+ return cell.error === void 0 ? { status: "error" } : { status: "error", error: cell.error };
93807
+ }
93808
+ if (cell.status === "empty") {
93809
+ return { status: "empty" };
93758
93810
  }
93759
- return request2.data;
93811
+ return { status: cell.status };
93760
93812
  }
93761
- function readJsonlFile(source) {
93762
- let buf;
93763
- try {
93764
- buf = (0, import_node_fs11.readFileSync)(source);
93765
- } catch (err) {
93766
- throw new InvalidArgumentError(`--bulk: could not read ${source} (${err.message})`);
93813
+ function projectRow(row) {
93814
+ const out = {};
93815
+ for (const [key, cell] of Object.entries(row)) {
93816
+ out[key] = projectCell(cell);
93767
93817
  }
93768
- validateJsonl(buf);
93769
- return buf;
93818
+ return out;
93770
93819
  }
93771
- function validateJsonl(buf) {
93772
- const text = buf.toString("utf8");
93773
- const lines = text.split("\n");
93774
- let parsedRows = 0;
93775
- for (let i = 0; i < lines.length; i++) {
93776
- const trimmed = (lines[i] ?? "").trim();
93777
- if (trimmed === "") continue;
93778
- const lineNumber = i + 1;
93779
- let parsed;
93780
- try {
93781
- parsed = JSON.parse(trimmed);
93782
- } catch (err) {
93783
- throw new InvalidArgumentError(
93784
- `--bulk: line ${String(lineNumber)} is not valid JSON (${err.message})`
93785
- );
93786
- }
93787
- const result = RunToolItemSchema.safeParse(parsed);
93788
- if (!result.success) {
93789
- const issue = result.error.issues[0];
93790
- const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
93791
- const message = issue === void 0 ? "invalid shape" : issue.message;
93792
- throw new InvalidArgumentError(
93793
- `--bulk: line ${String(lineNumber)} must match { "id": <string>, "inputs": <object> }${path7}: ${message}`
93794
- );
93795
- }
93796
- parsedRows++;
93797
- }
93798
- if (parsedRows === 0) {
93799
- throw new InvalidArgumentError("--bulk: file is empty (no JSON lines found)");
93820
+ function projectFields(fields) {
93821
+ const out = {};
93822
+ for (const [key, meta] of Object.entries(fields)) {
93823
+ out[key] = { id: meta.id, name: meta.name, type: meta.type };
93800
93824
  }
93825
+ return out;
93801
93826
  }
93802
- function readUtf8Source(flagName, source) {
93803
- const display = source === "-" ? "stdin" : source;
93804
- if (isInlineJson(source)) {
93805
- return source;
93827
+ function projectQueryResponse(response) {
93828
+ return {
93829
+ data: response.data.map(projectRow),
93830
+ ...response.cursor === void 0 ? {} : { cursor: response.cursor },
93831
+ ...response.fields === void 0 ? {} : { fields: projectFields(response.fields) }
93832
+ };
93833
+ }
93834
+
93835
+ // src/commands/tables/query.ts
93836
+ function parseLimit(raw) {
93837
+ const n2 = Number.parseInt(raw, 10);
93838
+ if (!Number.isInteger(n2) || String(n2) !== raw.trim()) {
93839
+ throw new InvalidArgumentError("must be an integer");
93806
93840
  }
93807
- try {
93808
- return source === "-" ? (0, import_node_fs11.readFileSync)(0, "utf8") : (0, import_node_fs11.readFileSync)(source, "utf8");
93809
- } catch (err) {
93810
- throw new InvalidArgumentError(`${flagName}: could not read ${display} (${err.message})`);
93841
+ return n2;
93842
+ }
93843
+ function buildRequestBody(opts) {
93844
+ const body = {
93845
+ query: readJsonFlag("--query", opts.query),
93846
+ ...opts.limit !== void 0 ? { limit: opts.limit } : {},
93847
+ ...opts.cursor !== void 0 ? { cursor: opts.cursor } : {}
93848
+ };
93849
+ const result = StructuredQueryRequest.safeParse(body);
93850
+ if (!result.success) {
93851
+ const issue = result.error.issues[0];
93852
+ const path7 = issue?.path.length ? ` at ${issue.path.join(".")}` : "";
93853
+ const message = issue === void 0 ? "invalid shape" : issue.message;
93854
+ throw new InvalidArgumentError(`invalid request${path7}: ${message}`);
93811
93855
  }
93856
+ return body;
93812
93857
  }
93813
-
93814
- // src/commands/tools/runs/start.ts
93815
- function buildStartCommand() {
93816
- const cmd = new Command("start");
93858
+ function buildQueryCommand() {
93859
+ const cmd = new Command("query");
93817
93860
  cmd.description(
93818
- "Start an async tool run through the API & CLI integration. Returns immediately; this command does not poll or wait."
93819
- ).argument("<toolId>", "Tool id, e.g. function:tbl_abc123").option("--input <json|file|->", "Run body JSON: inline JSON, a file path, or - to read from stdin.").option("--bulk <file.jsonl>", 'Batch run input JSONL file. Each line is { "id": <string>, "inputs": <object> }.').option("--webhook-id <id>", "Registered webhook id (wh_...) to notify when the run finishes.").addHelpText(
93861
+ "Run a structured query against one or more tables in the authenticated workspace. The query is read from --query; the response is written to stdout as JSON."
93862
+ ).requiredOption(
93863
+ "--query <file|->",
93864
+ "Path to a JSON file containing the structured query. Use - to read from stdin."
93865
+ ).option("--limit <n>", "Max rows to return (1-100, default 50).", parseLimit).option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").addHelpText(
93820
93866
  "after",
93821
93867
  `
93822
93868
  Output (success, exit 0):
93823
- Inline:
93824
- { "toolRunId": <string>, "mode": "inline", "status": "in_progress" }
93869
+ {
93870
+ "data": [ { "<fieldId>": <cell> } ],
93871
+ "cursor": <string|undefined>,
93872
+ "fields": <{ "<fieldId>": { "id": <string>, "name": <string>, "type": <string> } }|undefined>
93873
+ }
93825
93874
 
93826
- Bulk:
93827
- { "toolRunId": <string>, "mode": "bulk", "status": "in_progress", "fileId": <string> }
93875
+ Each <cell> is one of:
93876
+ { "status": "success", "value": <unknown>, "fields": <object|null>, "isStale": <true|undefined> }
93877
+ { "status": "error", "error": <string|undefined> }
93878
+ { "status": "running" | "queued" | "retry" | "rate_limited" | "awaiting_callback" }
93879
+ { "status": "empty" }
93828
93880
 
93829
- --input values:
93830
- { "items": [{ "id": <string>, "inputs": <object> }] }
93831
- items requires 1 to 100 entries; for larger batches use --bulk.
93881
+ Query shape (--query):
93882
+ The --query file is the query itself \u2014 what to fetch. Pagination is not part of it.
93883
+ Minimal: { "tables": [{ "id": "tbl_..." }] }
93884
+ Beyond \`tables\`, a query may also include \`filter\`, \`select\`, \`join\`, \`order_by\`,
93885
+ \`group_by\`, and \`field_mode\`.
93886
+ Field references can use ids or names; multi-table queries declare each table in \`tables\`.
93887
+
93888
+ Pagination:
93889
+ Page size and position are flags, not part of the query:
93890
+ --limit <n> max rows per call (1-100, default 50)
93891
+ --cursor <token> resume from a previous response's \`cursor\`
93892
+ When more results exist, the response includes a top-level \`cursor\`; pass it back via
93893
+ --cursor to fetch the next page.
93832
93894
 
93833
93895
  Common errors:
93834
- validation_error (exit 2) Missing/conflicting input flags, unreadable file, invalid JSON body, or a JSONL row that fails the { "id": <string>, "inputs": <object> } shape (error names the line number).
93835
- not_found (exit 6) No tool with that id in this workspace, or the tool is not enabled for API & CLI.
93836
- auth_forbidden (exit 3) Key lacks access to run this tool through API & CLI.
93837
- server_error (exit 1) Bulk input upload to storage failed; safe to retry the command.
93896
+ validation_error (exit 2) Missing --query, unreadable file, invalid JSON, or a request that does not match the schema.
93897
+ auth_forbidden (exit 3) Key lacks the cli:all scope, or the workspace is not in the public-API beta.
93898
+ not_found (exit 6) A referenced table or field does not exist.
93838
93899
 
93839
93900
  Examples:
93840
- $ clay tools update function:tbl_x --integrations api
93841
- $ cat input.json | clay tools runs start function:tbl_x --input -
93842
- $ clay tools runs start function:tbl_x --input '{"items":[{"id":"r1","inputs":{}}]}' | jq -r '.toolRunId'
93843
- $ clay tools runs start function:tbl_x --input input.json | jq -r '.toolRunId'
93844
- $ clay tools runs start function:tbl_x --input input.json --webhook-id wh_abc123 | jq -r '.toolRunId'
93845
- $ clay tools runs start function:tbl_x --bulk rows.jsonl
93846
- $ clay tools runs start function:tbl_x --bulk rows.jsonl --webhook-id wh_abc123
93901
+ $ clay tables query --query ./query.json | jq '.data | length'
93902
+ $ echo '{"tables":[{"id":"tbl_..."}]}' | clay tables query --query - --limit 100
93903
+ $ clay tables query --query ./query.json --limit 100 --cursor "$CURSOR"
93847
93904
  `
93848
- ).action(async (toolId, opts) => {
93849
- const hasInput = opts.input !== void 0;
93850
- const hasBulk = opts.bulk !== void 0;
93851
- if (hasInput === hasBulk) {
93852
- throw new InvalidArgumentError("exactly one of --input or --bulk is required");
93853
- }
93854
- const client = await publicApiClient(publicApiToolsContract);
93855
- if (opts.input !== void 0) {
93856
- const body2 = readRunToolRequest(opts.input);
93857
- body2.webhook_id = opts.webhookId;
93858
- const response2 = await unwrap(client.runTool({ params: { tool_id: toolId }, body: body2 }));
93859
- writeJson(projectInlineStart(response2));
93860
- return;
93861
- }
93862
- if (opts.bulk === void 0) {
93863
- throw new InvalidArgumentError("exactly one of --input or --bulk is required");
93864
- }
93865
- const body = readJsonlFile(opts.bulk);
93866
- const upload = await unwrap(client.runToolBatchUploadUrl({ params: { tool_id: toolId } }));
93867
- await uploadJsonl(upload.upload_url, body);
93868
- const response = await unwrap(
93869
- client.startToolRunBatch({
93870
- params: { tool_id: toolId },
93871
- body: { file_id: upload.file_id, webhook_id: opts.webhookId }
93872
- })
93873
- );
93874
- writeJson(projectBulkStart(response, upload.file_id));
93905
+ ).action(async (opts) => {
93906
+ const body = buildRequestBody(opts);
93907
+ const client = await publicApiClient(publicApiTablesContract);
93908
+ const response = await unwrap(client.query({ body }));
93909
+ writeJson(projectQueryResponse(response));
93875
93910
  });
93876
93911
  return cmd;
93877
93912
  }
93878
- async function uploadJsonl(uploadUrl, body) {
93879
- const response = await fetchWithTimeout(
93880
- uploadUrl,
93881
- {
93882
- method: "PUT",
93883
- headers: { "content-type": "application/x-ndjson" },
93884
- body: Uint8Array.from(body)
93885
- },
93886
- uploadTimeoutMs()
93887
- );
93888
- if (response.ok) return;
93889
- throw new UploadFailedError(`Bulk input upload to storage failed: ${await uploadFailureMessage(response)}`);
93890
- }
93891
- async function uploadFailureMessage(response) {
93892
- let text = "";
93893
- try {
93894
- text = await response.text();
93895
- } catch {
93896
- return `HTTP ${String(response.status)}`;
93897
- }
93898
- if (text.length === 0) {
93899
- return `HTTP ${String(response.status)}`;
93900
- }
93901
- try {
93902
- const parsed = JSON.parse(text);
93903
- if (typeof parsed === "object" && parsed !== null && "message" in parsed) {
93904
- const message = parsed.message;
93905
- if (typeof message === "string" && message.length > 0) return message;
93906
- }
93907
- } catch {
93908
- return `HTTP ${String(response.status)}: ${text.slice(0, 200)}`;
93909
- }
93910
- return `HTTP ${String(response.status)}: ${text.slice(0, 200)}`;
93911
- }
93912
-
93913
- // src/commands/tools/runs/index.ts
93914
- function buildRunsCommand() {
93915
- const cmd = new Command("runs");
93916
- cmd.description("Start async tool runs and fetch run status/results.").addHelpText(
93917
- "after",
93918
- `
93919
- Subcommands:
93920
- list List recent async tool runs and their statuses.
93921
- start Start an inline or bulk async tool run.
93922
- get Fetch status/results for an inline or bulk run.
93923
93913
 
93924
- Examples:
93925
- $ clay tools runs list
93926
- $ cat input.json | clay tools runs start function:tbl_x --input -
93927
- $ clay tools runs start function:tbl_x --bulk rows.jsonl
93928
- $ clay tools runs get run_abc | jq -r '.status'
93929
- `
93930
- );
93931
- cmd.addCommand(applyClaySettings(buildListCommand4()));
93932
- cmd.addCommand(applyClaySettings(buildStartCommand()));
93933
- cmd.addCommand(applyClaySettings(buildGetCommand2()));
93934
- return cmd;
93935
- }
93914
+ // ../../libs/api-contract/src/clayql/clayql-sync/interfaces.ts
93915
+ var MAX_BULK_SYNC_ITEMS = 5;
93916
+ var SyncStatusSchema = external_exports.enum(["in_progress", "success", "error"]);
93917
+ var EnqueueRecordsSyncInput = external_exports.object({
93918
+ workspaceId: external_exports.number(),
93919
+ tableId: external_exports.string(),
93920
+ // Set by the worker on recovery follow-ups; breaks the chain on empty batch.
93921
+ isTailReenqueue: external_exports.boolean().optional()
93922
+ });
93923
+ var JobState = external_exports.enum([
93924
+ "completed",
93925
+ "failed",
93926
+ "delayed",
93927
+ "active",
93928
+ "waiting",
93929
+ "waiting-children",
93930
+ "unknown",
93931
+ "prioritized"
93932
+ ]);
93933
+ var EnqueueRecordsSyncResponse = external_exports.object({
93934
+ jobId: external_exports.string(),
93935
+ status: JobState,
93936
+ enqueuedAt: external_exports.string().datetime()
93937
+ });
93938
+ var EnqueueTablesInput = external_exports.object({
93939
+ workspaceId: external_exports.number(),
93940
+ tableIds: external_exports.array(external_exports.string()).min(1).max(MAX_BULK_SYNC_ITEMS),
93941
+ delayMs: external_exports.number().int().min(0).max(6e4).optional().describe(
93942
+ "Debounce window in ms passed to BullMQ as job delay. While a job with the same dedup id is delayed, subsequent enqueues are collapsed into it \u2014 gives cluster-wide debouncing on top of any per-pod throttling."
93943
+ )
93944
+ });
93945
+ var EnqueueTablesResponse = external_exports.object({
93946
+ totalQueued: external_exports.number(),
93947
+ errors: external_exports.array(
93948
+ external_exports.object({
93949
+ tableId: external_exports.string(),
93950
+ workspaceId: external_exports.number(),
93951
+ error: external_exports.string()
93952
+ })
93953
+ ).optional()
93954
+ });
93955
+ var ExecuteQueryInput = external_exports.object({
93956
+ workspaceId: external_exports.number(),
93957
+ query: external_exports.string(),
93958
+ parameters: external_exports.record(external_exports.union([external_exports.string(), external_exports.number(), external_exports.array(external_exports.string())])),
93959
+ conversationId: external_exports.string().optional()
93960
+ });
93961
+ var ExecuteQueryResponse = external_exports.array(external_exports.record(external_exports.any()));
93936
93962
 
93937
- // src/commands/tools/update.ts
93938
- function parseEntityType(value) {
93939
- if (value === "contact" || value === "company") return value;
93940
- throw new InvalidArgumentError("entity-type must be contact or company");
93941
- }
93942
- function parseToolType(value) {
93943
- try {
93944
- return parseToolId(value).toolType;
93945
- } catch {
93946
- throw new InvalidArgumentError("tool id is in an invalid format");
93963
+ // ../../libs/api-contract/src/tables/clayql-sync/contract.ts
93964
+ var ClayQLSyncStatusValue = external_exports.union([SyncStatusSchema, external_exports.literal("never_synced")]);
93965
+ var ClayQLSyncErrorCode = external_exports.enum([
93966
+ "INVALID_INPUT",
93967
+ "DB_CONNECTION_ERROR",
93968
+ "QUERY_ERROR",
93969
+ "DATABASE_ERROR",
93970
+ "RECORD_PROCESSING_ERROR",
93971
+ "WATERMARK_ERROR",
93972
+ "ORPHANED",
93973
+ "UNKNOWN_ERROR"
93974
+ ]);
93975
+ var ClayQLSyncStatusResponse = external_exports.object({
93976
+ status: ClayQLSyncStatusValue,
93977
+ lastAttemptAt: external_exports.string().datetime().nullable(),
93978
+ lastSuccessAt: external_exports.string().datetime().nullable(),
93979
+ errorCode: ClayQLSyncErrorCode.nullable()
93980
+ });
93981
+ var ClayQLSyncUsageResponse = external_exports.object({
93982
+ used: external_exports.number().int().nonnegative(),
93983
+ limit: external_exports.number().int().nonnegative(),
93984
+ slotTableIds: external_exports.array(external_exports.string())
93985
+ });
93986
+ var UpdateClayQLSyncRequest = external_exports.object({
93987
+ enabled: external_exports.boolean()
93988
+ });
93989
+ var UpdateClayQLSyncResponse = external_exports.object({
93990
+ id: external_exports.string(),
93991
+ enabled: external_exports.boolean()
93992
+ });
93993
+ var clayqlSyncContract = {
93994
+ getClayQLSyncStatus: {
93995
+ method: "GET",
93996
+ path: "/workspaces/:workspaceId/tables/:tableId/clayql-sync-status",
93997
+ pathParams: external_exports.object({
93998
+ workspaceId: workspaceIdPathParam,
93999
+ tableId: external_exports.string()
94000
+ }),
94001
+ responses: {
94002
+ 200: ClayQLSyncStatusResponse
94003
+ },
94004
+ summary: "Latest ClayQL sync attempt for a table",
94005
+ metadata: { team: "rep-tools" /* RepTools */ }
94006
+ },
94007
+ getClayQLSyncUsage: {
94008
+ method: "GET",
94009
+ path: "/workspaces/:workspaceId/clayql-sync-usage",
94010
+ pathParams: external_exports.object({
94011
+ workspaceId: workspaceIdPathParam
94012
+ }),
94013
+ responses: {
94014
+ 200: ClayQLSyncUsageResponse
94015
+ },
94016
+ summary: "Workspace synced-tables usage and limit",
94017
+ metadata: { team: "rep-tools" /* RepTools */ }
94018
+ },
94019
+ updateTableClayQLSync: {
94020
+ method: "PUT",
94021
+ path: "/workspaces/:workspaceId/tables/:tableId/clayql-sync",
94022
+ pathParams: external_exports.object({
94023
+ workspaceId: workspaceIdPathParam,
94024
+ tableId: external_exports.string()
94025
+ }),
94026
+ body: UpdateClayQLSyncRequest,
94027
+ responses: {
94028
+ 200: UpdateClayQLSyncResponse
94029
+ },
94030
+ summary: "Enable or disable ClayQL sync for a table",
94031
+ metadata: { team: "rep-tools" /* RepTools */ }
93947
94032
  }
93948
- }
94033
+ };
94034
+
94035
+ // src/commands/tables/update.ts
93949
94036
  function buildUpdateCommand3() {
93950
94037
  const cmd = new Command("update");
93951
- cmd.description("Update a tool \u2014 name, description, integrations, or entity-type.").argument("<toolId>", "Tool id, e.g. function:tbl_abc123 or workflow:wf_abc123").option("--name <name>", "Set the tool name (max 100 chars).").option("--description <description>", "Set the description. Pass an empty string to clear it.").option(
93952
- "--entity-type <type>",
93953
- "Set the MCP entity type: contact or company. Not valid for workflow tools",
93954
- parseEntityType
93955
- ).option(
93956
- "--integrations <csv>",
93957
- `Override all existing integrations. Pass comma-separated values (${TOOL_INTEGRATION_CSV}) or ${TOOL_INTEGRATION_CLEAR_VALUE} to clear.`,
93958
- parseToolIntegrationCsv
94038
+ cmd.description(
94039
+ "Enable or disable API query sync for a table in the authenticated workspace. A table must have sync enabled before it can be used with `clay tables query`."
94040
+ ).argument("<tableId>", "Table id, e.g. tbl_abc123").requiredOption(
94041
+ "--query-sync <true|false>",
94042
+ "Enable (true) or disable (false) API query sync for the table.",
94043
+ parseBooleanFlag("--query-sync")
93959
94044
  ).addHelpText(
93960
94045
  "after",
93961
94046
  `
93962
94047
  Output (success, exit 0):
93963
- Same shape as \`clay tools get\` \u2014 the updated tool with access.integrations.
93964
-
93965
- ${TOOL_INTEGRATION_VALUES_HELP}
93966
-
93967
- --entity-type applies to function tools only; passing it for a workflow tool is rejected.
94048
+ {
94049
+ "id": <string>,
94050
+ "querySyncEnabled": <boolean>
94051
+ }
93968
94052
 
93969
94053
  Common errors:
93970
- validation_error (exit 2) Missing update flags, invalid entity type, --entity-type on a workflow tool, or invalid integration value.
93971
- not_found (exit 6) No tool with that id in this workspace.
93972
- auth_forbidden (exit 3) Key lacks the cli:all scope (or 'all').
94054
+ validation_error (exit 2) Missing or invalid --query-sync, or missing table id.
94055
+ auth_forbidden (exit 3) Key lacks the cli:all scope (or all) or you lack access to the table.
94056
+ not_found (exit 6) No table with that id in this workspace.
93973
94057
 
93974
94058
  Examples:
93975
- $ clay tools update function:tbl_x --name "Renamed tool"
93976
- $ clay tools update function:tbl_x --description "" --entity-type company
93977
- $ clay tools update function:tbl_x --integrations api,mcp
93978
- $ clay tools update function:tbl_x --integrations none
93979
- $ clay tools update workflow:wf_x --name "Renamed workflow" --integrations api
94059
+ $ clay tables update tbl_abc123 --query-sync true
94060
+ $ clay tables update tbl_abc123 --query-sync false | jq '.querySyncEnabled'
93980
94061
  `
93981
- ).action(async (toolId, opts) => {
93982
- const hasUpdate = opts.name !== void 0 || opts.description !== void 0 || opts.entityType !== void 0 || opts.integrations !== void 0;
93983
- if (!hasUpdate) {
93984
- throw new InvalidArgumentError(
93985
- "at least one of --name, --description, --entity-type, or --integrations is required"
93986
- );
93987
- }
93988
- const toolType = parseToolType(toolId);
93989
- if (toolType !== "function" && toolType !== "workflow") {
93990
- throw new InvalidArgumentError(`Tools of type "${toolType}" are not yet supported by CLI.`);
93991
- }
93992
- if (toolType === "workflow" && opts.entityType !== void 0) {
93993
- throw new InvalidArgumentError("--entity-type is only valid for function tools");
93994
- }
94062
+ ).action(async (tableId, opts) => {
93995
94063
  const workspaceId = await currentWorkspaceId();
93996
- const client = await v3Client(toolsContract);
93997
- const body = {
93998
- type: toolType,
93999
- ...opts.name !== void 0 ? { name: opts.name } : {},
94000
- ...opts.description !== void 0 ? { description: opts.description === "" ? null : opts.description } : {},
94001
- ...toolType === "function" && opts.entityType !== void 0 ? { entityType: opts.entityType } : {},
94002
- ...opts.integrations !== void 0 ? { access: { integrations: opts.integrations } } : {}
94003
- };
94004
- const updated = await unwrap(client.updateTool({ params: { workspaceId, toolId }, body }));
94005
- writeJson(projectTool(updated));
94064
+ const client = await v3Client(clayqlSyncContract);
94065
+ const updated = await unwrap(
94066
+ client.updateTableClayQLSync({
94067
+ params: { workspaceId, tableId },
94068
+ body: { enabled: opts.querySync }
94069
+ })
94070
+ );
94071
+ writeJson({ id: updated.id, querySyncEnabled: updated.enabled });
94006
94072
  });
94007
94073
  return cmd;
94008
94074
  }
94009
94075
 
94010
- // src/commands/tools/index.ts
94011
- function registerTools(program3) {
94012
- const tools = applyClaySettings(new Command("tools").description("Manage Clay tools (list, get, update, runs)."));
94013
- tools.addHelpText(
94076
+ // src/commands/tables/index.ts
94077
+ function registerTables(program3) {
94078
+ const tables = applyClaySettings(
94079
+ new Command("tables").summary("Work with workspace tables.").description("Work with tables in the authenticated workspace. Subcommands: list, query, update.")
94080
+ );
94081
+ tables.addHelpText(
94014
94082
  "after",
94015
94083
  `
94016
94084
  Subcommands:
94017
- list List tools in the workspace (id + name + description).
94018
- get Fetch a tool by id with full config, integrations, and input schema.
94019
- update Update name, description, entity-type, or integrations.
94020
- runs Start async tool runs and fetch run status/results.
94021
-
94022
- These are workspace tools (function and workflow types). For workflow building blocks
94023
- (actions you add to a node\u2019s "tools"), see \`clay workflows actions\` instead.
94085
+ list List tables in the workspace.
94086
+ query Run a structured query across one or more tables.
94087
+ update Enable or disable API query sync for a table.
94024
94088
 
94025
- See \`clay tools <subcommand> --help\` for per-subcommand JSON shape, error codes, and examples.
94089
+ See \`clay tables <subcommand> --help\` for per-subcommand JSON shape, error codes, and examples.
94026
94090
  `
94027
94091
  );
94028
- tools.addCommand(applyClaySettings(buildListCommand3()));
94029
- tools.addCommand(applyClaySettings(buildGetCommand()));
94030
- tools.addCommand(applyClaySettings(buildUpdateCommand3()));
94031
- tools.addCommand(applyClaySettings(buildRunsCommand()));
94032
- program3.addCommand(tools);
94092
+ tables.addCommand(applyClaySettings(buildListCommand4()));
94093
+ tables.addCommand(applyClaySettings(buildQueryCommand()));
94094
+ tables.addCommand(applyClaySettings(buildUpdateCommand3()));
94095
+ program3.addCommand(tables);
94033
94096
  }
94034
94097
 
94035
94098
  // ../../libs/api-contract/src/webhooks/contract.ts
@@ -94280,9 +94343,7 @@ Examples:
94280
94343
  // src/commands/webhooks/index.ts
94281
94344
  function registerWebhooks(program3) {
94282
94345
  const webhooks = applyClaySettings(
94283
- new Command("webhooks").description(
94284
- "Manage webhooks in the authenticated workspace. Subcommands: create, list, delete, test."
94285
- )
94346
+ new Command("webhooks").summary("Manage webhooks.").description("Manage webhooks in the authenticated workspace. Subcommands: create, list, delete, test.")
94286
94347
  );
94287
94348
  webhooks.addHelpText(
94288
94349
  "after",
@@ -94305,7 +94366,7 @@ See \`clay webhooks <subcommand> --help\` for per-subcommand JSON shape, error c
94305
94366
 
94306
94367
  // src/commands/whoami.ts
94307
94368
  function registerWhoami(program3) {
94308
- program3.command("whoami").description(
94369
+ program3.command("whoami").summary("Print the authenticated user and workspace.").description(
94309
94370
  "Print the authenticated user and their workspace as JSON. Useful for confirming auth is set up, or for scripting on user identity."
94310
94371
  ).addHelpText(
94311
94372
  "after",
@@ -94354,6 +94415,7 @@ var CreditUsageBreakdownSchema = zod_default.object({
94354
94415
  audienceBulkEnrichmentTableId: zod_default.string().optional().transform((val) => val),
94355
94416
  audienceBulkEnrichmentTableCreditsUsed: zod_default.number().optional(),
94356
94417
  actionExecutionsUsed: zod_default.number().optional(),
94418
+ cpjAllowanceUsed: zod_default.number().optional(),
94357
94419
  budgetId: zod_default.string().optional(),
94358
94420
  budgetCreditsUsed: zod_default.number().optional()
94359
94421
  });
@@ -94568,6 +94630,22 @@ var RunCPJPreviewEnrichmentResponse = external_exports.object({
94568
94630
  });
94569
94631
 
94570
94632
  // ../../libs/api-contract/src/terracotta/clay-actions/contract.ts
94633
+ var ClayActionOutputParameter = external_exports.lazy(
94634
+ () => external_exports.object({
94635
+ name: external_exports.string(),
94636
+ displayName: external_exports.string().optional(),
94637
+ type: external_exports.string(),
94638
+ schema: external_exports.array(ClayActionOutputParameter).optional()
94639
+ })
94640
+ );
94641
+ var ClayActionOutputSchemasRequestBody = external_exports.object({
94642
+ requests: external_exports.array(external_exports.object({ packageId: external_exports.string(), actionKey: external_exports.string() }))
94643
+ });
94644
+ var ClayActionOutputSchemaItem = external_exports.object({
94645
+ packageId: external_exports.string(),
94646
+ actionKey: external_exports.string(),
94647
+ outputParameters: external_exports.array(ClayActionOutputParameter)
94648
+ });
94571
94649
  var terracottaClayActionsContract = {
94572
94650
  getClayActions: {
94573
94651
  method: "GET",
@@ -94611,6 +94689,20 @@ var terracottaClayActionsContract = {
94611
94689
  },
94612
94690
  summary: "Resolve dynamic select options / fields for Clay action parameters given chosen inputs",
94613
94691
  metadata: { team: "workflows" /* Workflows */ }
94692
+ },
94693
+ getClayActionOutputSchemas: {
94694
+ method: "POST",
94695
+ path: "/workspaces/:workspaceId/tc-clay-action-output-schemas",
94696
+ pathParams: external_exports.object({
94697
+ workspaceId: external_exports.string()
94698
+ }),
94699
+ body: ClayActionOutputSchemasRequestBody,
94700
+ responses: {
94701
+ 200: external_exports.array(ClayActionOutputSchemaItem),
94702
+ 404: external_exports.object({ error: external_exports.string() })
94703
+ },
94704
+ summary: "Get declared output field schemas for Clay actions (batch), from each action's output_parameter_schema",
94705
+ metadata: { team: "workflows" /* Workflows */ }
94614
94706
  }
94615
94707
  };
94616
94708
 
@@ -96345,6 +96437,7 @@ var SerializedWorkflowRun = external_exports.object({
96345
96437
  updatedAt: external_exports.string().datetime(),
96346
96438
  langsmithTraceHeader: external_exports.string().nullable().optional()
96347
96439
  });
96440
+ var WORKFLOW_RUN_LIST_MAX_PAGE_SIZE = 100;
96348
96441
  var WorkflowRunsFilterQuerySchema = external_exports.object({
96349
96442
  /** ISO datetime — runs with createdAt >= this instant */
96350
96443
  createdAfter: external_exports.string().datetime().optional(),
@@ -96357,7 +96450,9 @@ var WorkflowRunsFilterQuerySchema = external_exports.object({
96357
96450
  });
96358
96451
  var GetWorkflowRunsQuerySchema = WorkflowRunsFilterQuerySchema.extend({
96359
96452
  /** Opaque keyset cursor from previous response `nextCursor` */
96360
- cursor: external_exports.string().optional()
96453
+ cursor: external_exports.string().optional(),
96454
+ /** Page size; arrives as a string query param, capped at WORKFLOW_RUN_LIST_MAX_PAGE_SIZE. */
96455
+ limit: external_exports.coerce.number().int().positive().max(WORKFLOW_RUN_LIST_MAX_PAGE_SIZE).optional()
96361
96456
  });
96362
96457
  var GetWorkflowRunsResponseSchema = external_exports.object({
96363
96458
  runs: external_exports.array(SerializedWorkflowRun),
@@ -97042,12 +97137,17 @@ function getWaitingReason(step) {
97042
97137
  }
97043
97138
 
97044
97139
  // src/commands/workflows/runs/projection.ts
97045
- function projectRunStart(run) {
97140
+ function projectWorkflowRun(run) {
97046
97141
  return {
97047
97142
  runId: run.id,
97048
97143
  workflowId: run.workflowId,
97049
97144
  workflowName: run.workflowName,
97050
- status: run.runStatus
97145
+ status: run.runStatus,
97146
+ createdAt: run.createdAt,
97147
+ updatedAt: run.updatedAt,
97148
+ workflowSnapshotId: run.workflowSnapshotId,
97149
+ ...run.batchId != null ? { batchId: run.batchId } : {},
97150
+ ...run.triggerId != null ? { triggerId: run.triggerId } : {}
97051
97151
  };
97052
97152
  }
97053
97153
  function projectRunStateChange(body) {
@@ -97362,6 +97462,97 @@ Examples:
97362
97462
  return cmd;
97363
97463
  }
97364
97464
 
97465
+ // src/commands/workflows/runs/list.ts
97466
+ var RUN_STATUS_VALUES = Object.values(TCWorkflowRunStatus2.enum);
97467
+ function collectRunStatus(value, previous = []) {
97468
+ const parsed = TCWorkflowRunStatus2.safeParse(value);
97469
+ if (!parsed.success) {
97470
+ throw new InvalidArgumentError(`--status must be one of: ${RUN_STATUS_VALUES.join(", ")}`);
97471
+ }
97472
+ return [...previous, parsed.data];
97473
+ }
97474
+ function buildListCommand8() {
97475
+ const cmd = new Command("list");
97476
+ cmd.description("List runs of a workflow, newest first, with optional filters.").argument("<workflowId>", "Workflow id, e.g. wf_abc123").option("--status <status>", "Filter by run status. Repeatable to match any of several statuses.", collectRunStatus).option(
97477
+ "--created-after <datetime>",
97478
+ "Only runs created at or after this datetime",
97479
+ parseDatetimeFlag("--created-after")
97480
+ ).option("--snapshot-id <id>", "Only runs of this workflow snapshot version.").option("--search <text>", "Case-insensitive text search over run inputs, outputs, and error.").option("--cursor <token>", "Resume from a previous response's `cursor` to fetch the next page.").option(
97481
+ "--limit <n>",
97482
+ `Page size (1-${WORKFLOW_RUN_LIST_MAX_PAGE_SIZE}). Defaults to the server page size when omitted.`,
97483
+ parseLimitFlagWithMax(WORKFLOW_RUN_LIST_MAX_PAGE_SIZE)
97484
+ ).addHelpText(
97485
+ "after",
97486
+ `
97487
+ Output (success, exit 0):
97488
+ {
97489
+ "data": [
97490
+ {
97491
+ "runId": <string>,
97492
+ "workflowId": <string>,
97493
+ "workflowName": <string|null>,
97494
+ "status": <string>,
97495
+ "createdAt": <string>,
97496
+ "updatedAt": <string>,
97497
+ "workflowSnapshotId": <string>,
97498
+ "batchId": <string|undefined>,
97499
+ "triggerId": <string|undefined>
97500
+ }
97501
+ ],
97502
+ "cursor": <string|undefined>
97503
+ }
97504
+
97505
+ Status values:
97506
+ pending Run queued but not yet started.
97507
+ running Actively executing nodes.
97508
+ waiting Blocked on an async operation or concurrency slot.
97509
+ paused Paused by an operator \u2014 resume to continue.
97510
+ completed Finished successfully.
97511
+ failed Terminated with an error.
97512
+
97513
+ Pagination:
97514
+ --limit <n> server page size, 1-${WORKFLOW_RUN_LIST_MAX_PAGE_SIZE} (default 50 when omitted)
97515
+ --cursor <token> resume from a previous response's \`cursor\`
97516
+ When more results exist, the response includes a top-level \`cursor\`; pass it
97517
+ back via --cursor to fetch the next page.
97518
+
97519
+ Common errors:
97520
+ validation_error (exit 2) --status is not a known status, --created-after is not a valid datetime, or --limit is out of range.
97521
+ not_found (exit 6) No workflow with that id in this workspace.
97522
+ auth_forbidden (exit 3) Key lacks the terracotta:cli scope.
97523
+
97524
+ Examples:
97525
+ $ clay workflows runs list wf_abc123 | jq -r '.data[].runId'
97526
+ $ clay workflows runs list wf_abc123 --status failed
97527
+ $ clay workflows runs list wf_abc123 --status failed --status completed
97528
+ $ clay workflows runs list wf_abc123 --created-after 2026-06-01T00:00:00Z --search clay.com
97529
+ $ clay workflows runs list wf_abc123 --limit 200 | jq -r '.data[].runId'
97530
+ $ clay workflows runs list wf_abc123 --cursor "$CURSOR" | jq -r '.cursor'
97531
+ `
97532
+ ).action(async (workflowId, opts) => {
97533
+ const workspaceId = await currentWorkspaceId();
97534
+ const client = await v3Client(terracottaWorkflowExecutionContract);
97535
+ const result = await unwrap(
97536
+ client.getWorkflowRuns({
97537
+ params: { workspaceId, workflowId },
97538
+ query: {
97539
+ createdAfter: opts.createdAfter,
97540
+ runStatuses: opts.status,
97541
+ workflowSnapshotId: opts.snapshotId,
97542
+ searchQuery: opts.search,
97543
+ cursor: opts.cursor,
97544
+ limit: opts.limit
97545
+ }
97546
+ })
97547
+ );
97548
+ writeJson({
97549
+ data: result.runs.map(projectWorkflowRun),
97550
+ cursor: result.nextCursor ?? void 0
97551
+ });
97552
+ });
97553
+ return cmd;
97554
+ }
97555
+
97365
97556
  // src/commands/workflows/runs/pause.ts
97366
97557
  function buildPauseCommand() {
97367
97558
  const cmd = new Command("pause");
@@ -97441,7 +97632,12 @@ Output (success, exit 0):
97441
97632
  "runId": <string>,
97442
97633
  "workflowId": <string>,
97443
97634
  "workflowName": <string|null>,
97444
- "status": <string>
97635
+ "status": <string>,
97636
+ "createdAt": <string>,
97637
+ "updatedAt": <string>,
97638
+ "workflowSnapshotId": <string>,
97639
+ "batchId": <string|undefined>,
97640
+ "triggerId": <string|undefined>
97445
97641
  }
97446
97642
 
97447
97643
  Status values:
@@ -97468,7 +97664,7 @@ Examples:
97468
97664
  const workspaceId = await currentWorkspaceId();
97469
97665
  const client = await v3Client(terracottaWorkflowExecutionContract);
97470
97666
  const result = await unwrap(client.createWorkflowRun({ params: { workspaceId, workflowId }, body: { inputs } }));
97471
- writeJson(projectRunStart(result.workflowRun));
97667
+ writeJson(projectWorkflowRun(result.workflowRun));
97472
97668
  });
97473
97669
  return cmd;
97474
97670
  }
@@ -97564,6 +97760,7 @@ function buildRunsCommand2() {
97564
97760
  "after",
97565
97761
  `
97566
97762
  Subcommands:
97763
+ list List runs of a workflow, with filters.
97567
97764
  start Start a workflow run.
97568
97765
  get Fetch status, progress, and per-node summary for a run.
97569
97766
  steps List the individual execution steps of a run, with filters.
@@ -97571,11 +97768,13 @@ Subcommands:
97571
97768
  resume Resume a paused run.
97572
97769
 
97573
97770
  Examples:
97771
+ $ clay workflows runs list wf_abc123 | jq -r '.data[].runId'
97574
97772
  $ clay workflows runs start wf_abc123 | jq -r '.runId'
97575
97773
  $ echo '{"domain":"clay.com"}' | clay workflows runs start wf_abc123 --input -
97576
97774
  $ clay workflows runs get wf_abc123 wfr_xyz789 | jq -r '.status'
97577
97775
  `
97578
97776
  );
97777
+ cmd.addCommand(applyClaySettings(buildListCommand8()));
97579
97778
  cmd.addCommand(applyClaySettings(buildStartCommand2()));
97580
97779
  cmd.addCommand(applyClaySettings(buildGetCommand4()));
97581
97780
  cmd.addCommand(applyClaySettings(buildStepsCommand()));
@@ -97700,7 +97899,7 @@ Examples:
97700
97899
  }
97701
97900
 
97702
97901
  // src/commands/workflows/snapshots/list.ts
97703
- function buildListCommand8() {
97902
+ function buildListCommand9() {
97704
97903
  const cmd = new Command("list");
97705
97904
  cmd.description("List a workflow\u2019s snapshots (automatic version history), newest first.").argument("<workflowId>", "Workflow id, e.g. wf_abc123").addHelpText(
97706
97905
  "after",
@@ -97795,7 +97994,7 @@ Examples:
97795
97994
  $ clay workflows snapshots restore wf_abc123 snap_xyz
97796
97995
  `
97797
97996
  );
97798
- cmd.addCommand(applyClaySettings(buildListCommand8()));
97997
+ cmd.addCommand(applyClaySettings(buildListCommand9()));
97799
97998
  cmd.addCommand(applyClaySettings(buildGetCommand5()));
97800
97999
  cmd.addCommand(applyClaySettings(buildRestoreCommand()));
97801
98000
  return cmd;
@@ -97803,7 +98002,9 @@ Examples:
97803
98002
 
97804
98003
  // src/commands/workflows/index.ts
97805
98004
  function registerWorkflows(program3) {
97806
- const workflows = applyClaySettings(new Command("workflows").description("Manage Clay workflows and their runs."));
98005
+ const workflows = applyClaySettings(
98006
+ new Command("workflows").summary("Manage Clay workflows and runs.").description("Manage Clay workflows and their runs.")
98007
+ );
97807
98008
  workflows.addHelpText(
97808
98009
  "after",
97809
98010
  `
@@ -97827,6 +98028,28 @@ See \`clay workflows <subcommand> --help\` for per-subcommand JSON shape, error
97827
98028
  program3.addCommand(workflows);
97828
98029
  }
97829
98030
 
98031
+ // src/help-style.ts
98032
+ var RESET = "\x1B[0m";
98033
+ var BOLD = "\x1B[1m";
98034
+ var BOLD_UNDERLINE = "\x1B[1;4m";
98035
+ function stylingEnabled() {
98036
+ if (process.env.NO_COLOR !== void 0 && process.env.NO_COLOR !== "") return false;
98037
+ if (process.env.FORCE_COLOR !== void 0 && process.env.FORCE_COLOR !== "") return true;
98038
+ return Boolean(process.stdout.isTTY);
98039
+ }
98040
+ function styleHeader(text) {
98041
+ return stylingEnabled() ? `${BOLD_UNDERLINE}${text}${RESET}` : text;
98042
+ }
98043
+ function styleCommand(text) {
98044
+ return stylingEnabled() ? `${BOLD}${text}${RESET}` : text;
98045
+ }
98046
+ function formatHelpList(items) {
98047
+ const help = new Help();
98048
+ help.helpWidth = process.stdout.columns || 80;
98049
+ const termWidth = Math.max(...items.map((item) => help.displayWidth(item.term)));
98050
+ return items.map((item) => help.formatItem(styleCommand(item.term), termWidth, item.description, help)).join("\n");
98051
+ }
98052
+
97830
98053
  // src/index.ts
97831
98054
  initSentry();
97832
98055
  primeReportingScopeFromCache();
@@ -97847,63 +98070,96 @@ var COMMANDER_USAGE_CODES = /* @__PURE__ */ new Set([
97847
98070
  ]);
97848
98071
  var REPORTABLE_ERROR_CODES = /* @__PURE__ */ new Set(["internal_error", "contract_mismatch"]);
97849
98072
  var program2 = new Command();
97850
- program2.name("clay").description(
97851
- "Clay CLI \u2014 a JSON-first command-line interface for working with Clay. Every command emits structured JSON on stdout for success and a typed error envelope on stderr."
97852
- ).version(CLI_VERSION, "-v, --version", "print the CLI version and exit").showHelpAfterError(false).exitOverride().configureOutput({
98073
+ program2.name("clay").description("Clay CLI \u2014 a JSON-first command-line interface for working with Clay.").version(CLI_VERSION, "-v, --version", "print the CLI version and exit").showHelpAfterError(false).exitOverride().configureOutput({
97853
98074
  // eslint-disable-next-line @typescript-eslint/no-empty-function -- intentionally no-op: Commander's human-readable error text breaks the JSON-first stderr contract; the catch handler below emits a structured envelope instead
97854
98075
  outputError: () => {
97855
98076
  }
98077
+ }).configureHelp({
98078
+ styleTitle: styleHeader,
98079
+ // Bold the command name in the Commands list; leave its description plain.
98080
+ styleSubcommandTerm: styleCommand,
98081
+ // The root's description is rendered as a titled block above Usage (see the
98082
+ // 'beforeAll' text below), so suppress its default rendering between Usage
98083
+ // and Options to avoid showing it twice. Scope this to the root only:
98084
+ // chained subcommands inherit this help configuration, and we still want
98085
+ // each of them to show its own full description on its own help page.
98086
+ commandDescription: (cmd) => cmd === program2 ? "" : cmd.description()
97856
98087
  });
98088
+ program2.addHelpText(
98089
+ "beforeAll",
98090
+ `${styleHeader("Clay CLI")}
98091
+ A JSON-first command-line interface for working with Clay.
98092
+ `
98093
+ );
98094
+ var EXIT_CODE_HELP = formatHelpList([
98095
+ { term: "0", description: "success" },
98096
+ {
98097
+ term: "1",
98098
+ description: "generic / unrecoverable (server_error, contract_mismatch, conflict, internal_error, invalid_config_file, aborted)"
98099
+ },
98100
+ {
98101
+ term: "2",
98102
+ description: "validation_error | tty_required \u2014 input was rejected as malformed, or an interactive command was run without a TTY (use --stdin or similar)"
98103
+ },
98104
+ {
98105
+ term: "3",
98106
+ description: "auth_missing_api_key | auth_invalid | auth_forbidden \u2014 run `clay login` to (re)authenticate"
98107
+ },
98108
+ {
98109
+ term: "4",
98110
+ description: "rate_limited (HTTP 429) \u2014 details.retryAfter is set when Clay supplied a Retry-After header"
98111
+ },
98112
+ { term: "5", description: "network_error | network_timeout \u2014 could not reach Clay" },
98113
+ { term: "6", description: "not_found (HTTP 404)" }
98114
+ ]);
98115
+ var ENV_VAR_HELP = formatHelpList([
98116
+ { term: "CLAY_API_KEY", description: "API key used when none is stored by `clay login`; a stored key wins." },
98117
+ {
98118
+ term: "CLAY_CONFIG_HOME",
98119
+ description: "Config directory parent (default: `~/.config/clay`); also holds cache.json."
98120
+ },
98121
+ { term: "CLAY_REQUEST_TIMEOUT_MS", description: "Per-request network timeout in ms (default: 60000)." },
98122
+ { term: "CLAY_UPLOAD_TIMEOUT_MS", description: "Bulk file-upload timeout in ms (default: 600000)." }
98123
+ ]);
98124
+ var AUTH_HELP = formatHelpList([
98125
+ {
98126
+ term: "clay login [--stdin]",
98127
+ description: "Store an API key. Use --stdin for agents and CI (pipe the key to avoid a TTY prompt). Stored key takes precedence over CLAY_API_KEY."
98128
+ }
98129
+ ]);
98130
+ var OUTPUT_CONTRACT_HELP = formatHelpList([
98131
+ { term: "Success", description: "JSON written to stdout, exit code 0." },
98132
+ {
98133
+ term: "Failure",
98134
+ description: '{ "error": { "code", "message", "details"? } } written to stderr, with a non-zero exit code.'
98135
+ },
98136
+ { term: "Determinism", description: "No interactive output, spinners, colors, or progress bars on stdout/stderr." }
98137
+ ]);
97857
98138
  program2.addHelpText(
97858
98139
  "after",
97859
98140
  `
97860
- Output contract:
97861
- Success JSON written to stdout, exit code 0.
97862
- Failure { "error": { "code", "message", "details"? } } written to stderr, with a non-zero exit code.
97863
- Determinism No interactive output, spinners, colors, or progress bars on stdout/stderr.
97864
-
97865
- Exit codes (branch on these from agents and scripts):
97866
- 0 success
97867
- 1 generic / unrecoverable (server_error, contract_mismatch, conflict, internal_error, invalid_config_file, aborted)
97868
- 2 validation_error | tty_required \u2014 input was rejected as malformed, or an interactive command was run without a TTY (use --stdin or similar)
97869
- 3 auth_missing_api_key | auth_invalid | auth_forbidden \u2014 run \`clay login\` to (re)authenticate
97870
- 4 rate_limited (HTTP 429) \u2014 details.retryAfter is set when Clay supplied a Retry-After header
97871
- 5 network_error | network_timeout \u2014 could not reach Clay
97872
- 6 not_found (HTTP 404)
97873
-
97874
- Authentication:
97875
- Interactive (requires a TTY):
97876
- $ clay login
97877
- Non-interactive (preferred for agents and CI):
97878
- $ echo "$CLAY_API_KEY" | clay login --stdin
97879
- Sign out:
97880
- $ clay logout
97881
- The API key is stored at \`<config-dir>/config.json\` with mode 0600. The config directory resolves to:
97882
- 1. $CLAY_CONFIG_HOME/clay, if set
97883
- 2. $XDG_CONFIG_HOME/clay, if set
97884
- 3. ~/.config/clay (default)
97885
- If no key is stored, the CLI falls back to the CLAY_API_KEY environment variable (a stored key from \`clay login\` always wins). The env var is the right fit for agents and CI that already export it; the env path is not validated up front, so a bad key surfaces as auth_invalid on the first call.
97886
- Values derived from the key (e.g. the resolved workspace id) are cached alongside in \`<config-dir>/cache.json\`; it is disposable and safe to delete.
97887
-
97888
- Environment variables:
97889
- CLAY_API_KEY API key used when none is stored by \`clay login\`. A stored key takes precedence. Surfaces as auth_invalid (exit 3) on first use if invalid.
97890
- CLAY_CONFIG_HOME Override the parent of the config directory. The CLI appends \`clay/\` to it, matching XDG semantics. Useful for isolating tests or alternate setups. Both config.json and the sibling cache.json live under this directory.
97891
- CLAY_REQUEST_TIMEOUT_MS Per-request network timeout in milliseconds (default: 60000). Each HTTP request the CLI makes is bounded by this; on expiry the command fails with network_timeout (exit 5).
97892
- CLAY_UPLOAD_TIMEOUT_MS File-upload timeout in milliseconds (default: 600000). Bounds bulk file uploads (e.g. \`clay tools runs start --bulk\`), which move whole payloads and so get a longer budget than CLAY_REQUEST_TIMEOUT_MS; on expiry the command fails with network_timeout (exit 5).
98141
+ ${styleHeader("Output contract:")}
98142
+ ${OUTPUT_CONTRACT_HELP}
97893
98143
 
97894
- Examples:
98144
+ ${styleHeader("Exit codes (branch on these from agents and scripts):")}
98145
+ ${EXIT_CODE_HELP}
98146
+
98147
+ ${styleHeader("Environment variables:")}
98148
+ ${ENV_VAR_HELP}
98149
+
98150
+ ${styleHeader("Authentication:")}
98151
+ ${AUTH_HELP}
98152
+
98153
+ ${styleHeader("Examples:")}
97895
98154
  $ clay whoami | jq -r '.user.id'
97896
98155
  $ echo "$CLAY_API_KEY" | clay login --stdin && clay whoami
97897
98156
  $ cat query.json | clay tables query --input - | jq '.data | length'
97898
-
97899
- Per-command help:
97900
- $ clay <command> --help
97901
98157
  `
97902
98158
  );
97903
98159
  registerWhoami(program2);
97904
98160
  registerLogin(program2);
97905
98161
  registerLogout(program2);
97906
- registerTools(program2);
98162
+ registerRoutines(program2);
97907
98163
  registerTables(program2);
97908
98164
  registerWorkflows(program2);
97909
98165
  registerWebhooks(program2);