@tarileo/avileo-catalog-cli 0.3.0 → 0.3.2
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/README.md +63 -16
- package/dist/index.js +342 -71
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -14729,18 +14729,19 @@ var AGENT_CAPABILITY_ACTIONS = [
|
|
|
14729
14729
|
"assets:read",
|
|
14730
14730
|
"assets:write",
|
|
14731
14731
|
"inventory:read",
|
|
14732
|
-
"inventory:write"
|
|
14732
|
+
"inventory:write",
|
|
14733
|
+
"payments:read",
|
|
14734
|
+
"payments:write"
|
|
14733
14735
|
];
|
|
14734
14736
|
var AgentCapabilityActionSchema = external_exports.enum(AGENT_CAPABILITY_ACTIONS);
|
|
14735
14737
|
var AGENT_KEY_MODES = ["read", "mutate"];
|
|
14736
14738
|
var AgentKeyModeSchema = external_exports.enum(AGENT_KEY_MODES);
|
|
14737
|
-
var
|
|
14739
|
+
var AGENT_KEY_READ_ACTIONS = [
|
|
14738
14740
|
"business:read",
|
|
14739
14741
|
"catalog:read",
|
|
14740
|
-
"catalog:write",
|
|
14741
14742
|
"assets:read",
|
|
14742
|
-
"
|
|
14743
|
-
"
|
|
14743
|
+
"inventory:read",
|
|
14744
|
+
"payments:read"
|
|
14744
14745
|
];
|
|
14745
14746
|
var AgentGrantedActionsSchema = external_exports.array(AgentCapabilityActionSchema).min(1).max(AGENT_CAPABILITY_ACTIONS.length).refine((actions) => new Set(actions).size === actions.length, {
|
|
14746
14747
|
message: "Las capacidades no pueden repetirse"
|
|
@@ -15221,9 +15222,91 @@ var AgentOperationApplyEnvelopeSchema = external_exports.object({
|
|
|
15221
15222
|
success: external_exports.literal(true),
|
|
15222
15223
|
data: external_exports.record(external_exports.string(), external_exports.unknown())
|
|
15223
15224
|
}).strict();
|
|
15225
|
+
var AGENT_PAYMENT_LINK_STATUSES = [
|
|
15226
|
+
"awaiting_payment",
|
|
15227
|
+
"verifying",
|
|
15228
|
+
"under_review",
|
|
15229
|
+
"confirmed",
|
|
15230
|
+
"rejected",
|
|
15231
|
+
"expired",
|
|
15232
|
+
"cancelled"
|
|
15233
|
+
];
|
|
15234
|
+
var AgentPaymentLinkStatusSchema = external_exports.enum(AGENT_PAYMENT_LINK_STATUSES);
|
|
15235
|
+
var AGENT_PAYMENT_LINK_EXPECTED_METHODS = [
|
|
15236
|
+
"yape",
|
|
15237
|
+
"plin",
|
|
15238
|
+
"transferencia",
|
|
15239
|
+
"any"
|
|
15240
|
+
];
|
|
15241
|
+
var AgentPaymentLinkExpectedMethodSchema = external_exports.enum(AGENT_PAYMENT_LINK_EXPECTED_METHODS);
|
|
15242
|
+
var AGENT_PAYMENT_LINK_CONFIRMED_BY = ["ai", "gateway", "manual", "platform"];
|
|
15243
|
+
var AgentPaymentLinkConfirmedBySchema = external_exports.enum(AGENT_PAYMENT_LINK_CONFIRMED_BY);
|
|
15244
|
+
var AgentPaymentLinkExtractionDtoSchema = external_exports.object({
|
|
15245
|
+
provider: external_exports.enum(["yape", "plin", "bbva_transfer", "unknown"]),
|
|
15246
|
+
/** Detected amount in soles (major units), or null when illegible. */
|
|
15247
|
+
detectedAmount: external_exports.number().nonnegative().multipleOf(0.01).nullable(),
|
|
15248
|
+
currency: external_exports.string().length(3).nullable(),
|
|
15249
|
+
operationNumber: external_exports.string().nullable(),
|
|
15250
|
+
paidAt: timestampSchema.nullable(),
|
|
15251
|
+
payerName: external_exports.string().nullable(),
|
|
15252
|
+
recipientName: external_exports.string().nullable(),
|
|
15253
|
+
confidence: external_exports.enum(["high", "medium", "low"]),
|
|
15254
|
+
signals: external_exports.array(external_exports.string())
|
|
15255
|
+
}).strict();
|
|
15256
|
+
var AgentCreatePaymentLinkInputSchema = external_exports.object({
|
|
15257
|
+
/** Amount in soles (major units); the backend stores amountMinor. */
|
|
15258
|
+
amount: external_exports.number().positive().multipleOf(0.01).max(1e6),
|
|
15259
|
+
currency: external_exports.string().trim().length(3).optional(),
|
|
15260
|
+
concept: nonEmptyTextSchema.max(200).optional(),
|
|
15261
|
+
expectedMethod: AgentPaymentLinkExpectedMethodSchema.optional(),
|
|
15262
|
+
expiresInHours: external_exports.number().int().min(1).max(720).optional(),
|
|
15263
|
+
customerPhone: nonEmptyTextSchema.max(20).optional(),
|
|
15264
|
+
idempotencyKey: nonEmptyTextSchema.max(80).optional()
|
|
15265
|
+
}).strict();
|
|
15266
|
+
var AgentPaymentLinkBaseDtoSchema = external_exports.object({
|
|
15267
|
+
id: uuidSchema,
|
|
15268
|
+
/** Requested amount in soles (major units). */
|
|
15269
|
+
amount: external_exports.number().positive().multipleOf(0.01),
|
|
15270
|
+
currency: external_exports.string().length(3),
|
|
15271
|
+
concept: external_exports.string().nullable(),
|
|
15272
|
+
expectedMethod: AgentPaymentLinkExpectedMethodSchema,
|
|
15273
|
+
status: AgentPaymentLinkStatusSchema,
|
|
15274
|
+
confirmedBy: AgentPaymentLinkConfirmedBySchema.nullable(),
|
|
15275
|
+
extraction: AgentPaymentLinkExtractionDtoSchema.nullable(),
|
|
15276
|
+
expiresAt: timestampSchema,
|
|
15277
|
+
createdAt: timestampSchema,
|
|
15278
|
+
confirmedAt: timestampSchema.nullable().optional()
|
|
15279
|
+
}).strict();
|
|
15280
|
+
var AgentPaymentLinkDtoSchema = AgentPaymentLinkBaseDtoSchema.extend({
|
|
15281
|
+
/** Persisted links can never recover the plaintext token URL. */
|
|
15282
|
+
url: external_exports.null()
|
|
15283
|
+
}).strict();
|
|
15284
|
+
var AgentCreatedPaymentLinkDtoSchema = external_exports.discriminatedUnion("replayed", [
|
|
15285
|
+
AgentPaymentLinkBaseDtoSchema.extend({
|
|
15286
|
+
url: external_exports.string().url(),
|
|
15287
|
+
replayed: external_exports.literal(false)
|
|
15288
|
+
}).strict(),
|
|
15289
|
+
AgentPaymentLinkBaseDtoSchema.extend({
|
|
15290
|
+
url: external_exports.null(),
|
|
15291
|
+
replayed: external_exports.literal(true)
|
|
15292
|
+
}).strict()
|
|
15293
|
+
]);
|
|
15294
|
+
var isoDateOrTimestampSchema = external_exports.union([
|
|
15295
|
+
external_exports.string().date(),
|
|
15296
|
+
external_exports.string().datetime({ offset: true })
|
|
15297
|
+
]);
|
|
15298
|
+
var AgentPaymentLinkFilterInputSchema = AgentPaginationInputSchema.extend({
|
|
15299
|
+
status: AgentPaymentLinkStatusSchema.optional(),
|
|
15300
|
+
from: isoDateOrTimestampSchema.optional(),
|
|
15301
|
+
to: isoDateOrTimestampSchema.optional()
|
|
15302
|
+
}).strict();
|
|
15303
|
+
var AgentPaymentLinkPageSchema = external_exports.object({
|
|
15304
|
+
items: external_exports.array(AgentPaymentLinkDtoSchema),
|
|
15305
|
+
total: external_exports.number().int().nonnegative()
|
|
15306
|
+
}).strict();
|
|
15224
15307
|
var AGENT_DEVICE_AUTH_STATUSES = ["pending", "approved", "denied", "expired"];
|
|
15225
15308
|
var AGENT_DEVICE_AUTH_DEFAULT_PERMISSIONS = [
|
|
15226
|
-
...
|
|
15309
|
+
...AGENT_KEY_READ_ACTIONS
|
|
15227
15310
|
];
|
|
15228
15311
|
function parsePollResponse(value) {
|
|
15229
15312
|
if (!AGENT_DEVICE_AUTH_STATUSES.includes(value.status)) {
|
|
@@ -15540,6 +15623,32 @@ var AgentOperationsResource = class {
|
|
|
15540
15623
|
});
|
|
15541
15624
|
}
|
|
15542
15625
|
};
|
|
15626
|
+
var AgentPaymentLinksResource = class {
|
|
15627
|
+
constructor(http) {
|
|
15628
|
+
this.http = http;
|
|
15629
|
+
}
|
|
15630
|
+
http;
|
|
15631
|
+
/**
|
|
15632
|
+
* Creates a payment link. `amount` is in soles (major units); the backend
|
|
15633
|
+
* converts it to minor units — never convert it here. The URL is only
|
|
15634
|
+
* non-null for the initial create response.
|
|
15635
|
+
*/
|
|
15636
|
+
create(input) {
|
|
15637
|
+
return this.http.request("/api/v1/agent/payment-links", {
|
|
15638
|
+
method: "POST",
|
|
15639
|
+
body: input,
|
|
15640
|
+
mutation: true
|
|
15641
|
+
}).then((response) => AgentCreatedPaymentLinkDtoSchema.parse(response));
|
|
15642
|
+
}
|
|
15643
|
+
/** Fetches a persisted link; `url` is always `null`. */
|
|
15644
|
+
get(paymentLinkId) {
|
|
15645
|
+
return this.http.request(`/api/v1/agent/payment-links/${encodeURIComponent(paymentLinkId)}`).then((response) => AgentPaymentLinkDtoSchema.parse(response));
|
|
15646
|
+
}
|
|
15647
|
+
/** Lists persisted links; every item has `url: null`. */
|
|
15648
|
+
list(filter = {}) {
|
|
15649
|
+
return this.http.request(`/api/v1/agent/payment-links${queryString(filter)}`).then((response) => AgentPaymentLinkPageSchema.parse(response));
|
|
15650
|
+
}
|
|
15651
|
+
};
|
|
15543
15652
|
function createAvileoAgent(config2) {
|
|
15544
15653
|
const http = new AgentHttpClient(config2);
|
|
15545
15654
|
return {
|
|
@@ -15551,7 +15660,8 @@ function createAvileoAgent(config2) {
|
|
|
15551
15660
|
tags: new AgentTagsResource(http),
|
|
15552
15661
|
assets: new AgentAssetsResource(http),
|
|
15553
15662
|
inventory: new AgentInventoryResource(http),
|
|
15554
|
-
imports: new AgentImportsResource(http)
|
|
15663
|
+
imports: new AgentImportsResource(http),
|
|
15664
|
+
paymentLinks: new AgentPaymentLinksResource(http)
|
|
15555
15665
|
};
|
|
15556
15666
|
}
|
|
15557
15667
|
|
|
@@ -15560,6 +15670,53 @@ import { chmodSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSy
|
|
|
15560
15670
|
import { randomUUID } from "crypto";
|
|
15561
15671
|
import { homedir } from "os";
|
|
15562
15672
|
import { dirname, join } from "path";
|
|
15673
|
+
import { isIP } from "net";
|
|
15674
|
+
var LOCAL_IPV4_HOST_PATTERN = /^(?:127\.|10\.|192\.168\.|169\.254\.|172\.(?:1[6-9]|2\d|3[01])\.|100\.(?:6[4-9]|[7-9]\d|1[01]\d|12[0-7])\.)/;
|
|
15675
|
+
function isLocalHostname(hostname3) {
|
|
15676
|
+
const host = hostname3.replace(/^\[|\]$/g, "").toLowerCase();
|
|
15677
|
+
if (host === "localhost" || host.endsWith(".localhost") || host.endsWith(".local")) return true;
|
|
15678
|
+
if (host === "::1" || host === "::" || /^f[cd][0-9a-f]{2}:/.test(host)) return true;
|
|
15679
|
+
if (host.includes(":")) return false;
|
|
15680
|
+
if (!host.includes(".")) return true;
|
|
15681
|
+
return isIP(host) === 4 && LOCAL_IPV4_HOST_PATTERN.test(host);
|
|
15682
|
+
}
|
|
15683
|
+
function normalizeApiBaseUrl(rawUrl) {
|
|
15684
|
+
const candidate = rawUrl.trim().replace(/\/+$/, "");
|
|
15685
|
+
if (!candidate) {
|
|
15686
|
+
throw new CliOriginUnsupportedError("La URL base de la API est\xE1 vac\xEDa");
|
|
15687
|
+
}
|
|
15688
|
+
let parsed;
|
|
15689
|
+
try {
|
|
15690
|
+
parsed = new URL(candidate);
|
|
15691
|
+
} catch {
|
|
15692
|
+
throw new CliOriginUnsupportedError(`La URL base de la API no es v\xE1lida: ${candidate}`);
|
|
15693
|
+
}
|
|
15694
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
15695
|
+
throw new CliOriginUnsupportedError(
|
|
15696
|
+
`La URL base debe usar HTTPS (o HTTP local de desarrollo); se recibi\xF3 ${parsed.protocol}//`
|
|
15697
|
+
);
|
|
15698
|
+
}
|
|
15699
|
+
if (parsed.protocol === "http:" && !isLocalHostname(parsed.hostname)) {
|
|
15700
|
+
throw new CliOriginUnsupportedError(
|
|
15701
|
+
"Solo se permite HTTP para hosts locales de desarrollo; usa un origen HTTPS"
|
|
15702
|
+
);
|
|
15703
|
+
}
|
|
15704
|
+
if (parsed.username || parsed.password) {
|
|
15705
|
+
throw new CliOriginUnsupportedError("La URL base no debe incluir credenciales embebidas");
|
|
15706
|
+
}
|
|
15707
|
+
if (parsed.search || parsed.hash) {
|
|
15708
|
+
throw new CliOriginUnsupportedError("La URL base no debe incluir query ni fragmento");
|
|
15709
|
+
}
|
|
15710
|
+
return `${parsed.protocol}//${parsed.host}${parsed.pathname.replace(/\/+$/, "")}`;
|
|
15711
|
+
}
|
|
15712
|
+
function apiOrigin(baseUrl) {
|
|
15713
|
+
const parsed = new URL(baseUrl);
|
|
15714
|
+
return `${parsed.protocol}//${parsed.host}`;
|
|
15715
|
+
}
|
|
15716
|
+
function overrideBaseUrl(env) {
|
|
15717
|
+
const raw = env.AVILEO_AGENT_BASE_URL?.trim();
|
|
15718
|
+
return raw ? normalizeApiBaseUrl(raw) : void 0;
|
|
15719
|
+
}
|
|
15563
15720
|
var AGENT_KEY_PATTERN = /^avileo_sk_[^\s]+$/;
|
|
15564
15721
|
function normalizeAgentKey(value, message) {
|
|
15565
15722
|
const key = value.trim();
|
|
@@ -15590,10 +15747,15 @@ function readLocalCredential(env = process.env) {
|
|
|
15590
15747
|
throw new CliConfigurationError("La credencial local no es una Agent Key v\xE1lida");
|
|
15591
15748
|
}
|
|
15592
15749
|
const apiKey = normalizeAgentKey(record2.apiKey, "La credencial local no es una Agent Key v\xE1lida");
|
|
15593
|
-
|
|
15594
|
-
|
|
15750
|
+
if (typeof record2.baseUrl !== "string" || !record2.baseUrl.trim()) {
|
|
15751
|
+
throw new CliConfigurationError(
|
|
15752
|
+
"La credencial local no tiene un origen vinculado. Vuelve a autorizar con auth login --base-url <URL_DEL_PORTAL> antes de usarla."
|
|
15753
|
+
);
|
|
15754
|
+
}
|
|
15755
|
+
return { apiKey, baseUrl: normalizeApiBaseUrl(record2.baseUrl) };
|
|
15595
15756
|
}
|
|
15596
15757
|
function resolveCredential(env = process.env) {
|
|
15758
|
+
const override = overrideBaseUrl(env);
|
|
15597
15759
|
const environmentValue = env.AVILEO_AGENT_API_KEY;
|
|
15598
15760
|
if (environmentValue !== void 0) {
|
|
15599
15761
|
return {
|
|
@@ -15602,31 +15764,29 @@ function resolveCredential(env = process.env) {
|
|
|
15602
15764
|
"AVILEO_AGENT_API_KEY no es una Agent Key v\xE1lida"
|
|
15603
15765
|
),
|
|
15604
15766
|
source: "environment",
|
|
15605
|
-
|
|
15767
|
+
baseUrl: override ?? AVILEO_AGENT_API_URL
|
|
15606
15768
|
};
|
|
15607
15769
|
}
|
|
15608
15770
|
const local = readLocalCredential(env);
|
|
15609
15771
|
if (!local) return null;
|
|
15610
|
-
|
|
15611
|
-
|
|
15612
|
-
|
|
15613
|
-
|
|
15614
|
-
}
|
|
15772
|
+
if (override && apiOrigin(local.baseUrl) !== apiOrigin(override)) {
|
|
15773
|
+
throw new CliOriginConflictError(
|
|
15774
|
+
`La credencial local est\xE1 vinculada al origen ${apiOrigin(local.baseUrl)}, pero AVILEO_AGENT_BASE_URL apunta a ${apiOrigin(override)}. La clave nunca se env\xEDa a otro origen: quita la variable de entorno o vuelve a autenticar con auth login --base-url ${apiOrigin(override)} para emitir una clave en ese origen.`
|
|
15775
|
+
);
|
|
15776
|
+
}
|
|
15777
|
+
return { ...local, source: "local" };
|
|
15615
15778
|
}
|
|
15616
15779
|
function saveLocalCredential(credential, env = process.env) {
|
|
15617
15780
|
const apiKey = normalizeAgentKey(
|
|
15618
15781
|
credential.apiKey,
|
|
15619
15782
|
"Solo se pueden guardar Agent Keys de Avileo"
|
|
15620
15783
|
);
|
|
15784
|
+
const baseUrl = normalizeApiBaseUrl(credential.baseUrl);
|
|
15621
15785
|
const path = localCredentialPath(env);
|
|
15622
15786
|
mkdirSync(dirname(path), { recursive: true, mode: 448 });
|
|
15623
15787
|
const temporaryPath = `${path}.${randomUUID()}.tmp`;
|
|
15624
|
-
writeFileSync(
|
|
15625
|
-
|
|
15626
|
-
`${JSON.stringify({ apiKey, ...credential.baseUrl ? { baseUrl: credential.baseUrl } : {} })}
|
|
15627
|
-
`,
|
|
15628
|
-
{ mode: 384 }
|
|
15629
|
-
);
|
|
15788
|
+
writeFileSync(temporaryPath, `${JSON.stringify({ apiKey, baseUrl })}
|
|
15789
|
+
`, { mode: 384 });
|
|
15630
15790
|
chmodSync(temporaryPath, 384);
|
|
15631
15791
|
renameSync(temporaryPath, path);
|
|
15632
15792
|
chmodSync(path, 384);
|
|
@@ -15650,7 +15810,7 @@ function createClientFromEnvironment({
|
|
|
15650
15810
|
}
|
|
15651
15811
|
return clientFactory({
|
|
15652
15812
|
apiKey: credential.apiKey,
|
|
15653
|
-
|
|
15813
|
+
baseUrl: credential.baseUrl
|
|
15654
15814
|
});
|
|
15655
15815
|
}
|
|
15656
15816
|
var CliConfigurationError = class extends Error {
|
|
@@ -15660,6 +15820,20 @@ var CliConfigurationError = class extends Error {
|
|
|
15660
15820
|
this.name = "CliConfigurationError";
|
|
15661
15821
|
}
|
|
15662
15822
|
};
|
|
15823
|
+
var CliOriginUnsupportedError = class extends CliConfigurationError {
|
|
15824
|
+
code = "CLI_ORIGIN_UNSUPPORTED";
|
|
15825
|
+
constructor(message) {
|
|
15826
|
+
super(message);
|
|
15827
|
+
this.name = "CliOriginUnsupportedError";
|
|
15828
|
+
}
|
|
15829
|
+
};
|
|
15830
|
+
var CliOriginConflictError = class extends CliConfigurationError {
|
|
15831
|
+
code = "CLI_ORIGIN_CONFLICT";
|
|
15832
|
+
constructor(message) {
|
|
15833
|
+
super(message);
|
|
15834
|
+
this.name = "CliOriginConflictError";
|
|
15835
|
+
}
|
|
15836
|
+
};
|
|
15663
15837
|
|
|
15664
15838
|
// src/output.ts
|
|
15665
15839
|
var CliProtocolError = class extends Error {
|
|
@@ -15720,34 +15894,8 @@ function redact(value) {
|
|
|
15720
15894
|
return value;
|
|
15721
15895
|
}
|
|
15722
15896
|
|
|
15723
|
-
// src/commands/
|
|
15724
|
-
|
|
15725
|
-
const business = root.command("business").description("Consulta el negocio vinculado a la clave agente");
|
|
15726
|
-
business.command("show").description("Muestra las capacidades seguras del negocio").action(async () => {
|
|
15727
|
-
emitSuccess(await getClient().business.get());
|
|
15728
|
-
});
|
|
15729
|
-
}
|
|
15730
|
-
|
|
15731
|
-
// src/commands/catalog.ts
|
|
15732
|
-
import { createHash } from "crypto";
|
|
15733
|
-
import { readFile, stat } from "fs/promises";
|
|
15734
|
-
import { basename, extname } from "path";
|
|
15735
|
-
function requireId(value, name) {
|
|
15736
|
-
if (!value.trim()) throw new CliProtocolError("CLI_VALIDATION_ERROR", `${name} es obligatorio`);
|
|
15737
|
-
return value;
|
|
15738
|
-
}
|
|
15739
|
-
async function readMutationInput(path) {
|
|
15740
|
-
let parsed;
|
|
15741
|
-
try {
|
|
15742
|
-
parsed = JSON.parse(await readFile(path, "utf8"));
|
|
15743
|
-
} catch {
|
|
15744
|
-
throw new CliProtocolError("CLI_INPUT_ERROR", "No se pudo leer un objeto JSON desde --from");
|
|
15745
|
-
}
|
|
15746
|
-
if (!parsed || Array.isArray(parsed) || typeof parsed !== "object") {
|
|
15747
|
-
throw new CliProtocolError("CLI_VALIDATION_ERROR", "--from debe contener un objeto JSON");
|
|
15748
|
-
}
|
|
15749
|
-
return normalizeInput(parsed);
|
|
15750
|
-
}
|
|
15897
|
+
// src/commands/mutation.ts
|
|
15898
|
+
import { readFile } from "fs/promises";
|
|
15751
15899
|
function normalizeInput(value) {
|
|
15752
15900
|
const forbidden = {
|
|
15753
15901
|
businessId: true,
|
|
@@ -15770,12 +15918,17 @@ function normalizeInput(value) {
|
|
|
15770
15918
|
};
|
|
15771
15919
|
return visit(value);
|
|
15772
15920
|
}
|
|
15773
|
-
function
|
|
15774
|
-
|
|
15775
|
-
|
|
15776
|
-
|
|
15777
|
-
|
|
15778
|
-
|
|
15921
|
+
async function readMutationInput(path) {
|
|
15922
|
+
let parsed;
|
|
15923
|
+
try {
|
|
15924
|
+
parsed = JSON.parse(await readFile(path, "utf8"));
|
|
15925
|
+
} catch {
|
|
15926
|
+
throw new CliProtocolError("CLI_INPUT_ERROR", "No se pudo leer un objeto JSON desde --from");
|
|
15927
|
+
}
|
|
15928
|
+
if (!parsed || Array.isArray(parsed) || typeof parsed !== "object") {
|
|
15929
|
+
throw new CliProtocolError("CLI_VALIDATION_ERROR", "--from debe contener un objeto JSON");
|
|
15930
|
+
}
|
|
15931
|
+
return normalizeInput(parsed);
|
|
15779
15932
|
}
|
|
15780
15933
|
function localResult(input, current) {
|
|
15781
15934
|
if (current === void 0) return { validated: "local", input };
|
|
@@ -15785,6 +15938,53 @@ function localResult(input, current) {
|
|
|
15785
15938
|
);
|
|
15786
15939
|
return { validated: "local", current, changes };
|
|
15787
15940
|
}
|
|
15941
|
+
|
|
15942
|
+
// src/commands/business.ts
|
|
15943
|
+
function profileValues(profile) {
|
|
15944
|
+
const values = profile.values;
|
|
15945
|
+
if (!values || Array.isArray(values) || typeof values !== "object") return {};
|
|
15946
|
+
return values;
|
|
15947
|
+
}
|
|
15948
|
+
function registerBusinessCommands(root, getClient) {
|
|
15949
|
+
const business = root.command("business").description("Consulta el negocio vinculado a la clave agente");
|
|
15950
|
+
business.command("show").description("Muestra las capacidades seguras del negocio").action(async () => {
|
|
15951
|
+
emitSuccess(await getClient().business.get());
|
|
15952
|
+
});
|
|
15953
|
+
const profile = business.command("profile").description("Consulta o propone cambios al perfil del negocio");
|
|
15954
|
+
profile.command("show").description("Muestra campos, valores y completitud del perfil").action(async () => {
|
|
15955
|
+
emitSuccess(await getClient().business.profile());
|
|
15956
|
+
});
|
|
15957
|
+
profile.command("update").description("Previsualiza o propone cambios al perfil").requiredOption("--from <json-file>", "Valores de perfil en un objeto JSON").option("--apply", "Crea una propuesta para aprobaci\xF3n en Avileo").action(async (options, command) => {
|
|
15958
|
+
const values = await readMutationInput(options.from);
|
|
15959
|
+
if (!command.optsWithGlobals().apply) {
|
|
15960
|
+
const current = await getClient().business.profile();
|
|
15961
|
+
emitSuccess(localResult(values, profileValues(current)));
|
|
15962
|
+
return;
|
|
15963
|
+
}
|
|
15964
|
+
emitSuccess(
|
|
15965
|
+
await getClient().operations.propose({
|
|
15966
|
+
operationName: "business.profile.update",
|
|
15967
|
+
payload: { values }
|
|
15968
|
+
})
|
|
15969
|
+
);
|
|
15970
|
+
});
|
|
15971
|
+
}
|
|
15972
|
+
|
|
15973
|
+
// src/commands/catalog.ts
|
|
15974
|
+
import { createHash } from "crypto";
|
|
15975
|
+
import { readFile as readFile2, stat } from "fs/promises";
|
|
15976
|
+
import { basename, extname } from "path";
|
|
15977
|
+
function requireId(value, name) {
|
|
15978
|
+
if (!value.trim()) throw new CliProtocolError("CLI_VALIDATION_ERROR", `${name} es obligatorio`);
|
|
15979
|
+
return value;
|
|
15980
|
+
}
|
|
15981
|
+
function withMutationOptions(command, includeFrom = true) {
|
|
15982
|
+
if (includeFrom) command.requiredOption("--from <json-file>", "Objeto JSON estructurado");
|
|
15983
|
+
return command.option("--apply", "Solicita aprobaci\xF3n o ejecuta una mutaci\xF3n aprobada").option("--approval-id <uuid>", "Aprobaci\xF3n emitida por Avileo");
|
|
15984
|
+
}
|
|
15985
|
+
function wantsApply(command) {
|
|
15986
|
+
return Boolean(command.optsWithGlobals().apply);
|
|
15987
|
+
}
|
|
15788
15988
|
function addListOptions(command) {
|
|
15789
15989
|
return command.option("--search <text>").option("--category-id <id>").option("--active <true|false>", "Filtra por estado activo", parseBoolean).option("--limit <number>", "M\xE1ximo de resultados", parseInteger).option("--offset <number>", "Desplazamiento", parseInteger);
|
|
15790
15990
|
}
|
|
@@ -16071,7 +16271,7 @@ function registerAssetCommands(catalog, getClient) {
|
|
|
16071
16271
|
"Solo se permiten im\xE1genes JPEG, PNG o WebP"
|
|
16072
16272
|
);
|
|
16073
16273
|
}
|
|
16074
|
-
const contents = await
|
|
16274
|
+
const contents = await readFile2(filePath);
|
|
16075
16275
|
const file2 = new File([contents], basename(filePath), { type: mimeType });
|
|
16076
16276
|
const rawApprovalId = command.optsWithGlobals().approvalId;
|
|
16077
16277
|
if (typeof rawApprovalId === "string") {
|
|
@@ -16212,6 +16412,57 @@ function safeFinalResult(start, browserOpened, result) {
|
|
|
16212
16412
|
function sleep(milliseconds) {
|
|
16213
16413
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
16214
16414
|
}
|
|
16415
|
+
function readAgentKeyFromTty(prompt = "Agent Key de Avileo: ") {
|
|
16416
|
+
if (!process.stdin.isTTY || !process.stderr.isTTY) {
|
|
16417
|
+
throw new CliProtocolError(
|
|
16418
|
+
"CLI_CONFIGURATION_ERROR",
|
|
16419
|
+
"auth configure requiere una terminal interactiva; usa AVILEO_AGENT_API_KEY en CI/CD"
|
|
16420
|
+
);
|
|
16421
|
+
}
|
|
16422
|
+
return new Promise((resolve, reject) => {
|
|
16423
|
+
let value = "";
|
|
16424
|
+
const input = process.stdin;
|
|
16425
|
+
const output = process.stderr;
|
|
16426
|
+
const wasRaw = input.isRaw;
|
|
16427
|
+
const cleanup = () => {
|
|
16428
|
+
input.removeListener("data", onData);
|
|
16429
|
+
input.pause();
|
|
16430
|
+
if (wasRaw !== void 0) input.setRawMode(Boolean(wasRaw));
|
|
16431
|
+
};
|
|
16432
|
+
const finish = (result) => {
|
|
16433
|
+
cleanup();
|
|
16434
|
+
output.write("\n");
|
|
16435
|
+
if (result instanceof Error) reject(result);
|
|
16436
|
+
else resolve(result);
|
|
16437
|
+
};
|
|
16438
|
+
const onData = (chunk) => {
|
|
16439
|
+
for (const character of String(chunk)) {
|
|
16440
|
+
if (character === "") {
|
|
16441
|
+
finish(
|
|
16442
|
+
new CliProtocolError(
|
|
16443
|
+
"CLI_CONFIGURATION_ERROR",
|
|
16444
|
+
"Configuraci\xF3n cancelada por el usuario"
|
|
16445
|
+
)
|
|
16446
|
+
);
|
|
16447
|
+
return;
|
|
16448
|
+
}
|
|
16449
|
+
if (character === "\r" || character === "\n") {
|
|
16450
|
+
finish(value);
|
|
16451
|
+
return;
|
|
16452
|
+
}
|
|
16453
|
+
if (character === "\x7F" || character === "\b") {
|
|
16454
|
+
value = value.slice(0, -1);
|
|
16455
|
+
continue;
|
|
16456
|
+
}
|
|
16457
|
+
value += character;
|
|
16458
|
+
}
|
|
16459
|
+
};
|
|
16460
|
+
output.write(prompt);
|
|
16461
|
+
input.setRawMode(true);
|
|
16462
|
+
input.resume();
|
|
16463
|
+
input.on("data", onData);
|
|
16464
|
+
});
|
|
16465
|
+
}
|
|
16215
16466
|
async function openWithExecutable(command, args) {
|
|
16216
16467
|
return new Promise((resolve) => {
|
|
16217
16468
|
const child = spawn(command, args, { stdio: "ignore", shell: false, detached: true });
|
|
@@ -16239,9 +16490,15 @@ async function openVerificationUri(uri) {
|
|
|
16239
16490
|
}
|
|
16240
16491
|
return false;
|
|
16241
16492
|
}
|
|
16493
|
+
function resolveSelectedBaseUrl(options) {
|
|
16494
|
+
const explicit = options.baseUrl?.trim();
|
|
16495
|
+
if (explicit) return normalizeApiBaseUrl(explicit);
|
|
16496
|
+
const fromEnvironment = options.env.AVILEO_AGENT_BASE_URL?.trim();
|
|
16497
|
+
return fromEnvironment ? normalizeApiBaseUrl(fromEnvironment) : AVILEO_AGENT_API_URL;
|
|
16498
|
+
}
|
|
16242
16499
|
async function login(options) {
|
|
16243
|
-
const baseUrl = options
|
|
16244
|
-
const deviceAuth = options.deviceAuthFactory(
|
|
16500
|
+
const baseUrl = resolveSelectedBaseUrl(options);
|
|
16501
|
+
const deviceAuth = options.deviceAuthFactory({ baseUrl });
|
|
16245
16502
|
const start = await deviceAuth.start({ name: "Avileo CLI" });
|
|
16246
16503
|
const browserOpened = await options.openBrowser(start.verificationUri);
|
|
16247
16504
|
process.stderr.write(
|
|
@@ -16258,7 +16515,7 @@ async function login(options) {
|
|
|
16258
16515
|
continue;
|
|
16259
16516
|
}
|
|
16260
16517
|
if (result.status === "denied" || result.status === "expired") {
|
|
16261
|
-
emitSuccess(safeFinalResult(start, browserOpened, result));
|
|
16518
|
+
emitSuccess({ ...safeFinalResult(start, browserOpened, result), baseUrl });
|
|
16262
16519
|
return;
|
|
16263
16520
|
}
|
|
16264
16521
|
if (!result.agentKey || !result.keyId || !result.businessId) {
|
|
@@ -16267,18 +16524,23 @@ async function login(options) {
|
|
|
16267
16524
|
"La autorizaci\xF3n aprobada no devolvi\xF3 una credencial v\xE1lida"
|
|
16268
16525
|
);
|
|
16269
16526
|
}
|
|
16270
|
-
saveLocalCredential(
|
|
16271
|
-
|
|
16272
|
-
apiKey: result.agentKey,
|
|
16273
|
-
...baseUrl ? { baseUrl } : {}
|
|
16274
|
-
},
|
|
16275
|
-
options.env
|
|
16276
|
-
);
|
|
16277
|
-
emitSuccess(safeFinalResult(start, browserOpened, result));
|
|
16527
|
+
saveLocalCredential({ apiKey: result.agentKey, baseUrl }, options.env);
|
|
16528
|
+
emitSuccess({ ...safeFinalResult(start, browserOpened, result), baseUrl });
|
|
16278
16529
|
return;
|
|
16279
16530
|
}
|
|
16280
16531
|
throw new CliProtocolError("CLI_AUTH_TIMEOUT", "La autorizaci\xF3n expir\xF3 antes de ser aprobada");
|
|
16281
16532
|
}
|
|
16533
|
+
async function configure(options) {
|
|
16534
|
+
const baseUrl = resolveSelectedBaseUrl(options);
|
|
16535
|
+
const apiKey = await options.readSecret("Agent Key de Avileo (no se mostrar\xE1): ");
|
|
16536
|
+
saveLocalCredential({ apiKey, baseUrl }, options.env);
|
|
16537
|
+
emitSuccess({
|
|
16538
|
+
configured: true,
|
|
16539
|
+
source: "local",
|
|
16540
|
+
baseUrl,
|
|
16541
|
+
credentialPath: localCredentialPath(options.env)
|
|
16542
|
+
});
|
|
16543
|
+
}
|
|
16282
16544
|
async function status(options) {
|
|
16283
16545
|
const credential = resolveCredential(options.env);
|
|
16284
16546
|
if (!credential) {
|
|
@@ -16290,13 +16552,13 @@ async function status(options) {
|
|
|
16290
16552
|
try {
|
|
16291
16553
|
business = await options.getClient().business.get();
|
|
16292
16554
|
} catch (error51) {
|
|
16293
|
-
const code = error51.code;
|
|
16555
|
+
const code = error51 && typeof error51 === "object" && "code" in error51 ? error51.code : void 0;
|
|
16294
16556
|
businessLookupError = typeof code === "string" ? code : "LOOKUP_FAILED";
|
|
16295
16557
|
}
|
|
16296
16558
|
emitSuccess({
|
|
16297
16559
|
configured: true,
|
|
16298
16560
|
source: credential.source,
|
|
16299
|
-
|
|
16561
|
+
baseUrl: credential.baseUrl ?? AVILEO_AGENT_API_URL,
|
|
16300
16562
|
business,
|
|
16301
16563
|
...businessLookupError ? { businessLookupError } : {}
|
|
16302
16564
|
});
|
|
@@ -16312,7 +16574,15 @@ async function logout(options) {
|
|
|
16312
16574
|
}
|
|
16313
16575
|
function registerAuthCommands(root, options) {
|
|
16314
16576
|
const auth = root.command("auth").description("Conecta la CLI con Avileo sin copiar claves en el chat");
|
|
16315
|
-
auth.command("
|
|
16577
|
+
auth.command("configure").description("Guarda una Agent Key existente sin mostrarla en pantalla").option("--base-url <url>", "Origen de la API donde se usar\xE1 la clave").action(
|
|
16578
|
+
(commandOptions) => configure({ ...options, baseUrl: commandOptions.baseUrl })
|
|
16579
|
+
);
|
|
16580
|
+
auth.command("login").description("Autoriza esta CLI mediante un link temporal").option(
|
|
16581
|
+
"--base-url <url>",
|
|
16582
|
+
"Origen de la API a vincular; tiene prioridad sobre AVILEO_AGENT_BASE_URL"
|
|
16583
|
+
).action(
|
|
16584
|
+
(commandOptions) => login({ ...options, baseUrl: commandOptions.baseUrl })
|
|
16585
|
+
);
|
|
16316
16586
|
auth.command("status").description("Muestra el estado de la credencial sin revelar secretos").action(() => status(options));
|
|
16317
16587
|
auth.command("logout").description("Elimina solamente la credencial local").action(() => logout(options));
|
|
16318
16588
|
}
|
|
@@ -16338,6 +16608,7 @@ function createProgram(options = {}) {
|
|
|
16338
16608
|
env: options.env ?? process.env,
|
|
16339
16609
|
deviceAuthFactory: options.deviceAuthFactory ?? createAvileoAgentDeviceAuth,
|
|
16340
16610
|
openBrowser: options.openBrowser ?? openVerificationUri,
|
|
16611
|
+
readSecret: options.readSecret ?? readAgentKeyFromTty,
|
|
16341
16612
|
getClient,
|
|
16342
16613
|
json: () => Boolean(program.opts().json)
|
|
16343
16614
|
});
|