@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/CHANGELOG.md +6 -0
- package/dist/cli.js +964 -163
- package/dist/docs-bundle.json +46 -11
- package/dist/skill/reference/cli/email-servers.md +175 -0
- package/dist/skill/reference/cli/surface.md +7 -0
- package/dist/skill/reference/step-types.md +246 -0
- package/dist/skill/reference/workflow-yaml.md +2 -1
- package/package.json +1 -1
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.
|
|
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
|
|
241464
|
+
existsSync as existsSync15,
|
|
240651
241465
|
mkdirSync as mkdirSync5,
|
|
240652
241466
|
readdirSync as readdirSync4,
|
|
240653
|
-
readFileSync as
|
|
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
|
|
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 =
|
|
240671
|
-
if (
|
|
241484
|
+
const srcCandidate = resolve5(here, "..", "..", "templates");
|
|
241485
|
+
if (existsSync15(srcCandidate))
|
|
240672
241486
|
return srcCandidate;
|
|
240673
|
-
const distCandidate =
|
|
240674
|
-
if (
|
|
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 =
|
|
241498
|
+
const target = resolve5(process.cwd(), opts.dir ?? name);
|
|
240685
241499
|
assertSafeTargetDir(target, opts.dir);
|
|
240686
|
-
if (
|
|
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 (!
|
|
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 =
|
|
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
|
|
241050
|
-
import { join as join8, resolve as
|
|
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 (
|
|
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 (!
|
|
241868
|
+
if (!existsSync16(pkgPath))
|
|
241069
241869
|
return false;
|
|
241070
|
-
const raw =
|
|
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 =
|
|
241080
|
-
if (!
|
|
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
|
|
242007
|
+
existsSync as existsSync17,
|
|
241208
242008
|
lstatSync,
|
|
241209
242009
|
mkdirSync as mkdirSync6,
|
|
241210
|
-
readFileSync as
|
|
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
|
|
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 =
|
|
241293
|
-
if (
|
|
242092
|
+
const srcCandidate = resolve7(here, "..", "..", "skill");
|
|
242093
|
+
if (existsSync17(srcCandidate))
|
|
241294
242094
|
return srcCandidate;
|
|
241295
|
-
const distCandidate =
|
|
241296
|
-
if (
|
|
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,
|
|
242133
|
+
const sourceBytes = templateSourceFile(relativePath, readFileSync17(sourcePath), cliVersion);
|
|
241334
242134
|
const sourceHash = sha256(sourceBytes);
|
|
241335
|
-
if (!
|
|
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 =
|
|
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 (!
|
|
242173
|
+
if (!existsSync17(targetPath))
|
|
241374
242174
|
continue;
|
|
241375
|
-
manifestEntries.push({ path: relativePath, sha256: sha256(
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
242216
|
+
if (!existsSync17(path))
|
|
241417
242217
|
continue;
|
|
241418
|
-
const currentHash = sha256(
|
|
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
|
|
242419
|
+
return existsSync17(join10(cwd, tool.relativePath, MANIFEST_NAME));
|
|
241620
242420
|
}
|
|
241621
242421
|
function isProjectUsing(cwd, tool) {
|
|
241622
|
-
return tool.detectPaths.some((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 (!
|
|
242446
|
+
if (!existsSync17(path))
|
|
241647
242447
|
return null;
|
|
241648
242448
|
try {
|
|
241649
|
-
return JSON.parse(
|
|
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
|
-
|
|
241659
|
-
|
|
241660
|
-
|
|
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 (
|
|
241664
|
-
const pkg = JSON.parse(
|
|
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 (!
|
|
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
|
|
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
|
|
242471
|
-
import { basename, dirname as dirname6, isAbsolute, relative as relative4, resolve as
|
|
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 =
|
|
242713
|
-
if (!
|
|
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 =
|
|
243532
|
+
const candidate = resolve8(projectRoot, templatePath);
|
|
242733
243533
|
if (!opts.allowExternal) {
|
|
242734
243534
|
assertInsideProject(projectRoot, templatePath, candidate);
|
|
242735
243535
|
}
|
|
242736
|
-
if (!
|
|
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
|
|
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 (!
|
|
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 (!
|
|
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) =>
|
|
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) =>
|
|
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
|
|
243141
|
-
import { basename as basename3, resolve as
|
|
243142
|
-
function
|
|
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
|
|
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(
|
|
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: ${
|
|
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 =
|
|
244004
|
+
const filePath = resolve9(file);
|
|
243205
244005
|
const bytes = await fs19.readFile(filePath);
|
|
243206
|
-
const client =
|
|
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
|
-
|
|
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 =
|
|
244022
|
+
const client = buildClient3(opts);
|
|
243223
244023
|
const result = await listPublicTemplates(client, { limit: opts.limit, offset: opts.offset });
|
|
243224
244024
|
if (opts.json) {
|
|
243225
|
-
|
|
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 =
|
|
244050
|
+
const client = buildClient3(opts);
|
|
243251
244051
|
const template = await getPublicTemplate(client, templateId);
|
|
243252
244052
|
if (opts.json) {
|
|
243253
|
-
|
|
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 =
|
|
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 =
|
|
244069
|
+
const filePath = resolve9(file);
|
|
243270
244070
|
const bytes = await fs19.readFile(filePath);
|
|
243271
|
-
const client =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
244099
|
+
const client = buildClient3(opts);
|
|
243300
244100
|
const result = await deleteWorkspaceTemplate(client, templateId);
|
|
243301
244101
|
if (opts.json) {
|
|
243302
|
-
|
|
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 =
|
|
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 =
|
|
243321
|
-
if (!
|
|
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
|
-
|
|
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
|
|
243364
|
-
import { join as join12, resolve as
|
|
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
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
244548
|
+
if (!existsSync22(path)) {
|
|
243749
244549
|
return [{ field: path, message: "File not found." }];
|
|
243750
244550
|
}
|
|
243751
|
-
const text =
|
|
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 (!
|
|
244568
|
+
if (!existsSync22(root)) {
|
|
243769
244569
|
return [{ field: root, message: "Folder not found." }];
|
|
243770
244570
|
}
|
|
243771
|
-
if (
|
|
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 (!
|
|
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 =
|
|
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(
|
|
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 (
|
|
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 (
|
|
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 (
|
|
244674
|
+
if (existsSync22(expectedJsonPath)) {
|
|
243875
244675
|
let parsed;
|
|
243876
244676
|
try {
|
|
243877
|
-
parsed = JSON.parse(
|
|
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 (!
|
|
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
|
|
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 =
|
|
243988
|
-
if (
|
|
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 (!
|
|
244796
|
+
if (!existsSync22(parent) || !statSync7(parent).isDirectory())
|
|
243997
244797
|
continue;
|
|
243998
|
-
const projects = readdirSync7(parent, { withFileTypes: true }).filter((entry) => entry.isDirectory() && !entry.isSymbolicLink() &&
|
|
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 &&
|
|
244815
|
+
const templateOk = wfOk && existsSync22(wfFile) ? await runTemplateDiagnostics(wfFile, wfResult.steps, opts) : true;
|
|
244016
244816
|
let onlineOk = true;
|
|
244017
|
-
if (wfOk && opts.online &&
|
|
244018
|
-
onlineOk = printIssues("invoke refs (server)", wfPath, await onlineInvokeIssues(
|
|
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 && (!
|
|
244035
|
-
const target =
|
|
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(
|
|
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 ?
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
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 (!
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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);
|