@eigenpal/cli 0.15.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -7685,6 +7685,7 @@ var init_common = __esm(() => {
7685
7685
  AUTOMATION_TRIGGER: "atr",
7686
7686
  FILE_SOURCE_CONFIG: "fsc",
7687
7687
  FILE_UPLOAD: "fup",
7688
+ EMAIL_SERVER: "ems",
7688
7689
  WEBHOOK_ENDPOINT: "whep",
7689
7690
  WEBHOOK_EVENT: "whev",
7690
7691
  WEBHOOK_DELIVERY: "whdl",
@@ -15429,6 +15430,250 @@ var init_validation = __esm(() => {
15429
15430
  init_workspace_schema();
15430
15431
  });
15431
15432
 
15433
+ // ../types/src/email-servers.ts
15434
+ function defaultSmtpPort(security, port) {
15435
+ return port ?? SMTP_DEFAULT_PORT_BY_SECURITY[security];
15436
+ }
15437
+ function refineSmtpCredentialPair(data, ctx) {
15438
+ const hasUsername = data.username !== undefined;
15439
+ const hasPassword = data.password !== undefined;
15440
+ if (hasUsername !== hasPassword) {
15441
+ ctx.addIssue({
15442
+ code: "custom",
15443
+ path: hasUsername ? ["password"] : ["username"],
15444
+ message: "SMTP username and password must both be set or both omitted"
15445
+ });
15446
+ }
15447
+ }
15448
+ function refineSmtpNoneRejectsCredentials(data, ctx) {
15449
+ if (data.security !== "none")
15450
+ return;
15451
+ if (typeof data.username === "string") {
15452
+ ctx.addIssue({
15453
+ code: "custom",
15454
+ path: ["username"],
15455
+ message: SMTP_NONE_CREDENTIALS_MESSAGE
15456
+ });
15457
+ }
15458
+ if (data.password !== undefined) {
15459
+ ctx.addIssue({
15460
+ code: "custom",
15461
+ path: ["password"],
15462
+ message: SMTP_NONE_CREDENTIALS_MESSAGE
15463
+ });
15464
+ }
15465
+ }
15466
+ function hasTransport(patch) {
15467
+ return "transport" in patch;
15468
+ }
15469
+ function smtpDestinationChanged(existingTransport, patch, storedSmtp) {
15470
+ if (existingTransport !== "smtp")
15471
+ return false;
15472
+ const hostChanged = storedSmtp?.host != null && storedSmtp.host !== patch.host;
15473
+ const usernameChanged = typeof patch.username === "string" && patch.username !== (storedSmtp?.username ?? null);
15474
+ return hostChanged || usernameChanged;
15475
+ }
15476
+ function planEmailServerSecretUpdate(input) {
15477
+ if (!hasTransport(input.patch)) {
15478
+ return { resendApiKey: "retain", smtpPassword: "retain", caPem: "retain" };
15479
+ }
15480
+ if (input.patch.transport === "resend") {
15481
+ return {
15482
+ resendApiKey: input.patch.apiKey !== undefined ? "set" : "retain",
15483
+ smtpPassword: "clear",
15484
+ caPem: "clear"
15485
+ };
15486
+ }
15487
+ const password = input.patch.password !== undefined ? "set" : input.patch.username === null ? "clear" : input.existingTransport !== "smtp" ? "clear" : smtpDestinationChanged(input.existingTransport, input.patch, input.storedSmtp) ? "clear" : "retain";
15488
+ const caPem = input.patch.caPem === null ? "clear" : input.patch.caPem !== undefined ? "set" : input.existingTransport === "smtp" ? "retain" : "clear";
15489
+ return {
15490
+ resendApiKey: "clear",
15491
+ smtpPassword: password,
15492
+ caPem
15493
+ };
15494
+ }
15495
+ function planSmtpAuthActions(existingTransport, patch, storedSmtp) {
15496
+ const secrets = planEmailServerSecretUpdate({ existingTransport, storedSmtp, patch });
15497
+ const username = patch.username === null ? "clear" : typeof patch.username === "string" ? "set" : existingTransport === "smtp" ? "retain" : "clear";
15498
+ return { username, password: secrets.smtpPassword };
15499
+ }
15500
+ function actionLeavesPresent(action, storedPresent) {
15501
+ if (action === "set")
15502
+ return true;
15503
+ if (action === "clear")
15504
+ return false;
15505
+ return storedPresent;
15506
+ }
15507
+ function getEmailServerUpdateError(existingTransport, patch, storedSmtp) {
15508
+ if (hasTransport(patch) && patch.transport === "smtp") {
15509
+ const auth = planSmtpAuthActions(existingTransport, patch, storedSmtp);
15510
+ const hasUsername = actionLeavesPresent(auth.username, Boolean(storedSmtp?.username));
15511
+ const hasPassword = actionLeavesPresent(auth.password, storedSmtp?.passwordConfigured === true);
15512
+ if (patch.security === "none" && (hasUsername || hasPassword)) {
15513
+ return SMTP_NONE_CREDENTIALS_MESSAGE;
15514
+ }
15515
+ if (smtpDestinationChanged(existingTransport, patch, storedSmtp) && patch.password === undefined && hasUsername && storedSmtp?.passwordConfigured === true) {
15516
+ return SMTP_TARGET_PASSWORD_MESSAGE;
15517
+ }
15518
+ if (hasUsername !== hasPassword) {
15519
+ return SMTP_CREDENTIAL_PAIR_MESSAGE;
15520
+ }
15521
+ }
15522
+ if (!hasTransport(patch))
15523
+ return null;
15524
+ if (patch.transport === existingTransport)
15525
+ return null;
15526
+ if (patch.transport === "resend" && patch.apiKey === undefined) {
15527
+ return "Resend API key is required when changing transport to resend";
15528
+ }
15529
+ return null;
15530
+ }
15531
+ var EMAIL_SERVER_TRANSPORTS, SMTP_SECURITY_MODES, SMTP_DEFAULT_PORT_BY_SECURITY, EMAIL_SERVER_ID_PREFIX, EMAIL_SERVER_ID_PATTERN, EmailServerIdSchema, EmailServerNameSchema, EmailServerFromEmailSchema, FROM_NAME_UNSAFE, EmailServerFromNameSchema, SmtpHostSchema, SmtpPortSchema, SmtpSecuritySchema, SmtpUsernameSchema, SecretStringSchema, fromFields, SMTP_NONE_CREDENTIALS_MESSAGE = "SMTP credentials cannot be used with security 'none'", SMTP_CREDENTIAL_PAIR_MESSAGE = "SMTP username and password must both be present or both absent", SMTP_TARGET_PASSWORD_MESSAGE = "A new SMTP password is required when the host or username changes", CreateResendEmailServerRequestSchema, CreateSmtpEmailServerRequestSchema, CreateEmailServerRequestSchema, UpdateMetadataOnlySchema, UpdateResendEmailServerRequestSchema, UpdateSmtpEmailServerRequestSchema, UpdateEmailServerRequestSchema, PublicEmailServerTimestamps, PublicResendEmailServerSchema, PublicSmtpEmailServerSchema, EmailServerSchema, ListEmailServersResponseSchema, DeleteEmailServerResponseSchema, TestEmailServerRequestSchema, TestEmailServerResponseSchema;
15532
+ var init_email_servers = __esm(() => {
15533
+ init_zod();
15534
+ init_common();
15535
+ EMAIL_SERVER_TRANSPORTS = ["resend", "smtp"];
15536
+ SMTP_SECURITY_MODES = ["starttls", "tls", "none"];
15537
+ SMTP_DEFAULT_PORT_BY_SECURITY = {
15538
+ starttls: 587,
15539
+ tls: 465,
15540
+ none: 25
15541
+ };
15542
+ EMAIL_SERVER_ID_PREFIX = ID_PREFIXES.EMAIL_SERVER;
15543
+ EMAIL_SERVER_ID_PATTERN = /^ems_[A-Za-z0-9_-]+$/;
15544
+ EmailServerIdSchema = string2().regex(EMAIL_SERVER_ID_PATTERN, "Expected ems_… id").max(128);
15545
+ EmailServerNameSchema = string2().trim().min(1).max(128);
15546
+ EmailServerFromEmailSchema = string2().trim().email();
15547
+ FROM_NAME_UNSAFE = /[\p{Cc}<>]/u;
15548
+ EmailServerFromNameSchema = string2().trim().min(1).max(128).refine((value) => !FROM_NAME_UNSAFE.test(value), {
15549
+ message: "fromName cannot contain control characters or angle brackets"
15550
+ });
15551
+ SmtpHostSchema = string2().trim().min(1).max(253);
15552
+ SmtpPortSchema = number2().int().min(1).max(65535);
15553
+ SmtpSecuritySchema = _enum(SMTP_SECURITY_MODES);
15554
+ SmtpUsernameSchema = string2().min(1).max(256);
15555
+ SecretStringSchema = string2().min(1);
15556
+ fromFields = {
15557
+ fromEmail: EmailServerFromEmailSchema,
15558
+ fromName: EmailServerFromNameSchema
15559
+ };
15560
+ CreateResendEmailServerRequestSchema = object({
15561
+ name: EmailServerNameSchema,
15562
+ enabled: boolean2().optional().default(true),
15563
+ transport: literal("resend"),
15564
+ apiKey: SecretStringSchema,
15565
+ ...fromFields
15566
+ }).strict();
15567
+ CreateSmtpEmailServerRequestSchema = object({
15568
+ name: EmailServerNameSchema,
15569
+ enabled: boolean2().optional().default(true),
15570
+ transport: literal("smtp"),
15571
+ host: SmtpHostSchema,
15572
+ port: SmtpPortSchema.optional(),
15573
+ security: SmtpSecuritySchema.optional().default("starttls"),
15574
+ username: SmtpUsernameSchema.optional(),
15575
+ password: SecretStringSchema.optional(),
15576
+ caPem: SecretStringSchema.optional(),
15577
+ ...fromFields
15578
+ }).strict().superRefine((data, ctx) => {
15579
+ refineSmtpCredentialPair(data, ctx);
15580
+ refineSmtpNoneRejectsCredentials(data, ctx);
15581
+ }).transform((data) => ({
15582
+ ...data,
15583
+ port: defaultSmtpPort(data.security, data.port)
15584
+ }));
15585
+ CreateEmailServerRequestSchema = discriminatedUnion("transport", [
15586
+ CreateResendEmailServerRequestSchema,
15587
+ CreateSmtpEmailServerRequestSchema
15588
+ ]).meta({ id: "CreateEmailServerRequest" });
15589
+ UpdateMetadataOnlySchema = object({
15590
+ name: EmailServerNameSchema.optional(),
15591
+ enabled: boolean2().optional()
15592
+ }).strict().superRefine((value, ctx) => {
15593
+ if (value.name === undefined && value.enabled === undefined) {
15594
+ ctx.addIssue({
15595
+ code: "custom",
15596
+ message: "at least one field is required"
15597
+ });
15598
+ }
15599
+ });
15600
+ UpdateResendEmailServerRequestSchema = object({
15601
+ name: EmailServerNameSchema.optional(),
15602
+ enabled: boolean2().optional(),
15603
+ transport: literal("resend"),
15604
+ apiKey: SecretStringSchema.optional(),
15605
+ ...fromFields
15606
+ }).strict();
15607
+ UpdateSmtpEmailServerRequestSchema = object({
15608
+ name: EmailServerNameSchema.optional(),
15609
+ enabled: boolean2().optional(),
15610
+ transport: literal("smtp"),
15611
+ host: SmtpHostSchema,
15612
+ port: SmtpPortSchema,
15613
+ security: SmtpSecuritySchema,
15614
+ username: SmtpUsernameSchema.nullable().optional(),
15615
+ password: SecretStringSchema.optional(),
15616
+ caPem: SecretStringSchema.nullable().optional(),
15617
+ ...fromFields
15618
+ }).strict().superRefine(refineSmtpNoneRejectsCredentials);
15619
+ UpdateEmailServerRequestSchema = union([
15620
+ UpdateResendEmailServerRequestSchema,
15621
+ UpdateSmtpEmailServerRequestSchema,
15622
+ UpdateMetadataOnlySchema
15623
+ ]).meta({ id: "UpdateEmailServerRequest" });
15624
+ PublicEmailServerTimestamps = {
15625
+ id: EmailServerIdSchema,
15626
+ name: EmailServerNameSchema,
15627
+ enabled: boolean2(),
15628
+ createdAt: union([string2(), exports_coerce.date()]),
15629
+ updatedAt: union([string2(), exports_coerce.date()])
15630
+ };
15631
+ PublicResendEmailServerSchema = object({
15632
+ ...PublicEmailServerTimestamps,
15633
+ transport: literal("resend"),
15634
+ fromEmail: EmailServerFromEmailSchema,
15635
+ fromName: EmailServerFromNameSchema,
15636
+ apiKeyConfigured: literal(true)
15637
+ }).strict().meta({ id: "PublicResendEmailServer" });
15638
+ PublicSmtpEmailServerSchema = object({
15639
+ ...PublicEmailServerTimestamps,
15640
+ transport: literal("smtp"),
15641
+ fromEmail: EmailServerFromEmailSchema,
15642
+ fromName: EmailServerFromNameSchema,
15643
+ host: SmtpHostSchema,
15644
+ port: SmtpPortSchema,
15645
+ security: SmtpSecuritySchema,
15646
+ username: string2().nullable(),
15647
+ passwordConfigured: boolean2(),
15648
+ caPemConfigured: boolean2()
15649
+ }).strict().meta({ id: "PublicSmtpEmailServer" });
15650
+ EmailServerSchema = discriminatedUnion("transport", [PublicResendEmailServerSchema, PublicSmtpEmailServerSchema]).meta({ id: "EmailServer" });
15651
+ ListEmailServersResponseSchema = object({
15652
+ data: array(EmailServerSchema),
15653
+ total: number2().int(),
15654
+ limit: number2().int(),
15655
+ offset: number2().int()
15656
+ }).meta({ id: "ListEmailServersResponse" });
15657
+ DeleteEmailServerResponseSchema = object({
15658
+ deleted: literal(true),
15659
+ id: EmailServerIdSchema
15660
+ }).strict().meta({ id: "DeleteEmailServerResponse" });
15661
+ TestEmailServerRequestSchema = object({
15662
+ to: EmailServerFromEmailSchema
15663
+ }).strict().meta({ id: "TestEmailServerRequest" });
15664
+ TestEmailServerResponseSchema = discriminatedUnion("ok", [
15665
+ object({
15666
+ ok: literal(true),
15667
+ transport: _enum(EMAIL_SERVER_TRANSPORTS),
15668
+ messageId: string2().min(1)
15669
+ }).strict(),
15670
+ object({
15671
+ ok: literal(false),
15672
+ error: string2().min(1)
15673
+ }).strict()
15674
+ ]).meta({ id: "TestEmailServerResponse" });
15675
+ });
15676
+
15432
15677
  // ../../node_modules/@babel/parser/lib/index.js
15433
15678
  var require_lib = __commonJS(function(exports) {
15434
15679
  Object.defineProperty(exports, "__esModule", {
@@ -52892,6 +53137,61 @@ var init_typed_script = __esm(() => {
52892
53137
  init_compile();
52893
53138
  });
52894
53139
 
53140
+ // ../types/src/workflow/email-recipients.ts
53141
+ function splitRecipientTokens(value) {
53142
+ const tokens = [];
53143
+ let start = 0;
53144
+ let templateClose;
53145
+ for (let index = 0;index < value.length; index++) {
53146
+ if (templateClose) {
53147
+ if (value.startsWith(templateClose, index)) {
53148
+ index++;
53149
+ templateClose = undefined;
53150
+ }
53151
+ continue;
53152
+ }
53153
+ if (value.startsWith("{{", index)) {
53154
+ templateClose = "}}";
53155
+ index++;
53156
+ continue;
53157
+ }
53158
+ if (value.startsWith("{%", index)) {
53159
+ templateClose = "%}";
53160
+ index++;
53161
+ continue;
53162
+ }
53163
+ if (value[index] === ",") {
53164
+ tokens.push(value.slice(start, index));
53165
+ start = index + 1;
53166
+ }
53167
+ }
53168
+ tokens.push(value.slice(start));
53169
+ return tokens;
53170
+ }
53171
+ function countDeterministicEmailRecipients(value) {
53172
+ if (value === undefined || value === null)
53173
+ return 0;
53174
+ const parts = Array.isArray(value) ? value : [value];
53175
+ let count = 0;
53176
+ for (const part of parts) {
53177
+ if (typeof part !== "string")
53178
+ continue;
53179
+ const tokens = splitRecipientTokens(part).map((token) => token.trim()).filter((token) => token.length > 0);
53180
+ count += tokens.length;
53181
+ }
53182
+ return count;
53183
+ }
53184
+ function countActionEmailRecipients(fields) {
53185
+ return countDeterministicEmailRecipients(fields.to) + countDeterministicEmailRecipients(fields.cc) + countDeterministicEmailRecipients(fields.bcc);
53186
+ }
53187
+ function actionEmailRecipientCountExceedsLimit(fields) {
53188
+ return countActionEmailRecipients(fields) > ACTION_EMAIL_MAX_RECIPIENTS;
53189
+ }
53190
+ var ACTION_EMAIL_MAX_RECIPIENTS = 10, ACTION_EMAIL_RECIPIENT_LIMIT_MESSAGE;
53191
+ var init_email_recipients = __esm(() => {
53192
+ ACTION_EMAIL_RECIPIENT_LIMIT_MESSAGE = `At most ${ACTION_EMAIL_MAX_RECIPIENTS} recipients combined across to, cc, and bcc`;
53193
+ });
53194
+
52895
53195
  // ../types/src/workflow/script-function.ts
52896
53196
  var SCRIPT_FN_MAX_BYTES = 50000;
52897
53197
 
@@ -52998,7 +53298,8 @@ var init_steps = __esm(() => {
52998
53298
  ACTION_STEP_TYPES = [
52999
53299
  "action.http",
53000
53300
  "action.invoke-workflow",
53001
- "action.website-reader"
53301
+ "action.website-reader",
53302
+ "action.email"
53002
53303
  ];
53003
53304
  CONTROL_STEP_TYPES = [
53004
53305
  "control.if",
@@ -53128,15 +53429,17 @@ function getStepSchema(stepType) {
53128
53429
  function listStepTypes() {
53129
53430
  return [...STEP_TYPES];
53130
53431
  }
53131
- var OptionalReasoningEffortSchema, AiParseConfigSchema, AiParseOutputSchema, AiExtractConfigSchema, AiExtractOutputSchema, VisionPageRangeSchema, AiVisionConfigSchema, AiVisionOutputSchema, AiSplitConfigSchema, AiSplitSectionSchema, AiSplitOutputSchema, AiSegmentConfigSchema, AiSegmentOutputSchema, AiClassifyConfigSchema, AiClassifyOutputSchema, ClassifyPagesLabelSchema2, AiClassifyPagesConfigSchema, AiClassifyPagesOutputSchema, TransformSetConfigSchema, TransformSetOutputSchema, TransformRemoveConfigSchema, TransformRemoveOutputSchema, TransformCombineConfigSchema, TransformCombineOutputSchema, TransformSplitConfigSchema, TransformSplitOutputSchema, TransformMergeConfigSchema, TransformMergeOutputSchema, TransformTemplateConfigSchema, TransformTemplateOutputSchema, TransformPdfEmbedConfigSchema, TransformPdfEmbedOutputSchema, TransformXlsxToJsonConfigSchema, TransformXlsxToJsonOutputSchema, JsonToXlsxAuthoringRowsSchema, JsonToXlsxSheetConfigSchema, TransformJsonToXlsxConfigSchema, TransformJsonToXlsxOutputSchema, TransformScriptConfigSchema, TransformScriptOutputSchema, ParsedDocPageSchema, TransformTextChunkerConfigSchema, TransformTextChunkerOutputSchema, RegexNormalizerSchema, RegexFormatSchema, REGEX_FLAGS, RegexFieldSchema, TransformRegexExtractConfigSchema, TransformRegexExtractOutputSchema, ActionHttpConfigSchema, ActionHttpOutputSchema, ActionInvokeWorkflowConfigSchema, ActionInvokeWorkflowOutputSchema, ActionWebsiteReaderConfigSchema, ActionWebsiteReaderOutputSchema, ControlIfConfigSchema, ControlIfOutputSchema, ControlSwitchConfigSchema, ControlSwitchOutputSchema, ControlForeachConfigSchema, ControlForeachOutputSchema, ControlParallelMapConfigSchema, ControlParallelMapOutputSchema, ControlParallelConfigSchema, ControlParallelOutputSchema, ControlWaitConfigSchema, ControlWaitOutputSchema, ControlFailConfigSchema, ControlFailOutputSchema, STEP_SCHEMAS;
53432
+ var OptionalReasoningEffortSchema, AiParseConfigSchema, AiParseOutputSchema, AiExtractConfigSchema, AiExtractOutputSchema, VisionPageRangeSchema, AiVisionConfigSchema, AiVisionOutputSchema, AiSplitConfigSchema, AiSplitSectionSchema, AiSplitOutputSchema, AiSegmentConfigSchema, AiSegmentOutputSchema, AiClassifyConfigSchema, AiClassifyOutputSchema, ClassifyPagesLabelSchema2, AiClassifyPagesConfigSchema, AiClassifyPagesOutputSchema, TransformSetConfigSchema, TransformSetOutputSchema, TransformRemoveConfigSchema, TransformRemoveOutputSchema, TransformCombineConfigSchema, TransformCombineOutputSchema, TransformSplitConfigSchema, TransformSplitOutputSchema, TransformMergeConfigSchema, TransformMergeOutputSchema, TransformTemplateConfigSchema, TransformTemplateOutputSchema, TransformPdfEmbedConfigSchema, TransformPdfEmbedOutputSchema, TransformXlsxToJsonConfigSchema, TransformXlsxToJsonOutputSchema, JsonToXlsxAuthoringRowsSchema, JsonToXlsxSheetConfigSchema, TransformJsonToXlsxConfigSchema, TransformJsonToXlsxOutputSchema, TransformScriptConfigSchema, TransformScriptOutputSchema, ParsedDocPageSchema, TransformTextChunkerConfigSchema, TransformTextChunkerOutputSchema, RegexNormalizerSchema, RegexFormatSchema, REGEX_FLAGS, RegexFieldSchema, TransformRegexExtractConfigSchema, TransformRegexExtractOutputSchema, ActionHttpConfigSchema, ActionHttpOutputSchema, ActionInvokeWorkflowConfigSchema, ActionInvokeWorkflowOutputSchema, ActionWebsiteReaderConfigSchema, ActionWebsiteReaderOutputSchema, ACTION_EMAIL_MAX_ATTACHMENTS = 10, ACTION_EMAIL_MAX_ATTACHMENT_BYTES, ACTION_EMAIL_BODY_MAX_BYTES, emailBodyMaxBytes = (value) => new TextEncoder().encode(value).byteLength <= ACTION_EMAIL_BODY_MAX_BYTES, ActionEmailRecipientListSchema, ActionEmailToSchema, ActionEmailOptionalRecipientsSchema, ActionEmailAttachmentSchema, ActionEmailConfigSchema, ActionEmailOutputSchema, ControlIfConfigSchema, ControlIfOutputSchema, ControlSwitchConfigSchema, ControlSwitchOutputSchema, ControlForeachConfigSchema, ControlForeachOutputSchema, ControlParallelMapConfigSchema, ControlParallelMapOutputSchema, ControlParallelConfigSchema, ControlParallelOutputSchema, ControlWaitConfigSchema, ControlWaitOutputSchema, ControlFailConfigSchema, ControlFailOutputSchema, STEP_SCHEMAS;
53132
53433
  var init_step_configs = __esm(() => {
53133
53434
  init_zod();
53134
53435
  init_ai_client();
53135
53436
  init_common();
53437
+ init_email_servers();
53136
53438
  init_parser();
53137
53439
  init_json_to_xlsx();
53138
53440
  init_xlsx_to_json();
53139
53441
  init_typed_script();
53442
+ init_email_recipients();
53140
53443
  init_steps();
53141
53444
  OptionalReasoningEffortSchema = ReasoningEffortSchema.optional().describe("Reasoning effort for models that support it. Omit to preserve the current provider default.");
53142
53445
  AiParseConfigSchema = object({
@@ -53661,6 +53964,54 @@ var init_step_configs = __esm(() => {
53661
53964
  length: number2().describe("Content length in characters"),
53662
53965
  url: string2().describe("Final URL after redirects")
53663
53966
  });
53967
+ ACTION_EMAIL_MAX_ATTACHMENT_BYTES = 12 * 1024 * 1024;
53968
+ ACTION_EMAIL_BODY_MAX_BYTES = 50 * 1024;
53969
+ ActionEmailRecipientListSchema = array(string2().min(1));
53970
+ ActionEmailToSchema = union([
53971
+ string2().min(1, "To is required"),
53972
+ ActionEmailRecipientListSchema.min(1, "To requires at least one recipient")
53973
+ ]);
53974
+ ActionEmailOptionalRecipientsSchema = union([
53975
+ string2().min(1),
53976
+ ActionEmailRecipientListSchema
53977
+ ]);
53978
+ ActionEmailAttachmentSchema = union([
53979
+ string2().min(1).describe("File id or template expression that resolves to a file id"),
53980
+ object({
53981
+ fileId: string2().min(1).describe("File id or template expression that resolves to a file id"),
53982
+ filename: string2().min(1).optional().describe("Optional download filename override")
53983
+ })
53984
+ ]);
53985
+ ActionEmailConfigSchema = object({
53986
+ server: EmailServerIdSchema.describe("Outbound email server id (`ems_…`)"),
53987
+ to: ActionEmailToSchema.describe("Primary recipient(s). String, comma-separated list, or nonempty string array. Combined with cc and bcc, at most 10 recipients."),
53988
+ cc: ActionEmailOptionalRecipientsSchema.optional().describe("Carbon-copy recipient(s). String, comma-separated list, or string array. Combined with to and bcc, at most 10 recipients."),
53989
+ bcc: ActionEmailOptionalRecipientsSchema.optional().describe("Blind carbon-copy recipient(s). String, comma-separated list, or string array. Combined with to and cc, at most 10 recipients."),
53990
+ replyTo: string2().min(1).optional().describe("Reply-To address (supports template expressions)"),
53991
+ subject: string2().min(1, "Subject is required").describe("Email subject"),
53992
+ text: string2().min(1, "Body is required").refine(emailBodyMaxBytes, {
53993
+ message: `Email body must be at most ${ACTION_EMAIL_BODY_MAX_BYTES} bytes`
53994
+ }).describe("Plain-text email body (max 50KiB)"),
53995
+ attachments: array(ActionEmailAttachmentSchema).max(ACTION_EMAIL_MAX_ATTACHMENTS, `At most ${ACTION_EMAIL_MAX_ATTACHMENTS} attachments`).optional().describe("Optional same-run attachments as { fileId, filename? } or a bare fileId string (12MiB combined)")
53996
+ }).superRefine((config, ctx) => {
53997
+ if (actionEmailRecipientCountExceedsLimit(config)) {
53998
+ ctx.addIssue({
53999
+ code: "custom",
54000
+ message: ACTION_EMAIL_RECIPIENT_LIMIT_MESSAGE,
54001
+ path: ["to"]
54002
+ });
54003
+ }
54004
+ });
54005
+ ActionEmailOutputSchema = object({
54006
+ serverId: EmailServerIdSchema.describe("Email server that sent (or would have sent) the message"),
54007
+ messageId: string2().nullable().describe("Provider message id. Null when delivery was skipped (evaluation runs)."),
54008
+ provider: _enum(["resend", "smtp"]).nullable().describe("Email provider that sent the message. Null when delivery was skipped."),
54009
+ to: array(string2()).describe("Normalized To recipients"),
54010
+ cc: array(string2()).describe("Normalized Cc recipients"),
54011
+ bcc: array(string2()).describe("Normalized Bcc recipients"),
54012
+ attachmentCount: number2().int().nonnegative().describe("Number of attachments sent"),
54013
+ totalBytes: number2().int().nonnegative().describe("Total attachment size in bytes")
54014
+ });
53664
54015
  ControlIfConfigSchema = object({
53665
54016
  condition: string2().min(1, "Condition is required").describe("LiquidJS expression that evaluates to boolean")
53666
54017
  });
@@ -53914,6 +54265,15 @@ var init_step_configs = __esm(() => {
53914
54265
  outputSchema: ActionWebsiteReaderOutputSchema,
53915
54266
  configInWith: true
53916
54267
  },
54268
+ "action.email": {
54269
+ type: "action.email",
54270
+ category: "action",
54271
+ name: "Send Email",
54272
+ description: "Send an email with optional attachments via a selected email server. At most 10 recipients combined across to, cc, and bcc.",
54273
+ configSchema: ActionEmailConfigSchema,
54274
+ outputSchema: ActionEmailOutputSchema,
54275
+ configInWith: true
54276
+ },
53917
54277
  "control.if": {
53918
54278
  type: "control.if",
53919
54279
  category: "control",
@@ -55423,6 +55783,7 @@ var init_src = __esm(() => {
55423
55783
  init_eval();
55424
55784
  init_git_source();
55425
55785
  init_triggers();
55786
+ init_email_servers();
55426
55787
  init_webhooks();
55427
55788
  init_typed_script();
55428
55789
  });
@@ -205368,7 +205729,7 @@ import { fileURLToPath as fileURLToPath8 } from "url";
205368
205729
  // package.json
205369
205730
  var package_default = {
205370
205731
  name: "@eigenpal/cli",
205371
- version: "0.15.1",
205732
+ version: "0.16.0",
205372
205733
  description: "Eigenpal CLI — author and run document workflows from your terminal. Agent-ready.",
205373
205734
  keywords: [
205374
205735
  "eigenpal",
@@ -240643,18 +241004,471 @@ function matchingSnippet(content, terms) {
240643
241004
  return line.replace(/^[#>*\s-]+/, "").replace(/[`[\]{}]/g, "").trim().slice(0, 140);
240644
241005
  }
240645
241006
 
241007
+ // src/lib/api-paths.ts
241008
+ var API_PREFIX = "/v1";
241009
+ function apiPath(suffix) {
241010
+ if (suffix === "/v1" || suffix.startsWith("/v1/"))
241011
+ return suffix;
241012
+ if (suffix === "/api/v1" || suffix.startsWith("/api/v1/")) {
241013
+ return `${API_PREFIX}${suffix.slice("/api/v1".length)}`;
241014
+ }
241015
+ const normalized = suffix.startsWith("/") ? suffix : `/${suffix}`;
241016
+ return `${API_PREFIX}${normalized}`;
241017
+ }
241018
+
241019
+ // src/lib/email-servers-cli.ts
241020
+ init_src();
241021
+ import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
241022
+ import { resolve as resolve4 } from "node:path";
241023
+ var SECRET_KEYS = new Set(["apiKey", "password", "caPem", "ciphertext"]);
241024
+ var SMTP_UPDATE_TARGET_FIELDS = ["host", "port", "security", "fromEmail", "fromName"];
241025
+ var SMTP_UPDATE_FLAG_BY_FIELD = {
241026
+ host: "--host",
241027
+ port: "--port",
241028
+ security: "--security",
241029
+ fromEmail: "--from-email",
241030
+ fromName: "--from-name"
241031
+ };
241032
+ function assertCompleteSmtpUpdateTarget(body) {
241033
+ if (body.transport !== "smtp")
241034
+ return;
241035
+ const missing = SMTP_UPDATE_TARGET_FIELDS.filter((field) => body[field] === undefined || body[field] === "");
241036
+ if (missing.length === 0)
241037
+ return;
241038
+ const flags = missing.map((field) => SMTP_UPDATE_FLAG_BY_FIELD[field]).join(", ");
241039
+ throw new Error(`SMTP updates that set --transport smtp require a complete target (host, port, security, from-email, from-name). Missing: ${flags}. Update does not default --security/--port (create still defaults to starttls and the matching port). Metadata-only updates omit --transport.`);
241040
+ }
241041
+ function countTruthy(values) {
241042
+ return values.filter(Boolean).length;
241043
+ }
241044
+ function assertExclusiveConfigSource(explicitFieldCount, opts, command) {
241045
+ const configSources = countTruthy([opts.configJson, opts.configFile]);
241046
+ if (configSources > 1) {
241047
+ throw new Error("Pass only one of --config-json or --config-file.");
241048
+ }
241049
+ if (configSources > 0 && explicitFieldCount > 0) {
241050
+ throw new Error(`${command} accepts either explicit flags or --config-json/--config-file, not both.`);
241051
+ }
241052
+ if (configSources === 0 && explicitFieldCount === 0 && command === "create") {
241053
+ throw new Error("create requires explicit fields or --config-json/--config-file (plus secret input for Resend or authenticated SMTP).");
241054
+ }
241055
+ }
241056
+ function readConfigObject(opts) {
241057
+ if (opts.configJson) {
241058
+ let parsed;
241059
+ try {
241060
+ parsed = JSON.parse(opts.configJson);
241061
+ } catch {
241062
+ throw new Error("--config-json must be valid JSON.");
241063
+ }
241064
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
241065
+ throw new Error("--config-json must be a JSON object.");
241066
+ }
241067
+ return parsed;
241068
+ }
241069
+ if (opts.configFile) {
241070
+ const filePath = opts.configFile === "-" ? undefined : resolve4(opts.configFile);
241071
+ let raw;
241072
+ try {
241073
+ raw = opts.configFile === "-" ? readFileSync14(0, "utf8") : readFileSync14(filePath, "utf8");
241074
+ } catch (err) {
241075
+ const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
241076
+ if (code === "ENOENT") {
241077
+ throw new Error(`Config file not found: ${resolve4(opts.configFile)}`);
241078
+ }
241079
+ throw err;
241080
+ }
241081
+ let parsed;
241082
+ try {
241083
+ parsed = JSON.parse(raw);
241084
+ } catch {
241085
+ throw new Error("--config-file must contain a JSON object.");
241086
+ }
241087
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
241088
+ throw new Error("--config-file must contain a JSON object.");
241089
+ }
241090
+ return parsed;
241091
+ }
241092
+ return {};
241093
+ }
241094
+ function rejectInlineSecrets(body) {
241095
+ for (const key of SECRET_KEYS) {
241096
+ if (key in body && body[key] != null) {
241097
+ throw new Error(`Secret field "${key}" cannot be set in --config-json/--config-file. Use the matching *-stdin or *-file flag, or answer the secure prompt.`);
241098
+ }
241099
+ }
241100
+ }
241101
+ async function readSecretInput2(label, opts, required) {
241102
+ const selected = countTruthy([opts.stdin, opts.file]);
241103
+ if (selected > 1) {
241104
+ throw new Error(`Pass only one of --${label}-stdin or --${label}-file.`);
241105
+ }
241106
+ if (opts.stdin) {
241107
+ return readFileSync14(0, "utf8").replace(/\n$/, "");
241108
+ }
241109
+ if (opts.file) {
241110
+ const filePath = opts.file === "-" ? undefined : resolve4(opts.file);
241111
+ try {
241112
+ return (opts.file === "-" ? readFileSync14(0, "utf8") : readFileSync14(filePath, "utf8")).replace(/\n$/, "");
241113
+ } catch (err) {
241114
+ const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
241115
+ if (code === "ENOENT") {
241116
+ throw new Error(`Secret file not found: ${resolve4(opts.file)}`);
241117
+ }
241118
+ throw err;
241119
+ }
241120
+ }
241121
+ if (!required)
241122
+ return;
241123
+ if (process.stdin.isTTY && process.stdout.isTTY) {
241124
+ await Promise.resolve().then(() => init_dist4());
241125
+ const answer = await Ce({ message: `${label} (input hidden)` });
241126
+ if (q(answer)) {
241127
+ me("Cancelled");
241128
+ process.exit(1);
241129
+ }
241130
+ return String(answer);
241131
+ }
241132
+ throw new Error(`${label} is required in noninteractive mode (use --${label}-stdin or --${label}-file).`);
241133
+ }
241134
+ function parseEnabled(opts) {
241135
+ if (opts.enabled && opts.disabled) {
241136
+ throw new Error("Pass only one of --enabled or --disabled.");
241137
+ }
241138
+ if (opts.disabled)
241139
+ return false;
241140
+ if (opts.enabled)
241141
+ return true;
241142
+ return;
241143
+ }
241144
+ async function buildCreateRequest(opts) {
241145
+ const explicitCount = countTruthy([
241146
+ opts.name,
241147
+ opts.transport,
241148
+ opts.fromEmail,
241149
+ opts.fromName,
241150
+ opts.enabled,
241151
+ opts.disabled,
241152
+ opts.host,
241153
+ opts.port,
241154
+ opts.security,
241155
+ opts.username
241156
+ ]);
241157
+ assertExclusiveConfigSource(explicitCount, opts, "create");
241158
+ const body = {};
241159
+ if (countTruthy([opts.configJson, opts.configFile]) > 0) {
241160
+ Object.assign(body, readConfigObject(opts));
241161
+ rejectInlineSecrets(body);
241162
+ }
241163
+ if (opts.name !== undefined)
241164
+ body.name = opts.name;
241165
+ if (opts.transport !== undefined)
241166
+ body.transport = opts.transport;
241167
+ if (opts.fromEmail !== undefined)
241168
+ body.fromEmail = opts.fromEmail;
241169
+ if (opts.fromName !== undefined)
241170
+ body.fromName = opts.fromName;
241171
+ const enabled = parseEnabled(opts);
241172
+ if (enabled !== undefined)
241173
+ body.enabled = enabled;
241174
+ if (opts.host !== undefined)
241175
+ body.host = opts.host;
241176
+ if (opts.port !== undefined)
241177
+ body.port = opts.port;
241178
+ if (opts.security !== undefined)
241179
+ body.security = opts.security;
241180
+ if (opts.username !== undefined)
241181
+ body.username = opts.username;
241182
+ const apiKey = await readSecretInput2("api-key", { stdin: opts.apiKeyStdin, file: opts.apiKeyFile }, false);
241183
+ if (apiKey !== undefined)
241184
+ body.apiKey = apiKey;
241185
+ const password = await readSecretInput2("password", { stdin: opts.passwordStdin, file: opts.passwordFile }, false);
241186
+ if (password !== undefined)
241187
+ body.password = password;
241188
+ const caPem = await readSecretInput2("ca-pem", { stdin: opts.caPemStdin, file: opts.caPemFile }, false);
241189
+ if (caPem !== undefined)
241190
+ body.caPem = caPem;
241191
+ const transport = body.transport;
241192
+ if (transport === "resend" && body.apiKey === undefined) {
241193
+ body.apiKey = await readSecretInput2("api-key", { stdin: opts.apiKeyStdin, file: opts.apiKeyFile }, true);
241194
+ }
241195
+ if (body.transport === "smtp" && typeof body.username === "string" && body.username.length > 0 && body.password === undefined) {
241196
+ body.password = await readSecretInput2("password", { stdin: opts.passwordStdin, file: opts.passwordFile }, true);
241197
+ }
241198
+ return CreateEmailServerRequestSchema.parse(body);
241199
+ }
241200
+ async function buildUpdateRequest(input) {
241201
+ const { existing, opts } = input;
241202
+ const explicitCount = countTruthy([
241203
+ opts.name,
241204
+ opts.transport,
241205
+ opts.fromEmail,
241206
+ opts.fromName,
241207
+ opts.enabled,
241208
+ opts.disabled,
241209
+ opts.host,
241210
+ opts.port,
241211
+ opts.security,
241212
+ opts.username,
241213
+ opts.clearCaPem,
241214
+ opts.clearUsername
241215
+ ]);
241216
+ assertExclusiveConfigSource(explicitCount, opts, "update");
241217
+ const body = {};
241218
+ if (countTruthy([opts.configJson, opts.configFile]) > 0) {
241219
+ Object.assign(body, readConfigObject(opts));
241220
+ rejectInlineSecrets(body);
241221
+ }
241222
+ if (opts.name !== undefined)
241223
+ body.name = opts.name;
241224
+ const enabled = parseEnabled(opts);
241225
+ if (enabled !== undefined)
241226
+ body.enabled = enabled;
241227
+ if (opts.transport !== undefined)
241228
+ body.transport = opts.transport;
241229
+ if (opts.fromEmail !== undefined)
241230
+ body.fromEmail = opts.fromEmail;
241231
+ if (opts.fromName !== undefined)
241232
+ body.fromName = opts.fromName;
241233
+ if (opts.host !== undefined)
241234
+ body.host = opts.host;
241235
+ if (opts.port !== undefined)
241236
+ body.port = opts.port;
241237
+ if (opts.security !== undefined)
241238
+ body.security = opts.security;
241239
+ if (opts.clearUsername)
241240
+ body.username = null;
241241
+ else if (opts.username !== undefined)
241242
+ body.username = opts.username;
241243
+ if (opts.clearCaPem)
241244
+ body.caPem = null;
241245
+ const apiKey = await readSecretInput2("api-key", { stdin: opts.apiKeyStdin, file: opts.apiKeyFile }, false);
241246
+ if (apiKey !== undefined)
241247
+ body.apiKey = apiKey;
241248
+ const password = await readSecretInput2("password", { stdin: opts.passwordStdin, file: opts.passwordFile }, false);
241249
+ if (password !== undefined)
241250
+ body.password = password;
241251
+ const caPem = await readSecretInput2("ca-pem", { stdin: opts.caPemStdin, file: opts.caPemFile }, false);
241252
+ if (caPem !== undefined)
241253
+ body.caPem = caPem;
241254
+ if (Object.keys(body).length === 0) {
241255
+ throw new Error("No changes requested. Pass fields to update or --config-json/--config-file.");
241256
+ }
241257
+ assertCompleteSmtpUpdateTarget(body);
241258
+ if (body.transport === "resend" && existing.transport !== "resend" && body.apiKey === undefined) {
241259
+ body.apiKey = await readSecretInput2("api-key", { stdin: opts.apiKeyStdin, file: opts.apiKeyFile }, true);
241260
+ }
241261
+ if (body.transport === "smtp" && body.password === undefined) {
241262
+ const targetUsername = body.username === null ? null : typeof body.username === "string" ? body.username : existing.username ?? null;
241263
+ const destinationChanged = existing.transport !== "smtp" || typeof body.host === "string" && existing.host !== undefined && body.host !== existing.host || targetUsername !== (existing.username ?? null);
241264
+ if (destinationChanged && targetUsername) {
241265
+ body.password = await readSecretInput2("password", { stdin: opts.passwordStdin, file: opts.passwordFile }, true);
241266
+ }
241267
+ }
241268
+ const patch = UpdateEmailServerRequestSchema.parse(body);
241269
+ const transportError = getEmailServerUpdateError(existing.transport, patch, {
241270
+ host: existing.host,
241271
+ username: existing.username,
241272
+ passwordConfigured: existing.passwordConfigured
241273
+ });
241274
+ if (transportError)
241275
+ throw new Error(transportError);
241276
+ return patch;
241277
+ }
241278
+ function redactValue(key, value) {
241279
+ if (SECRET_KEYS.has(key))
241280
+ return "[redacted]";
241281
+ if (value && typeof value === "object") {
241282
+ if (Array.isArray(value))
241283
+ return value.map((item) => redactUnknown(item));
241284
+ return redactUnknown(value);
241285
+ }
241286
+ return value;
241287
+ }
241288
+ function redactUnknown(value) {
241289
+ if (value == null || typeof value !== "object")
241290
+ return value;
241291
+ if (Array.isArray(value))
241292
+ return value.map((item) => redactUnknown(item));
241293
+ const out = {};
241294
+ for (const [key, nested] of Object.entries(value)) {
241295
+ out[key] = redactValue(key, nested);
241296
+ }
241297
+ return out;
241298
+ }
241299
+ function redactEmailServerPayload(value) {
241300
+ return redactUnknown(value);
241301
+ }
241302
+ function formatEmailServerHuman(server) {
241303
+ const lines = [];
241304
+ lines.push(`${server.id} ${server.name}${server.enabled ? "" : " (disabled)"}`);
241305
+ lines.push(` transport ${server.transport}`);
241306
+ lines.push(` from ${server.fromName} <${server.fromEmail}>`);
241307
+ if (server.transport === "resend") {
241308
+ lines.push(` api key configured`);
241309
+ } else {
241310
+ lines.push(` host ${server.host}:${server.port} (${server.security})`);
241311
+ lines.push(` username ${server.username ?? "-"}`);
241312
+ lines.push(` password ${server.passwordConfigured ? "configured" : "not configured"}`);
241313
+ lines.push(` ca pem ${server.caPemConfigured ? "configured" : "not configured"}`);
241314
+ }
241315
+ lines.push(` updated ${server.updatedAt instanceof Date ? server.updatedAt.toISOString() : server.updatedAt}`);
241316
+ return lines.join(`
241317
+ `);
241318
+ }
241319
+
241320
+ // src/commands/email-servers.ts
241321
+ var LIST_COLUMNS = [
241322
+ { key: "id", header: "id" },
241323
+ { key: "name", header: "name" },
241324
+ { key: "transport", header: "transport" },
241325
+ {
241326
+ key: "enabled",
241327
+ header: "enabled",
241328
+ format: (value) => value ? "yes" : "no"
241329
+ },
241330
+ { key: "fromEmail", header: "from" },
241331
+ {
241332
+ key: "host",
241333
+ header: "host",
241334
+ format: (_value, row) => row.transport === "smtp" ? String(row.host) : "-"
241335
+ },
241336
+ {
241337
+ key: "updatedAt",
241338
+ header: "updated",
241339
+ format: (value) => formatTimestamp(value)
241340
+ }
241341
+ ];
241342
+ function buildClient2(opts) {
241343
+ const config = resolveConfig(opts);
241344
+ requireApiKey(config);
241345
+ return new ApiClient(config);
241346
+ }
241347
+ function printJson2(value) {
241348
+ console.log(JSON.stringify(value, null, 2));
241349
+ }
241350
+ function sharedCreateOptions(cmd) {
241351
+ return cmd.option("--config-json <json>", "JSON object (non-secret fields only; use secret *-stdin/*-file flags)").option("--config-file <path>", "JSON file path (`-` reads stdin; non-secret fields only)").option("--name <name>", "Display name").option("--transport <kind>", "Transport: resend or smtp").option("--from-email <email>", "From address").option("--from-name <name>", "From display name (no control characters or <>)").option("--enabled", "Enable the server (default on create)").option("--disabled", "Disable the server").option("--host <host>", "SMTP host (required on update when --transport smtp)").option("--port <n>", "SMTP port. Required on update when --transport smtp; create defaults from --security", intArg).option("--security <mode>", "SMTP security: starttls, tls, or none (unauthenticated trusted relays; credentials are rejected). Required on update when --transport smtp; create defaults to starttls").option("--username <user>", "SMTP username (non-secret)").option("--api-key-stdin", "Read the Resend API key from stdin").option("--api-key-file <path>", "Read the Resend API key from a file (`-` for stdin)").option("--password-stdin", "Read the SMTP password from stdin").option("--password-file <path>", "Read the SMTP password from a file (`-` for stdin)").option("--ca-pem-stdin", "Read a custom SMTP CA PEM from stdin").option("--ca-pem-file <path>", "Read a custom SMTP CA PEM from a file (`-` for stdin)");
241352
+ }
241353
+ function sharedUpdateOptions(cmd) {
241354
+ return sharedCreateOptions(cmd).option("--clear-ca-pem", "Remove a stored custom SMTP CA certificate").option("--clear-username", "Clear stored SMTP username/password pair");
241355
+ }
241356
+ var EMAIL_SERVERS_EXAMPLES = `
241357
+ Examples:
241358
+ $ eigenpal email-servers list --json
241359
+ $ eigenpal email-servers get ems_... --json
241360
+ $ eigenpal email-servers create --transport resend --name Alerts \\
241361
+ --from-email alerts@example.com --from-name Alerts --api-key-stdin
241362
+ $ eigenpal email-servers create --transport smtp --name "Corp SMTP" --host smtp.example.com \\
241363
+ --from-email noreply@example.com --from-name Eigenpal
241364
+ $ eigenpal email-servers create --config-file ./resend.json --api-key-file ./re.key
241365
+ $ eigenpal email-servers update ems_... --name "Ops alerts"
241366
+ $ eigenpal email-servers update ems_... --transport smtp --host smtp.example.com \\
241367
+ --port 587 --security starttls --from-email noreply@example.com \\
241368
+ --from-name Eigenpal --password-stdin
241369
+ $ eigenpal email-servers delete ems_... --yes
241370
+ $ eigenpal email-servers test ems_... --to you@example.com
241371
+
241372
+ Secrets never belong on the command line. Provide Resend API keys, SMTP passwords,
241373
+ and CA PEM material via --*-stdin, --*-file, or the secure TTY prompt.
241374
+ `;
241375
+ function registerEmailServersCommands(program) {
241376
+ const emailServers = program.command("email-servers").alias("email-server").description("Manage outbound email servers (ems_…): list, inspect, create, update, delete, and send a real test message.").addHelpText("after", EMAIL_SERVERS_EXAMPLES);
241377
+ const listCmd = emailServers.command("list").description("List outbound email servers for the current workspace.");
241378
+ addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
241379
+ const client = buildClient2(opts);
241380
+ const raw = await client.get(apiPath("/email-servers"), {
241381
+ limit: String(opts.limit),
241382
+ offset: String(opts.offset)
241383
+ });
241384
+ renderListResult(raw, LIST_COLUMNS, {
241385
+ json: opts.json,
241386
+ entityLabel: "email server"
241387
+ });
241388
+ }));
241389
+ const getCmd = emailServers.command("get <id>").description("Inspect one email server. Human output is redacted even if the API regresses.");
241390
+ addJsonFlag(withBaseUrl(getCmd)).action(action(async (id, opts) => {
241391
+ const client = buildClient2(opts);
241392
+ const raw = await client.get(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241393
+ const redacted = redactEmailServerPayload(raw);
241394
+ if (opts.json) {
241395
+ printJson2(redacted);
241396
+ return;
241397
+ }
241398
+ console.log(formatEmailServerHuman(redacted));
241399
+ }));
241400
+ const createCmd = emailServers.command("create").description("Create an outbound email server. Resend requires an API key; SMTP accepts optional username/password except with --security none, plus optional CA PEM, and defaults to starttls on port 587.");
241401
+ addJsonFlag(withBaseUrl(sharedCreateOptions(createCmd))).action(action(async (opts) => {
241402
+ const body = await buildCreateRequest(opts);
241403
+ const client = buildClient2(opts);
241404
+ const created = await client.post(apiPath("/email-servers"), body);
241405
+ const redacted = redactEmailServerPayload(created);
241406
+ if (opts.json) {
241407
+ printJson2(redacted);
241408
+ return;
241409
+ }
241410
+ success(`Created ${ui.bold(redacted.id)} (${redacted.transport})`);
241411
+ console.log(formatEmailServerHuman(redacted));
241412
+ }));
241413
+ const updateCmd = emailServers.command("update <id>").description("Update metadata or replace transport configuration. Omitted secrets are retained. Passing --transport smtp requires --host, --port, --security, --from-email, and --from-name (no security/port defaults). Metadata-only updates omit --transport.");
241414
+ addJsonFlag(withBaseUrl(sharedUpdateOptions(updateCmd))).action(action(async (id, opts) => {
241415
+ const client = buildClient2(opts);
241416
+ const existing = await client.get(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241417
+ const body = await buildUpdateRequest({ existing, opts });
241418
+ const updated = await client.patch(apiPath(`/email-servers/${encodeURIComponent(id)}`), body);
241419
+ const redacted = redactEmailServerPayload(updated);
241420
+ if (opts.json) {
241421
+ printJson2(redacted);
241422
+ return;
241423
+ }
241424
+ success(`Updated ${ui.bold(redacted.id)}`);
241425
+ console.log(formatEmailServerHuman(redacted));
241426
+ }));
241427
+ const deleteCmd = emailServers.command("delete <id>").description("Soft-delete an outbound email server.").option("--yes", "Required for non-TTY shells", false);
241428
+ addJsonFlag(withBaseUrl(deleteCmd)).action(action(async (id, opts) => {
241429
+ if (!opts.yes && !process.stdout.isTTY) {
241430
+ throw new Error("email-servers delete is destructive and requires --yes when run non-interactively");
241431
+ }
241432
+ const client = buildClient2(opts);
241433
+ const result = await client.delete(apiPath(`/email-servers/${encodeURIComponent(id)}`));
241434
+ if (opts.json) {
241435
+ printJson2(result);
241436
+ return;
241437
+ }
241438
+ success(`Deleted ${ui.bold(id)}`);
241439
+ }));
241440
+ const testCmd = emailServers.command("test <id>").description("Send a real connectivity test email through the stored server to --to. Disabled servers fail with a conflict.").requiredOption("--to <email>", "Recipient for the live test message");
241441
+ addJsonFlag(withBaseUrl(testCmd)).action(action(async (id, opts) => {
241442
+ const client = buildClient2(opts);
241443
+ const result = await client.post(apiPath(`/email-servers/${encodeURIComponent(id)}/test`), {
241444
+ to: opts.to
241445
+ });
241446
+ if (opts.json) {
241447
+ printJson2(result);
241448
+ if (!result.ok)
241449
+ process.exit(1);
241450
+ return;
241451
+ }
241452
+ if (result.ok) {
241453
+ success(`Test email sent via ${ui.bold(result.transport)} (${ui.dim(result.messageId)})`);
241454
+ return;
241455
+ }
241456
+ throw new Error(result.error);
241457
+ }));
241458
+ }
241459
+
240646
241460
  // src/commands/init/index.ts
240647
241461
  init_dist4();
240648
241462
  import {
240649
241463
  copyFileSync,
240650
- existsSync as existsSync14,
241464
+ existsSync as existsSync15,
240651
241465
  mkdirSync as mkdirSync5,
240652
241466
  readdirSync as readdirSync4,
240653
- readFileSync as readFileSync14,
241467
+ readFileSync as readFileSync15,
240654
241468
  statSync as statSync4,
240655
241469
  writeFileSync as writeFileSync7
240656
241470
  } from "node:fs";
240657
- import { dirname as dirname4, join as join7, relative as relative2, resolve as resolve4 } from "node:path";
241471
+ import { dirname as dirname4, join as join7, relative as relative2, resolve as resolve5 } from "node:path";
240658
241472
  import { fileURLToPath as fileURLToPath6 } from "node:url";
240659
241473
  var TEMPLATE_NAMES = ["blank", "pdf-extraction", "text-classification"];
240660
241474
  var TEMPLATE_DESCRIPTIONS = {
@@ -240667,11 +241481,11 @@ function isValidProjectName(name) {
240667
241481
  }
240668
241482
  function resolveTemplatesRoot() {
240669
241483
  const here = dirname4(fileURLToPath6(import.meta.url));
240670
- const srcCandidate = resolve4(here, "..", "..", "templates");
240671
- if (existsSync14(srcCandidate))
241484
+ const srcCandidate = resolve5(here, "..", "..", "templates");
241485
+ if (existsSync15(srcCandidate))
240672
241486
  return srcCandidate;
240673
- const distCandidate = resolve4(here, "templates");
240674
- if (existsSync14(distCandidate))
241487
+ const distCandidate = resolve5(here, "templates");
241488
+ if (existsSync15(distCandidate))
240675
241489
  return distCandidate;
240676
241490
  throw new Error(`Cannot locate bundled templates. Looked in:
240677
241491
  ${srcCandidate}
@@ -240681,9 +241495,9 @@ async function init(name, opts) {
240681
241495
  if (!isValidProjectName(name)) {
240682
241496
  throw new Error(`Invalid project name "${name}". Use lowercase kebab/snake-case (e.g. parse-invoices), max 60 chars.`);
240683
241497
  }
240684
- const target = resolve4(process.cwd(), opts.dir ?? name);
241498
+ const target = resolve5(process.cwd(), opts.dir ?? name);
240685
241499
  assertSafeTargetDir(target, opts.dir);
240686
- if (existsSync14(target) && readdirSync4(target).length > 0) {
241500
+ if (existsSync15(target) && readdirSync4(target).length > 0) {
240687
241501
  throw new Error(`Target directory ${relative2(process.cwd(), target)} exists and is not empty.`);
240688
241502
  }
240689
241503
  let template;
@@ -240698,7 +241512,7 @@ async function init(name, opts) {
240698
241512
  template = await promptForTemplate();
240699
241513
  }
240700
241514
  const sourceRoot = join7(resolveTemplatesRoot(), template);
240701
- if (!existsSync14(sourceRoot)) {
241515
+ if (!existsSync15(sourceRoot)) {
240702
241516
  throw new Error(`Template directory missing on disk: ${sourceRoot}`);
240703
241517
  }
240704
241518
  const written = copyTemplate(sourceRoot, target, name);
@@ -240751,7 +241565,7 @@ function copyTemplate(src, dst, projectName) {
240751
241565
  }
240752
241566
  mkdirSync5(dirname4(targetPath), { recursive: true });
240753
241567
  if (isTextFile(sourcePath)) {
240754
- const text = readFileSync14(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
241568
+ const text = readFileSync15(sourcePath, "utf-8").replaceAll(PLACEHOLDER, projectName);
240755
241569
  writeFileSync7(targetPath, text);
240756
241570
  } else {
240757
241571
  copyFileSync(sourcePath, targetPath);
@@ -240878,20 +241692,6 @@ function multipartMaxBytesFromEnv(raw = env.EIGENPAL_MULTIPART_MAX_BYTES) {
240878
241692
 
240879
241693
  // src/lib/upload-reusable-file.ts
240880
241694
  import { randomUUID } from "node:crypto";
240881
-
240882
- // src/lib/api-paths.ts
240883
- var API_PREFIX = "/v1";
240884
- function apiPath(suffix) {
240885
- if (suffix === "/v1" || suffix.startsWith("/v1/"))
240886
- return suffix;
240887
- if (suffix === "/api/v1" || suffix.startsWith("/api/v1/")) {
240888
- return `${API_PREFIX}${suffix.slice("/api/v1".length)}`;
240889
- }
240890
- const normalized = suffix.startsWith("/") ? suffix : `/${suffix}`;
240891
- return `${API_PREFIX}${normalized}`;
240892
- }
240893
-
240894
- // src/lib/upload-reusable-file.ts
240895
241695
  function newIdempotencyKey() {
240896
241696
  return randomUUID();
240897
241697
  }
@@ -241046,8 +241846,8 @@ function parseInputFileSpecs(inputFile) {
241046
241846
 
241047
241847
  // src/lib/format-eigenpal.ts
241048
241848
  import { spawnSync as spawnSync5 } from "child_process";
241049
- import { existsSync as existsSync15, readFileSync as readFileSync15 } from "fs";
241050
- import { join as join8, resolve as resolve5 } from "path";
241849
+ import { existsSync as existsSync16, readFileSync as readFileSync16 } from "fs";
241850
+ import { join as join8, resolve as resolve6 } from "path";
241051
241851
  var PRETTRC_NAMES = [
241052
241852
  ".prettierrc",
241053
241853
  ".prettierrc.json",
@@ -241060,14 +241860,14 @@ var PRETTRC_NAMES = [
241060
241860
  ];
241061
241861
  function hasPrettierConfig(cwd) {
241062
241862
  for (const name of PRETTRC_NAMES) {
241063
- if (existsSync15(join8(cwd, name)))
241863
+ if (existsSync16(join8(cwd, name)))
241064
241864
  return true;
241065
241865
  }
241066
241866
  try {
241067
241867
  const pkgPath = join8(cwd, "package.json");
241068
- if (!existsSync15(pkgPath))
241868
+ if (!existsSync16(pkgPath))
241069
241869
  return false;
241070
- const raw = readFileSync15(pkgPath, "utf-8");
241870
+ const raw = readFileSync16(pkgPath, "utf-8");
241071
241871
  const pkg = JSON.parse(raw);
241072
241872
  return pkg != null && typeof pkg === "object" && "prettier" in pkg;
241073
241873
  } catch {
@@ -241076,8 +241876,8 @@ function hasPrettierConfig(cwd) {
241076
241876
  }
241077
241877
  function formatEigenpalDirIfAvailable(dir) {
241078
241878
  const cwd = process.cwd();
241079
- const absDir = resolve5(cwd, dir);
241080
- if (!existsSync15(absDir))
241879
+ const absDir = resolve6(cwd, dir);
241880
+ if (!existsSync16(absDir))
241081
241881
  return;
241082
241882
  if (!hasPrettierConfig(cwd))
241083
241883
  return;
@@ -241204,17 +242004,17 @@ async function rerunTarget(runId, opts) {
241204
242004
  init_dist4();
241205
242005
  import { createHash as createHash5 } from "node:crypto";
241206
242006
  import {
241207
- existsSync as existsSync16,
242007
+ existsSync as existsSync17,
241208
242008
  lstatSync,
241209
242009
  mkdirSync as mkdirSync6,
241210
- readFileSync as readFileSync16,
242010
+ readFileSync as readFileSync17,
241211
242011
  readdirSync as readdirSync5,
241212
242012
  rmSync as rmSync2,
241213
242013
  rmdirSync,
241214
242014
  unlinkSync as unlinkSync2,
241215
242015
  writeFileSync as writeFileSync8
241216
242016
  } from "node:fs";
241217
- import { sep as PATH_SEP, dirname as dirname5, join as join10, relative as relative3, resolve as resolve6 } from "node:path";
242017
+ import { sep as PATH_SEP, dirname as dirname5, join as join10, relative as relative3, resolve as resolve7 } from "node:path";
241218
242018
  import { fileURLToPath as fileURLToPath7 } from "node:url";
241219
242019
 
241220
242020
  // src/commands/skill/tools.ts
@@ -241289,11 +242089,11 @@ var TOOLS = [
241289
242089
  var MANIFEST_NAME = ".eigenpal-manifest.json";
241290
242090
  function resolveSkillSource() {
241291
242091
  const here = dirname5(fileURLToPath7(import.meta.url));
241292
- const srcCandidate = resolve6(here, "..", "..", "skill");
241293
- if (existsSync16(srcCandidate))
242092
+ const srcCandidate = resolve7(here, "..", "..", "skill");
242093
+ if (existsSync17(srcCandidate))
241294
242094
  return srcCandidate;
241295
- const distCandidate = resolve6(here, "skill");
241296
- if (existsSync16(distCandidate))
242095
+ const distCandidate = resolve7(here, "skill");
242096
+ if (existsSync17(distCandidate))
241297
242097
  return distCandidate;
241298
242098
  throw new Error(`Cannot locate bundled skill content. Looked in:
241299
242099
  ${srcCandidate}
@@ -241330,15 +242130,15 @@ async function installSkill(opts) {
241330
242130
  for (const relativePath of sourceFiles) {
241331
242131
  const sourcePath = join10(source, relativePath);
241332
242132
  const targetPath = join10(target, relativePath);
241333
- const sourceBytes = templateSourceFile(relativePath, readFileSync16(sourcePath), cliVersion);
242133
+ const sourceBytes = templateSourceFile(relativePath, readFileSync17(sourcePath), cliVersion);
241334
242134
  const sourceHash = sha256(sourceBytes);
241335
- if (!existsSync16(targetPath)) {
242135
+ if (!existsSync17(targetPath)) {
241336
242136
  mkdirSync6(dirname5(targetPath), { recursive: true });
241337
242137
  writeFileSync8(targetPath, sourceBytes);
241338
242138
  written += 1;
241339
242139
  continue;
241340
242140
  }
241341
- const targetBytes = readFileSync16(targetPath);
242141
+ const targetBytes = readFileSync17(targetPath);
241342
242142
  const targetHash = sha256(targetBytes);
241343
242143
  if (targetHash === sourceHash) {
241344
242144
  skipped += 1;
@@ -241370,9 +242170,9 @@ async function installSkill(opts) {
241370
242170
  const manifestEntries = [];
241371
242171
  for (const relativePath of sourceFiles) {
241372
242172
  const targetPath = join10(target, relativePath);
241373
- if (!existsSync16(targetPath))
242173
+ if (!existsSync17(targetPath))
241374
242174
  continue;
241375
- manifestEntries.push({ path: relativePath, sha256: sha256(readFileSync16(targetPath)) });
242175
+ manifestEntries.push({ path: relativePath, sha256: sha256(readFileSync17(targetPath)) });
241376
242176
  }
241377
242177
  const manifest = {
241378
242178
  cliVersion,
@@ -241403,19 +242203,19 @@ async function uninstallSkill(opts) {
241403
242203
  } else if (!opts.yes) {
241404
242204
  throw new Error(nonInteractiveYesRequired("Uninstall skill from custom --target path"));
241405
242205
  }
241406
- const targetReal = resolve6(target);
242206
+ const targetReal = resolve7(target);
241407
242207
  const safeBase = targetReal + PATH_SEP;
241408
242208
  let removed = 0;
241409
242209
  let kept = 0;
241410
242210
  for (const entry of manifest.files) {
241411
- const path = resolve6(targetReal, entry.path);
242211
+ const path = resolve7(targetReal, entry.path);
241412
242212
  if (path !== targetReal && !path.startsWith(safeBase)) {
241413
242213
  console.error(`Refusing to touch ${path}: manifest path escapes ${targetReal}`);
241414
242214
  continue;
241415
242215
  }
241416
- if (!existsSync16(path))
242216
+ if (!existsSync17(path))
241417
242217
  continue;
241418
- const currentHash = sha256(readFileSync16(path));
242218
+ const currentHash = sha256(readFileSync17(path));
241419
242219
  if (currentHash !== entry.sha256 && !opts.yes) {
241420
242220
  kept += 1;
241421
242221
  continue;
@@ -241616,10 +242416,10 @@ function hintFor(tool, installed, detected) {
241616
242416
  return tool.relativePath;
241617
242417
  }
241618
242418
  function isInstalled(cwd, tool) {
241619
- return existsSync16(join10(cwd, tool.relativePath, MANIFEST_NAME));
242419
+ return existsSync17(join10(cwd, tool.relativePath, MANIFEST_NAME));
241620
242420
  }
241621
242421
  function isProjectUsing(cwd, tool) {
241622
- return tool.detectPaths.some((p) => existsSync16(join10(cwd, p)));
242422
+ return tool.detectPaths.some((p) => existsSync17(join10(cwd, p)));
241623
242423
  }
241624
242424
  function listFiles(root) {
241625
242425
  const out = [];
@@ -241643,10 +242443,10 @@ function listFiles(root) {
241643
242443
  }
241644
242444
  function readManifest(target) {
241645
242445
  const path = join10(target, MANIFEST_NAME);
241646
- if (!existsSync16(path))
242446
+ if (!existsSync17(path))
241647
242447
  return null;
241648
242448
  try {
241649
- return JSON.parse(readFileSync16(path, "utf-8"));
242449
+ return JSON.parse(readFileSync17(path, "utf-8"));
241650
242450
  } catch {
241651
242451
  return null;
241652
242452
  }
@@ -241655,13 +242455,13 @@ function readCliVersion() {
241655
242455
  try {
241656
242456
  const here = dirname5(fileURLToPath7(import.meta.url));
241657
242457
  const candidates = [
241658
- resolve6(here, "..", "..", "..", "package.json"),
241659
- resolve6(here, "..", "..", "package.json"),
241660
- resolve6(here, "..", "package.json")
242458
+ resolve7(here, "..", "..", "..", "package.json"),
242459
+ resolve7(here, "..", "..", "package.json"),
242460
+ resolve7(here, "..", "package.json")
241661
242461
  ];
241662
242462
  for (const candidate of candidates) {
241663
- if (existsSync16(candidate)) {
241664
- const pkg = JSON.parse(readFileSync16(candidate, "utf-8"));
242463
+ if (existsSync17(candidate)) {
242464
+ const pkg = JSON.parse(readFileSync17(candidate, "utf-8"));
241665
242465
  if (pkg.name && pkg.name !== "@eigenpal/cli")
241666
242466
  continue;
241667
242467
  if (pkg.version)
@@ -241672,7 +242472,7 @@ function readCliVersion() {
241672
242472
  return "unknown";
241673
242473
  }
241674
242474
  function pruneEmptyDirs(root) {
241675
- if (!existsSync16(root))
242475
+ if (!existsSync17(root))
241676
242476
  return;
241677
242477
  const stack = [];
241678
242478
  const collect = (dir) => {
@@ -242462,13 +243262,13 @@ function looksLikeFreeform(prop) {
242462
243262
  return prop.pattern !== undefined || prop.format !== undefined;
242463
243263
  }
242464
243264
  // src/commands/workflow/index.ts
242465
- import { existsSync as existsSync22, promises as fs20 } from "node:fs";
243265
+ import { existsSync as existsSync23, promises as fs20 } from "node:fs";
242466
243266
  import path18 from "node:path";
242467
243267
 
242468
243268
  // src/lib/local-templates.ts
242469
243269
  init_src();
242470
- import { existsSync as existsSync17, promises as fs17, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
242471
- import { basename, dirname as dirname6, isAbsolute, relative as relative4, resolve as resolve7, sep } from "node:path";
243270
+ import { existsSync as existsSync18, promises as fs17, realpathSync as realpathSync3, statSync as statSync5 } from "node:fs";
243271
+ import { basename, dirname as dirname6, isAbsolute, relative as relative4, resolve as resolve8, sep } from "node:path";
242472
243272
 
242473
243273
  // src/lib/office-template.ts
242474
243274
  import { createHash as createHash6 } from "node:crypto";
@@ -242709,8 +243509,8 @@ function walkTemplateSteps(steps, visit) {
242709
243509
  }
242710
243510
  }
242711
243511
  function resolveWorkflowProjectRoot(workflowFile) {
242712
- const abs = resolve7(workflowFile);
242713
- if (!existsSync17(abs)) {
243512
+ const abs = resolve8(workflowFile);
243513
+ if (!existsSync18(abs)) {
242714
243514
  throw new Error(`Workflow file not found: ${abs}`);
242715
243515
  }
242716
243516
  return dirname6(realpathSync3(abs));
@@ -242729,11 +243529,11 @@ function resolveWorkflowTemplatePath(workflowFile, templatePath, opts = {}) {
242729
243529
  throw new Error(`Invalid local template path "${templatePath}". Use a relative .docx or .xlsx path such as ./templates/foo.xlsx.`);
242730
243530
  }
242731
243531
  const projectRoot = resolveWorkflowProjectRoot(workflowFile);
242732
- const candidate = resolve7(projectRoot, templatePath);
243532
+ const candidate = resolve8(projectRoot, templatePath);
242733
243533
  if (!opts.allowExternal) {
242734
243534
  assertInsideProject(projectRoot, templatePath, candidate);
242735
243535
  }
242736
- if (!existsSync17(candidate)) {
243536
+ if (!existsSync18(candidate)) {
242737
243537
  throw new Error(`Local template not found: ${candidate}`);
242738
243538
  }
242739
243539
  const real = realpathSync3(candidate);
@@ -242915,11 +243715,11 @@ function rewriteLocalTemplateYaml(yamlText, resolved) {
242915
243715
  }
242916
243716
 
242917
243717
  // src/commands/workflow/clear.ts
242918
- import { existsSync as existsSync18, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync6 } from "fs";
243718
+ import { existsSync as existsSync19, readdirSync as readdirSync6, rmSync as rmSync3, statSync as statSync6 } from "fs";
242919
243719
  import { basename as basename2, join as join11 } from "path";
242920
243720
  var EMPTY_REPORT = { removed: 0, kept: 0, touched: 0 };
242921
243721
  function getDirectoryEntries(path) {
242922
- if (!existsSync18(path))
243722
+ if (!existsSync19(path))
242923
243723
  return [];
242924
243724
  return readdirSync6(path).filter((entry) => statSync6(join11(path, entry)).isDirectory()).sort();
242925
243725
  }
@@ -242940,7 +243740,7 @@ function removeDirEntriesWithRetention(path, removeAll) {
242940
243740
  return { removed, kept: keepSet.size, touched: entries.length };
242941
243741
  }
242942
243742
  function removeJudgeSummaryFilesWithRetention(exampleDir, removeAll) {
242943
- if (!existsSync18(exampleDir))
243743
+ if (!existsSync19(exampleDir))
242944
243744
  return EMPTY_REPORT;
242945
243745
  const stampByFile = new Map;
242946
243746
  for (const fileName of readdirSync6(exampleDir).sort()) {
@@ -243012,7 +243812,7 @@ async function clearEvalOutputs(dir, exampleNames = [], options = {}) {
243012
243812
  runSection({
243013
243813
  exampleDirs,
243014
243814
  clean: (exampleDir) => removeDirEntriesWithRetention(join11(exampleDir, "executions"), removeAll),
243015
- shouldCount: (exampleDir) => existsSync18(join11(exampleDir, "executions")),
243815
+ shouldCount: (exampleDir) => existsSync19(join11(exampleDir, "executions")),
243016
243816
  successLabel: "Execution cleanup complete",
243017
243817
  scannedLabel: "examples scanned:",
243018
243818
  seenLabel: "runs seen: ",
@@ -243024,7 +243824,7 @@ async function clearEvalOutputs(dir, exampleNames = [], options = {}) {
243024
243824
  runSection({
243025
243825
  exampleDirs,
243026
243826
  clean: (exampleDir) => removeJudgeSummaryFilesWithRetention(exampleDir, removeAll),
243027
- shouldCount: (exampleDir) => existsSync18(exampleDir),
243827
+ shouldCount: (exampleDir) => existsSync19(exampleDir),
243028
243828
  successLabel: "Judge summary cleanup complete",
243029
243829
  scannedLabel: "examples scanned: ",
243030
243830
  seenLabel: "summary files seen: ",
@@ -243137,24 +243937,24 @@ function registerStepExecCommands(workflow) {
243137
243937
 
243138
243938
  // src/commands/workflow/templates.ts
243139
243939
  init_src();
243140
- import { existsSync as existsSync19, promises as fs19 } from "node:fs";
243141
- import { basename as basename3, resolve as resolve8 } from "node:path";
243142
- function buildClient2(opts) {
243940
+ import { existsSync as existsSync20, promises as fs19 } from "node:fs";
243941
+ import { basename as basename3, resolve as resolve9 } from "node:path";
243942
+ function buildClient3(opts) {
243143
243943
  const config = resolveConfig(opts);
243144
243944
  requireApiKey(config);
243145
243945
  return new ApiClient(config);
243146
243946
  }
243147
- function printJson2(value) {
243947
+ function printJson3(value) {
243148
243948
  console.log(JSON.stringify(value, null, 2));
243149
243949
  }
243150
243950
  async function readJsonFixtureFile(fixturePath) {
243151
243951
  let raw;
243152
243952
  try {
243153
- raw = await fs19.readFile(resolve8(fixturePath), "utf8");
243953
+ raw = await fs19.readFile(resolve9(fixturePath), "utf8");
243154
243954
  } catch (err) {
243155
243955
  const code = err && typeof err === "object" && "code" in err ? String(err.code) : "";
243156
243956
  if (code === "ENOENT") {
243157
- throw new Error(`JSON fixture file not found: ${resolve8(fixturePath)}`);
243957
+ throw new Error(`JSON fixture file not found: ${resolve9(fixturePath)}`);
243158
243958
  }
243159
243959
  throw err;
243160
243960
  }
@@ -243201,9 +244001,9 @@ function registerTemplateCommands(parent) {
243201
244001
  const templates = parent.command("templates").description("Manage workspace DOCX/XLSX templates (tmpl_…): upload, list, inspect, download, replace, delete, and smoke-fill.").addHelpText("after", TEMPLATES_EXAMPLES);
243202
244002
  const uploadCmd = templates.command("upload <file>").description("Upload a DOCX or XLSX file as a new tmpl_… resource with an immutable tmpr_… revision.").option("--name <name>", "Display name (defaults to the filename without extension)").option("--description <text>", "Optional description");
243203
244003
  addJsonFlag(withBaseUrl(uploadCmd)).action(action(async (file, opts) => {
243204
- const filePath = resolve8(file);
244004
+ const filePath = resolve9(file);
243205
244005
  const bytes = await fs19.readFile(filePath);
243206
- const client = buildClient2(opts);
244006
+ const client = buildClient3(opts);
243207
244007
  const template = await uploadWorkspaceTemplate(client, {
243208
244008
  bytes,
243209
244009
  filename: basename3(filePath),
@@ -243211,7 +244011,7 @@ function registerTemplateCommands(parent) {
243211
244011
  description: opts.description
243212
244012
  });
243213
244013
  if (opts.json) {
243214
- printJson2(template);
244014
+ printJson3(template);
243215
244015
  return;
243216
244016
  }
243217
244017
  success(`Uploaded ${ui.bold(template.id)} revision ${ui.bold(template.currentRevision?.id ?? "-")} (${template.format})`);
@@ -243219,10 +244019,10 @@ function registerTemplateCommands(parent) {
243219
244019
  }));
243220
244020
  const listCmd = templates.command("list").description("List workspace templates.");
243221
244021
  addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
243222
- const client = buildClient2(opts);
244022
+ const client = buildClient3(opts);
243223
244023
  const result = await listPublicTemplates(client, { limit: opts.limit, offset: opts.offset });
243224
244024
  if (opts.json) {
243225
- printJson2(result);
244025
+ printJson3(result);
243226
244026
  return;
243227
244027
  }
243228
244028
  console.log(table(result.items.map((row) => ({
@@ -243247,10 +244047,10 @@ function registerTemplateCommands(parent) {
243247
244047
  }));
243248
244048
  const getCmd = templates.command("get <template-id>").alias("inspect").description("Inspect a tmpl_… resource: current tmpr_…, format, checksum, tokens, grammar.");
243249
244049
  addJsonFlag(withBaseUrl(getCmd)).action(action(async (templateId, opts) => {
243250
- const client = buildClient2(opts);
244050
+ const client = buildClient3(opts);
243251
244051
  const template = await getPublicTemplate(client, templateId);
243252
244052
  if (opts.json) {
243253
- printJson2(template);
244053
+ printJson3(template);
243254
244054
  return;
243255
244055
  }
243256
244056
  printTemplateHuman(template);
@@ -243259,21 +244059,21 @@ function registerTemplateCommands(parent) {
243259
244059
  withBaseUrl(downloadCmd).action(action(async (templateId, opts) => {
243260
244060
  if (!opts.out)
243261
244061
  throw new Error("Missing --out <path>.");
243262
- const client = buildClient2(opts);
244062
+ const client = buildClient3(opts);
243263
244063
  const downloaded = await downloadTemplateBytes(client, templateId, opts.revisionId);
243264
244064
  await fs19.writeFile(opts.out, downloaded.bytes);
243265
244065
  success(`Wrote ${ui.bold(opts.out)} ${ui.dim(`(${downloaded.bytes.byteLength} bytes)`)}`);
243266
244066
  }));
243267
244067
  const replaceCmd = templates.command("replace <template-id> <file>").description("Append an immutable revision and advance the tmpl_… pointer.");
243268
244068
  addJsonFlag(withBaseUrl(replaceCmd)).action(action(async (templateId, file, opts) => {
243269
- const filePath = resolve8(file);
244069
+ const filePath = resolve9(file);
243270
244070
  const bytes = await fs19.readFile(filePath);
243271
- const client = buildClient2(opts);
244071
+ const client = buildClient3(opts);
243272
244072
  const current = await getPublicTemplate(client, templateId);
243273
244073
  const nextInspection = inspectOfficeTemplateBytes(bytes, basename3(filePath));
243274
244074
  if (current.currentRevision?.sha256 === nextInspection.sha256 || current.sha256 === nextInspection.sha256) {
243275
244075
  if (opts.json) {
243276
- printJson2({ ...current, reused: true });
244076
+ printJson3({ ...current, reused: true });
243277
244077
  return;
243278
244078
  }
243279
244079
  success(`Checksum matches current revision ${ui.bold(current.currentRevision?.id ?? "-")} — skipped upload`);
@@ -243285,7 +244085,7 @@ function registerTemplateCommands(parent) {
243285
244085
  filename: basename3(filePath)
243286
244086
  });
243287
244087
  if (opts.json) {
243288
- printJson2(template);
244088
+ printJson3(template);
243289
244089
  return;
243290
244090
  }
243291
244091
  success(`Replaced ${ui.bold(template.id)} → revision ${ui.bold(template.currentRevision?.id ?? "-")}`);
@@ -243296,10 +244096,10 @@ function registerTemplateCommands(parent) {
243296
244096
  if (!opts.yes && !process.stdout.isTTY) {
243297
244097
  throw new Error("templates delete is destructive and requires --yes when run non-interactively");
243298
244098
  }
243299
- const client = buildClient2(opts);
244099
+ const client = buildClient3(opts);
243300
244100
  const result = await deleteWorkspaceTemplate(client, templateId);
243301
244101
  if (opts.json) {
243302
- printJson2(result);
244102
+ printJson3(result);
243303
244103
  return;
243304
244104
  }
243305
244105
  success(`Deleted ${ui.bold(templateId)}`);
@@ -243312,13 +244112,13 @@ function registerTemplateCommands(parent) {
243312
244112
  let filename;
243313
244113
  const isTmpl = TemplateIdSchema.safeParse(templateArg).success;
243314
244114
  if (isTmpl) {
243315
- const client = buildClient2(opts);
244115
+ const client = buildClient3(opts);
243316
244116
  const downloaded = await downloadTemplateBytes(client, templateArg, opts.revisionId);
243317
244117
  bytes = downloaded.bytes;
243318
244118
  filename = downloaded.filename;
243319
244119
  } else {
243320
- const filePath = resolve8(templateArg);
243321
- if (!existsSync19(filePath)) {
244120
+ const filePath = resolve9(templateArg);
244121
+ if (!existsSync20(filePath)) {
243322
244122
  throw new Error(`Template file not found: ${filePath}. Pass a local .docx/.xlsx path or a tmpl_… id.`);
243323
244123
  }
243324
244124
  bytes = await fs19.readFile(filePath);
@@ -243340,7 +244140,7 @@ function registerTemplateCommands(parent) {
243340
244140
  bytes: rendered.output.byteLength
243341
244141
  };
243342
244142
  if (opts.json) {
243343
- printJson2(payload);
244143
+ printJson3(payload);
243344
244144
  return;
243345
244145
  }
243346
244146
  success(`Wrote ${ui.bold(opts.out)} (${rendered.inspection.format}, ${rendered.output.byteLength} bytes)`);
@@ -243360,12 +244160,12 @@ function registerTemplateCommands(parent) {
243360
244160
 
243361
244161
  // src/commands/workflow/validation.ts
243362
244162
  init_src();
243363
- import { existsSync as existsSync21, readdirSync as readdirSync7, readFileSync as readFileSync18, statSync as statSync7 } from "fs";
243364
- import { join as join12, resolve as resolve9 } from "path";
244163
+ import { existsSync as existsSync22, readdirSync as readdirSync7, readFileSync as readFileSync19, statSync as statSync7 } from "fs";
244164
+ import { join as join12, resolve as resolve10 } from "path";
243365
244165
 
243366
244166
  // src/lib/template-diagnostics.ts
243367
244167
  init_src();
243368
- import { existsSync as existsSync20, readFileSync as readFileSync17 } from "node:fs";
244168
+ import { existsSync as existsSync21, readFileSync as readFileSync18 } from "node:fs";
243369
244169
  function walkSteps(steps, pathPrefix, visit) {
243370
244170
  if (!Array.isArray(steps))
243371
244171
  return;
@@ -243490,7 +244290,7 @@ async function diagnoseTemplateSteps(args) {
243490
244290
  });
243491
244291
  continue;
243492
244292
  }
243493
- if (!existsSync20(absolute)) {
244293
+ if (!existsSync21(absolute)) {
243494
244294
  diagnostics.push({
243495
244295
  field: `${info.fieldPath}.template`,
243496
244296
  message: `File not found: ${absolute}`,
@@ -243499,7 +244299,7 @@ async function diagnoseTemplateSteps(args) {
243499
244299
  continue;
243500
244300
  }
243501
244301
  try {
243502
- const bytes = readFileSync17(absolute);
244302
+ const bytes = readFileSync18(absolute);
243503
244303
  const inspection = inspectOfficeTemplateBytes(bytes, absolute);
243504
244304
  diagnostics.push(...formatDiagnostics(info, inspection));
243505
244305
  } catch (err) {
@@ -243635,7 +244435,7 @@ function countInvokeWorkflowSteps(steps) {
243635
244435
  return count;
243636
244436
  }
243637
244437
  function validateWorkflowYaml(path) {
243638
- if (!existsSync21(path)) {
244438
+ if (!existsSync22(path)) {
243639
244439
  return {
243640
244440
  issues: [{ field: path, message: "File not found." }],
243641
244441
  warnings: [],
@@ -243644,7 +244444,7 @@ function validateWorkflowYaml(path) {
243644
244444
  steps: []
243645
244445
  };
243646
244446
  }
243647
- const text = readFileSync18(path, "utf-8");
244447
+ const text = readFileSync19(path, "utf-8");
243648
244448
  try {
243649
244449
  const definition = parseWorkflow(text);
243650
244450
  let warnings = [];
@@ -243745,10 +244545,10 @@ function printSchemaQualityWarnings(path, warnings) {
243745
244545
  }
243746
244546
  }
243747
244547
  function validateEvaluatorsYaml(path) {
243748
- if (!existsSync21(path)) {
244548
+ if (!existsSync22(path)) {
243749
244549
  return [{ field: path, message: "File not found." }];
243750
244550
  }
243751
- const text = readFileSync18(path, "utf-8");
244551
+ const text = readFileSync19(path, "utf-8");
243752
244552
  let parsed;
243753
244553
  try {
243754
244554
  parsed = $parse(text);
@@ -243765,17 +244565,17 @@ function validateEvaluatorsYaml(path) {
243765
244565
  }
243766
244566
  function validateDatasetFolder(root) {
243767
244567
  const issues = [];
243768
- if (!existsSync21(root)) {
244568
+ if (!existsSync22(root)) {
243769
244569
  return [{ field: root, message: "Folder not found." }];
243770
244570
  }
243771
- if (existsSync21(join12(root, "manifest.json"))) {
244571
+ if (existsSync22(join12(root, "manifest.json"))) {
243772
244572
  issues.push({
243773
244573
  field: "manifest.json",
243774
244574
  message: "Top-level manifest.json is the legacy format. Re-export the dataset using the folder convention."
243775
244575
  });
243776
244576
  }
243777
244577
  const examplesDir = join12(root, "examples");
243778
- if (!existsSync21(examplesDir)) {
244578
+ if (!existsSync22(examplesDir)) {
243779
244579
  issues.push({ field: "examples/", message: "No examples/ directory found at dataset root." });
243780
244580
  return issues;
243781
244581
  }
@@ -243791,7 +244591,7 @@ function validateDatasetFolder(root) {
243791
244591
  continue;
243792
244592
  }
243793
244593
  const inputJsonPath = join12(exampleFolder, "input.json");
243794
- const hasInputJson = existsSync21(inputJsonPath);
244594
+ const hasInputJson = existsSync22(inputJsonPath);
243795
244595
  if (!hasInputJson) {
243796
244596
  issues.push({
243797
244597
  field: `examples/${exampleName}/input.json`,
@@ -243801,7 +244601,7 @@ function validateDatasetFolder(root) {
243801
244601
  }
243802
244602
  let args;
243803
244603
  try {
243804
- const parsed = JSON.parse(readFileSync18(inputJsonPath, "utf-8"));
244604
+ const parsed = JSON.parse(readFileSync19(inputJsonPath, "utf-8"));
243805
244605
  if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
243806
244606
  issues.push({
243807
244607
  field: `examples/${exampleName}/input.json`,
@@ -243818,7 +244618,7 @@ function validateDatasetFolder(root) {
243818
244618
  continue;
243819
244619
  }
243820
244620
  const inputDir = join12(exampleFolder, "input");
243821
- if (existsSync21(join12(inputDir, "arguments.json"))) {
244621
+ if (existsSync22(join12(inputDir, "arguments.json"))) {
243822
244622
  issues.push({
243823
244623
  field: `examples/${exampleName}/input/arguments.json`,
243824
244624
  message: "Legacy input/arguments.json is no longer accepted. Use input.json instead."
@@ -243835,7 +244635,7 @@ function validateDatasetFolder(root) {
243835
244635
  }
243836
244636
  const expectedDir = join12(exampleFolder, "expected");
243837
244637
  const expectedJsonPath = join12(exampleFolder, "expected.json");
243838
- if (existsSync21(expectedDir)) {
244638
+ if (existsSync22(expectedDir)) {
243839
244639
  for (const entry of readdirSync7(expectedDir)) {
243840
244640
  if (entry === "output.json" || entry === "error.json") {
243841
244641
  issues.push({
@@ -243871,10 +244671,10 @@ function validateDatasetFolder(root) {
243871
244671
  }
243872
244672
  }
243873
244673
  }
243874
- if (existsSync21(expectedJsonPath)) {
244674
+ if (existsSync22(expectedJsonPath)) {
243875
244675
  let parsed;
243876
244676
  try {
243877
- parsed = JSON.parse(readFileSync18(expectedJsonPath, "utf-8"));
244677
+ parsed = JSON.parse(readFileSync19(expectedJsonPath, "utf-8"));
243878
244678
  } catch {
243879
244679
  issues.push({
243880
244680
  field: `examples/${exampleName}/expected.json`,
@@ -243953,7 +244753,7 @@ function validateFileRefs2(args) {
243953
244753
  });
243954
244754
  continue;
243955
244755
  }
243956
- if (!existsSync21(join12(args.filesRoot, relative))) {
244756
+ if (!existsSync22(join12(args.filesRoot, relative))) {
243957
244757
  issues.push({
243958
244758
  field: `${args.fieldPrefix}:${ref.jsonPath}`,
243959
244759
  message: `Referenced file does not exist: ${ref.path}.`
@@ -243974,7 +244774,7 @@ function parseDatasetFileRef(path, root) {
243974
244774
  return parts.join("/");
243975
244775
  }
243976
244776
  function rootDir(opts) {
243977
- return resolve9(opts.dir ?? process.cwd());
244777
+ return resolve10(opts.dir ?? process.cwd());
243978
244778
  }
243979
244779
  async function onlineInvokeIssues(yamlText, opts) {
243980
244780
  const config = resolveConfig(opts);
@@ -243984,8 +244784,8 @@ async function onlineInvokeIssues(yamlText, opts) {
243984
244784
  return res.issues ?? [];
243985
244785
  }
243986
244786
  function discoverWorkflowProjectRoots(rootPath) {
243987
- const root = resolve9(rootPath);
243988
- if (existsSync21(join12(root, "workflow.yaml")))
244787
+ const root = resolve10(rootPath);
244788
+ if (existsSync22(join12(root, "workflow.yaml")))
243989
244789
  return [root];
243990
244790
  const candidates = [
243991
244791
  join12(root, "eigenpal", "workflows"),
@@ -243993,9 +244793,9 @@ function discoverWorkflowProjectRoots(rootPath) {
243993
244793
  root.endsWith(join12("eigenpal", "workflows")) ? root : ""
243994
244794
  ].filter(Boolean);
243995
244795
  for (const parent of candidates) {
243996
- if (!existsSync21(parent) || !statSync7(parent).isDirectory())
244796
+ if (!existsSync22(parent) || !statSync7(parent).isDirectory())
243997
244797
  continue;
243998
- const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync21(join12(parent, entry.name, "workflow.yaml"))).map((entry) => join12(parent, entry.name)).sort();
244798
+ const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() && existsSync22(join12(parent, entry.name, "workflow.yaml"))).map((entry) => join12(parent, entry.name)).sort();
243999
244799
  if (projects.length > 0)
244000
244800
  return projects;
244001
244801
  }
@@ -244012,10 +244812,10 @@ async function validateProjectRoot(root, opts) {
244012
244812
  }
244013
244813
  const evOk = printIssues("evaluators.yaml", relPath(root, join12(root, "evaluators.yaml")), validateEvaluatorsYaml(join12(root, "evaluators.yaml")));
244014
244814
  const dsOk = printIssues("dataset/", relPath(root, join12(root, "dataset")), validateDatasetFolder(join12(root, "dataset")));
244015
- const templateOk = wfOk && existsSync21(wfFile) ? await runTemplateDiagnostics(wfFile, wfResult.steps, opts) : true;
244815
+ const templateOk = wfOk && existsSync22(wfFile) ? await runTemplateDiagnostics(wfFile, wfResult.steps, opts) : true;
244016
244816
  let onlineOk = true;
244017
- if (wfOk && opts.online && existsSync21(wfFile)) {
244018
- onlineOk = printIssues("invoke refs (server)", wfPath, await onlineInvokeIssues(readFileSync18(wfFile, "utf-8"), opts));
244817
+ if (wfOk && opts.online && existsSync22(wfFile)) {
244818
+ onlineOk = printIssues("invoke refs (server)", wfPath, await onlineInvokeIssues(readFileSync19(wfFile, "utf-8"), opts));
244019
244819
  }
244020
244820
  return wfOk && evOk && dsOk && templateOk && onlineOk;
244021
244821
  }
@@ -244031,8 +244831,8 @@ Note
244031
244831
  ` + ` project unless you pass --allow-external-templates.
244032
244832
  `);
244033
244833
  withBaseUrl(cmd).action(action(async (path, opts) => {
244034
- if (path && (!existsSync21(resolve9(path)) || !statSync7(resolve9(path)).isDirectory())) {
244035
- const target = resolve9(path);
244834
+ if (path && (!existsSync22(resolve10(path)) || !statSync7(resolve10(path)).isDirectory())) {
244835
+ const target = resolve10(path);
244036
244836
  const wfResult = validateWorkflowYaml(target);
244037
244837
  const wfOk = printIssues("workflow.yaml", target, wfResult.issues);
244038
244838
  if (wfOk) {
@@ -244042,13 +244842,13 @@ Note
244042
244842
  const templateOk = wfOk ? await runTemplateDiagnostics(target, wfResult.steps, opts) : true;
244043
244843
  let onlineOk = true;
244044
244844
  if (wfOk && opts.online) {
244045
- onlineOk = printIssues("invoke refs (server)", target, await onlineInvokeIssues(readFileSync18(target, "utf-8"), opts));
244845
+ onlineOk = printIssues("invoke refs (server)", target, await onlineInvokeIssues(readFileSync19(target, "utf-8"), opts));
244046
244846
  }
244047
244847
  if (!wfOk || !templateOk || !onlineOk)
244048
244848
  process.exit(1);
244049
244849
  return;
244050
244850
  }
244051
- const requestedRoot = path ? resolve9(path) : rootDir(opts);
244851
+ const requestedRoot = path ? resolve10(path) : rootDir(opts);
244052
244852
  const projects = discoverWorkflowProjectRoots(requestedRoot);
244053
244853
  if (projects.length === 0) {
244054
244854
  if (!await validateProjectRoot(requestedRoot, opts))
@@ -244070,14 +244870,14 @@ Note
244070
244870
  }
244071
244871
  function registerEvaluatorsValidateCommand(parent) {
244072
244872
  parent.command("validate [path]").description("Validate an evaluators YAML file against the EvalConfig schema. Defaults to ./evaluators.yaml.").action((path) => {
244073
- const target = resolve9(path ?? "evaluators.yaml");
244873
+ const target = resolve10(path ?? "evaluators.yaml");
244074
244874
  if (!printIssues("evaluators", target, validateEvaluatorsYaml(target)))
244075
244875
  process.exit(1);
244076
244876
  });
244077
244877
  }
244078
244878
  function registerDatasetValidateCommand(parent) {
244079
244879
  parent.command("validate [path]").description("Validate a dataset folder against the examples/<name>/{input,expected,meta} convention. Defaults to ./dataset/.").action((path) => {
244080
- const target = resolve9(path ?? "dataset");
244880
+ const target = resolve10(path ?? "dataset");
244081
244881
  if (!printIssues("dataset", target, validateDatasetFolder(target)))
244082
244882
  process.exit(1);
244083
244883
  });
@@ -244091,20 +244891,20 @@ function relPath(root, target) {
244091
244891
  }
244092
244892
 
244093
244893
  // src/commands/workflow/index.ts
244094
- function buildClient3(opts) {
244894
+ function buildClient4(opts) {
244095
244895
  const config = resolveConfig(opts);
244096
244896
  requireApiKey(config);
244097
244897
  return new ApiClient(config);
244098
244898
  }
244099
244899
  async function buildClientForWorkflow(workflowIdOrSlug, opts) {
244100
- const client = buildClient3(opts);
244900
+ const client = buildClient4(opts);
244101
244901
  const workflowId = await resolveWorkflowId(client, workflowIdOrSlug);
244102
244902
  return { client, workflowId };
244103
244903
  }
244104
244904
  function descriptionFor(tool) {
244105
244905
  return WORKFLOW_TOOL_METADATA[tool].description;
244106
244906
  }
244107
- function printJson3(value) {
244907
+ function printJson4(value) {
244108
244908
  console.log(JSON.stringify(value, null, 2));
244109
244909
  }
244110
244910
  function extractWorkflowVersion(yaml) {
@@ -244205,7 +245005,7 @@ YAML's \`name:\` field). Both:
244205
245005
  function registerWorkflowCoreCommands(parent) {
244206
245006
  const listCmd = parent.command("list").description(descriptionFor("workflow_list")).option("--search <q>", "Filter by name");
244207
245007
  addJsonFlag(withBaseUrl(withPagination(listCmd))).action(action(async (opts) => {
244208
- const client = buildClient3(opts);
245008
+ const client = buildClient4(opts);
244209
245009
  const params = {
244210
245010
  limit: String(opts.limit),
244211
245011
  offset: String(opts.offset)
@@ -244293,7 +245093,7 @@ new uploads are deleted. The file on disk is not rewritten.
244293
245093
  defaultValue: "workflow.yaml",
244294
245094
  validate: (value) => {
244295
245095
  const p = value || "workflow.yaml";
244296
- if (!existsSync22(p))
245096
+ if (!existsSync23(p))
244297
245097
  return `Not found: ${p}`;
244298
245098
  return;
244299
245099
  }
@@ -244308,7 +245108,7 @@ new uploads are deleted. The file on disk is not rewritten.
244308
245108
  }
244309
245109
  }
244310
245110
  const yamlOnDisk = await fs20.readFile(filePath, "utf8");
244311
- const client = buildClient3(opts);
245111
+ const client = buildClient4(opts);
244312
245112
  const definition = parseWorkflowOrThrow(yamlOnDisk);
244313
245113
  const loadedTemplates = await loadLocalTemplatesForPush(filePath, definition.steps, {
244314
245114
  allowExternal: Boolean(opts.allowExternalTemplates)
@@ -244366,7 +245166,7 @@ new uploads are deleted. The file on disk is not rewritten.
244366
245166
  });
244367
245167
  await finalizeCreatedWorkspaceTemplates(client, created);
244368
245168
  if (opts.json) {
244369
- printJson3(withLocalTemplates(result, resolvedTemplates));
245169
+ printJson4(withLocalTemplates(result, resolvedTemplates));
244370
245170
  return;
244371
245171
  }
244372
245172
  success(`Pushed ${ui.bold(workflowId)} (v${result.version ?? nextVersion})`);
@@ -244380,7 +245180,7 @@ new uploads are deleted. The file on disk is not rewritten.
244380
245180
  });
244381
245181
  await finalizeCreatedWorkspaceTemplates(client, created);
244382
245182
  if (opts.json) {
244383
- printJson3(withLocalTemplates(result, resolvedTemplates));
245183
+ printJson4(withLocalTemplates(result, resolvedTemplates));
244384
245184
  return;
244385
245185
  }
244386
245186
  const id = result.workflow?.id ?? result.id ?? "?";
@@ -244399,7 +245199,7 @@ new uploads are deleted. The file on disk is not rewritten.
244399
245199
  folderPath: opts.folder
244400
245200
  });
244401
245201
  if (opts.json) {
244402
- printJson3(result);
245202
+ printJson4(result);
244403
245203
  return;
244404
245204
  }
244405
245205
  const target = opts.folder.trim() === "/" ? "root" : opts.folder;
@@ -244572,7 +245372,7 @@ function registerEvaluatorsCommands(parent) {
244572
245372
  yaml
244573
245373
  });
244574
245374
  if (opts.json) {
244575
- printJson3(result);
245375
+ printJson4(result);
244576
245376
  return;
244577
245377
  }
244578
245378
  let count = null;
@@ -244680,7 +245480,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
244680
245480
  }));
244681
245481
  if (issues.length === 0) {
244682
245482
  error2("Import aborted with no structured issues — server-side bug.");
244683
- printJson3(terminal);
245483
+ printJson4(terminal);
244684
245484
  } else {
244685
245485
  printIssues("dataset", opts.file, issues);
244686
245486
  if (errPayload.limitMb != null && errPayload.actualMb != null) {
@@ -244701,7 +245501,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
244701
245501
  if (terminal.phase === "done") {
244702
245502
  const done = terminal;
244703
245503
  if (opts.json) {
244704
- printJson3(done);
245504
+ printJson4(done);
244705
245505
  return;
244706
245506
  }
244707
245507
  const created = done.created ?? 0;
@@ -244719,7 +245519,7 @@ skip in CI). Folder layout reference: \`packages/cli/src/skill/reference/dataset
244719
245519
  }
244720
245520
  } else {
244721
245521
  error2(`Import response had unexpected terminal phase: ${terminal.phase}`);
244722
- printJson3(terminal);
245522
+ printJson4(terminal);
244723
245523
  process.exit(1);
244724
245524
  }
244725
245525
  }));
@@ -244779,7 +245579,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
244779
245579
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
244780
245580
  const result = await client.post(`/v1/automations/${workflowId}/examples`, body);
244781
245581
  if (opts.json) {
244782
- printJson3(result);
245582
+ printJson4(result);
244783
245583
  return;
244784
245584
  }
244785
245585
  success(`Created example ${ui.bold(opts.name)} (${result.id}) in ${ui.bold(workflowId)}`);
@@ -244805,7 +245605,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
244805
245605
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
244806
245606
  const result = await client.patch(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`, body);
244807
245607
  if (opts.json) {
244808
- printJson3(result);
245608
+ printJson4(result);
244809
245609
  return;
244810
245610
  }
244811
245611
  const fields = Object.keys(body).join(", ");
@@ -244819,7 +245619,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
244819
245619
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
244820
245620
  const deleted = await client.delete(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`);
244821
245621
  if (opts.json) {
244822
- printJson3(deleted);
245622
+ printJson4(deleted);
244823
245623
  return;
244824
245624
  }
244825
245625
  success(`Deleted example ${ui.bold(deleted.name ?? exampleId)} ${ui.dim(`(${exampleId})`)} from ${ui.bold(workflowId)}`);
@@ -244829,7 +245629,7 @@ exclusive. To attach files without a dataset folder, pass ingress refs in JSON:
244829
245629
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
244830
245630
  const row = await client.get(`/v1/automations/${workflowId}/examples/${encodeURIComponent(exampleId)}`);
244831
245631
  if (opts.json) {
244832
- printJson3(row);
245632
+ printJson4(row);
244833
245633
  return;
244834
245634
  }
244835
245635
  renderExampleHuman(row);
@@ -244956,7 +245756,7 @@ returns immediately with \`{ batchId, total }\`; poll
244956
245756
  const total = start.runCount ?? start.total ?? 0;
244957
245757
  if (!opts.wait) {
244958
245758
  if (opts.json) {
244959
- printJson3({ ...start, batchId: experimentId, total });
245759
+ printJson4({ ...start, batchId: experimentId, total });
244960
245760
  return;
244961
245761
  }
244962
245762
  success(`Started experiment ${ui.bold(experimentId)} ${ui.dim(`(${total} run${total === 1 ? "" : "s"} queued)`)}`);
@@ -244970,7 +245770,7 @@ returns immediately with \`{ batchId, total }\`; poll
244970
245770
  const status = await client.get(`/v1/automations/${workflowId}/experiments/${experimentId}`);
244971
245771
  if (status.status === "completed") {
244972
245772
  if (opts.json) {
244973
- printJson3({
245773
+ printJson4({
244974
245774
  ...status,
244975
245775
  batchId: experimentId,
244976
245776
  total: status.runCount ?? status.total
@@ -244990,7 +245790,7 @@ returns immediately with \`{ batchId, total }\`; poll
244990
245790
  }
244991
245791
  if (Date.now() >= deadline) {
244992
245792
  if (opts.json) {
244993
- printJson3({
245793
+ printJson4({
244994
245794
  ...status,
244995
245795
  batchId: experimentId,
244996
245796
  total: status.runCount ?? status.total
@@ -245030,12 +245830,12 @@ returns immediately with \`{ batchId, total }\`; poll
245030
245830
  const summary = summarizeExperimentExecutions(execs);
245031
245831
  if (execs.length === 0) {
245032
245832
  if (opts.json)
245033
- printJson3({ ...result, summary: rollupForJson(summary) });
245833
+ printJson4({ ...result, summary: rollupForJson(summary) });
245034
245834
  error2(`Experiment ${batchId} still has no executions after retrying — check the batch id.`);
245035
245835
  process.exit(1);
245036
245836
  }
245037
245837
  if (opts.json) {
245038
- printJson3({ ...result, summary: rollupForJson(summary) });
245838
+ printJson4({ ...result, summary: rollupForJson(summary) });
245039
245839
  return;
245040
245840
  }
245041
245841
  if (opts.short) {
@@ -245067,7 +245867,7 @@ returns immediately with \`{ batchId, total }\`; poll
245067
245867
  maxWait: opts.maxWait,
245068
245868
  onTerminal: (result, summary) => {
245069
245869
  if (wantPayload) {
245070
- printJson3({ ...result, summary: rollupForJson(summary) });
245870
+ printJson4({ ...result, summary: rollupForJson(summary) });
245071
245871
  } else {
245072
245872
  process.stderr.write(`${ui.dim(`use --include payload (or --json) for the full per-execution snapshot`)}
245073
245873
  `);
@@ -245075,7 +245875,7 @@ returns immediately with \`{ batchId, total }\`; poll
245075
245875
  },
245076
245876
  onDeadline: (result, summary) => {
245077
245877
  if (wantPayload)
245078
- printJson3({ ...result, summary: rollupForJson(summary) });
245878
+ printJson4({ ...result, summary: rollupForJson(summary) });
245079
245879
  }
245080
245880
  });
245081
245881
  }));
@@ -245099,7 +245899,7 @@ Behavior:
245099
245899
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
245100
245900
  const result = await client.post(`/v1/automations/${workflowId}/experiments/${batchId}/cancel`);
245101
245901
  if (opts.json) {
245102
- printJson3(result);
245902
+ printJson4(result);
245103
245903
  return;
245104
245904
  }
245105
245905
  const c = result.counts;
@@ -245173,7 +245973,7 @@ batches must belong to the same workflow within the caller's tenant.
245173
245973
  if (!Number.isFinite(threshold) || threshold < 0) {
245174
245974
  throw new Error("--regression-threshold must be a non-negative number");
245175
245975
  }
245176
- const client = buildClient3(opts);
245976
+ const client = buildClient4(opts);
245177
245977
  if (opts.outputs) {
245178
245978
  const [outputsA, outputsB] = await Promise.all([
245179
245979
  fetchExperimentOutputs(client, batchIdA),
@@ -245189,7 +245989,7 @@ batches must belong to the same workflow within the caller's tenant.
245189
245989
  rowsB: outputsB.rows
245190
245990
  });
245191
245991
  if (opts.json)
245192
- printJson3(outputDiff);
245992
+ printJson4(outputDiff);
245193
245993
  else
245194
245994
  renderExperimentOutputDiffHuman(outputDiff);
245195
245995
  return;
@@ -245207,7 +246007,7 @@ batches must belong to the same workflow within the caller's tenant.
245207
246007
  regressionThreshold: threshold
245208
246008
  });
245209
246009
  if (opts.json) {
245210
- printJson3(diff);
246010
+ printJson4(diff);
245211
246011
  return;
245212
246012
  }
245213
246013
  renderBatchDiffHuman(diff);
@@ -245245,7 +246045,7 @@ Behavior:
245245
246045
  const dest = opts.pull ? opts.pullOnComplete ?? `./results-${batchId}.${opts.format}` : null;
245246
246046
  if (dest) {
245247
246047
  const dir = path18.dirname(dest);
245248
- if (!existsSync22(dir)) {
246048
+ if (!existsSync23(dir)) {
245249
246049
  error2(`Destination directory does not exist: ${dir}. Create it first or pass a path under an existing directory.`);
245250
246050
  process.exit(2);
245251
246051
  }
@@ -245492,7 +246292,7 @@ sent to the server is replaced with \`templateId\` + \`templateRevisionId\`.
245492
246292
  const result = await client.post(automationVersionsPath(workflowId), body).catch((err) => rethrowAfterTemplateCleanup(client, created, err));
245493
246293
  await finalizeCreatedWorkspaceTemplates(client, created);
245494
246294
  if (opts.json) {
245495
- printJson3(withLocalTemplates(result, resolvedTemplates));
246295
+ printJson4(withLocalTemplates(result, resolvedTemplates));
245496
246296
  return;
245497
246297
  }
245498
246298
  const id = typeof result.id === "string" ? result.id : "?";
@@ -245515,7 +246315,7 @@ restore HEAD) return 404 — create a tagged copy first.
245515
246315
  const { client, workflowId } = await buildClientForWorkflow(workflow, opts);
245516
246316
  const result = await client.post(automationVersionsPath(workflowId, `/${encodeURIComponent(versionId)}/promote`));
245517
246317
  if (opts.json) {
245518
- printJson3(result);
246318
+ printJson4(result);
245519
246319
  return;
245520
246320
  }
245521
246321
  const label = formatWorkflowVersionLabel(result.version);
@@ -245538,7 +246338,7 @@ promoted until you create a tagged copy.
245538
246338
  const body = opts.message ? { message: opts.message } : {};
245539
246339
  const result = await client.post(automationVersionsPath(workflowId, `/${encodeURIComponent(versionId)}/restore`), body);
245540
246340
  if (opts.json) {
245541
- printJson3(result);
246341
+ printJson4(result);
245542
246342
  return;
245543
246343
  }
245544
246344
  const id = typeof result.id === "string" ? result.id : "?";
@@ -245787,7 +246587,7 @@ var HELP_GROUPS = [
245787
246587
  {
245788
246588
  title: "Authenticate",
245789
246589
  description: "Profiles in ~/.config/eigenpal/credentials.json",
245790
- commands: ["auth", "status", "models"]
246590
+ commands: ["auth", "status", "models", "email-servers"]
245791
246591
  },
245792
246592
  {
245793
246593
  title: "Workflows",
@@ -246015,6 +246815,7 @@ authCmd.command("use [profile]").description("Switch the active profile (persist
246015
246815
  registerWorkflowCommands(program2);
246016
246816
  registerAgentCommands(program2);
246017
246817
  registerModelsCommands(program2);
246818
+ registerEmailServersCommands(program2);
246018
246819
  registerRunCommands(program2);
246019
246820
  registerRunsCommands(program2);
246020
246821
  registerGitCommands(program2);