@native-marketing/sdk 0.3.6 → 0.3.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/http.js +7513 -431
- package/dist/index.js +1289 -67
- package/package.json +11 -1
- package/release.json +3 -3
- package/types/contracts/access/permission.d.ts +3 -0
- package/types/contracts/access/project-access.d.ts +2 -0
- package/types/contracts/agent/human-presentation-validation.d.ts +4 -0
- package/types/contracts/agent/human-presentation.d.ts +300 -0
- package/types/contracts/client-lifecycle.d.ts +55 -0
- package/types/contracts/client-update-policy.d.ts +84 -0
- package/types/contracts/generated/client-release.d.ts +14 -0
- package/types/contracts/index.d.ts +4 -0
- package/types/http/client-version.d.ts +35 -0
- package/types/http/client.d.ts +1 -0
- package/types/http/generated/schema.d.ts +594 -0
- package/types/http/human-presentation.d.ts +247 -0
- package/types/http/index.d.ts +4 -0
- package/types/sdk/capability-definition.d.ts +1 -0
- package/types/sdk/cli/commands.d.ts +1 -1
- package/types/sdk/cli/output.d.ts +8 -0
- package/types/sdk/cli/run.d.ts +1 -0
- package/types/sdk/client.d.ts +12 -0
- package/types/sdk/human-presentation.d.ts +566 -0
- package/types/sdk/index.d.ts +6 -0
- package/types/sdk/transport.d.ts +6 -1
- package/types/sdk/updates/commands.d.ts +11 -0
- package/types/sdk/updates/install.d.ts +20 -0
- package/types/sdk/updates/registry.d.ts +26 -0
- package/types/sdk/updates/store.d.ts +14 -0
- package/types/sdk/updates/version.d.ts +93 -0
package/dist/index.js
CHANGED
|
@@ -2570,6 +2570,7 @@ var permissionSchema = z32.enum([
|
|
|
2570
2570
|
"feedback.manage",
|
|
2571
2571
|
"recommendation.create",
|
|
2572
2572
|
"package.download",
|
|
2573
|
+
"presentation.share",
|
|
2573
2574
|
"source.read",
|
|
2574
2575
|
"source.ingest",
|
|
2575
2576
|
"source.content.read"
|
|
@@ -6934,7 +6935,13 @@ var surveyRejections = [
|
|
|
6934
6935
|
"PERSONAL_SURVEY_DRAFT_TRANSITION_IMMUTABLE"
|
|
6935
6936
|
];
|
|
6936
6937
|
function isKnownCapabilityRejection(code2, name) {
|
|
6937
|
-
return
|
|
6938
|
+
return name === "cf_issue_human_read_link" && [
|
|
6939
|
+
"HUMAN_TARGET_NOT_FOUND",
|
|
6940
|
+
"HUMAN_CONTENT_TOO_LARGE",
|
|
6941
|
+
"HUMAN_LINK_REQUEST_CONFLICT",
|
|
6942
|
+
"HUMAN_LINK_LIMIT",
|
|
6943
|
+
"HUMAN_LINK_SECRET_UNAVAILABLE"
|
|
6944
|
+
].includes(code2) || name === "cf_revoke_human_read_link" && code2 === "HUMAN_LINK_REQUEST_CONFLICT" || name === "cf_cleanup_human_read_links" && code2 === "HUMAN_CLEANUP_INPUT_INVALID" || capabilityRejectedErrorCodes.includes(code2) || name === "cf_repair_knowledge_reference" && [
|
|
6938
6945
|
"KNOWLEDGE_REFERENCE_REPAIR_CONFLICT",
|
|
6939
6946
|
"KNOWLEDGE_REFERENCE_REPAIR_NOT_SUPPORTED",
|
|
6940
6947
|
"KNOWLEDGE_REFERENCE_REPAIR_IDENTITY_MISMATCH",
|
|
@@ -7008,6 +7015,8 @@ function capabilityRecovery(code2, outcome, name) {
|
|
|
7008
7015
|
const change2 = changeCapabilityRecovery(code2, outcome, name);
|
|
7009
7016
|
if (change2) return change2;
|
|
7010
7017
|
if (outcome === "UNKNOWN") {
|
|
7018
|
+
if (name === "cf_issue_human_read_link") return "FIND_ORIGINAL_RECEIPT";
|
|
7019
|
+
if (name === "cf_revoke_human_read_link") return "READ_ORIGINAL_LINK_STATE";
|
|
7011
7020
|
if ([
|
|
7012
7021
|
"cf_material_verification_start",
|
|
7013
7022
|
"cf_material_verification_advance",
|
|
@@ -7305,6 +7314,110 @@ var knowledgeReferenceRepairCommandSchema = knowledgeReferenceRepairQuerySchema.
|
|
|
7305
7314
|
}).strict();
|
|
7306
7315
|
var knowledgeReferenceRepairReceiptQuerySchema = knowledgeAdoptionReceiptQuerySchema;
|
|
7307
7316
|
|
|
7317
|
+
// packages/contracts/src/agent/human-presentation.ts
|
|
7318
|
+
import { z as z103 } from "zod";
|
|
7319
|
+
var reference = z103.string().min(1).max(512);
|
|
7320
|
+
var digest = z103.string().regex(/^[a-f0-9]{64}$/u);
|
|
7321
|
+
var webUrl = z103.string().url().max(4096).refine((value) => {
|
|
7322
|
+
try {
|
|
7323
|
+
const url = new URL(value);
|
|
7324
|
+
return !url.username && !url.password && !url.search && (url.protocol === "https:" || url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname));
|
|
7325
|
+
} catch {
|
|
7326
|
+
return false;
|
|
7327
|
+
}
|
|
7328
|
+
});
|
|
7329
|
+
var packageCode = z103.string().regex(/^PKG-[0-9]{6,}$/u);
|
|
7330
|
+
var humanPresentationCapability = "com.native-marketing/human-presentation";
|
|
7331
|
+
var humanPresentationFeatures = Object.freeze({
|
|
7332
|
+
version: 1,
|
|
7333
|
+
subjects: ["CONTENT_PACKAGE"],
|
|
7334
|
+
interactions: ["CONTENT_PACKAGE_REVIEW"],
|
|
7335
|
+
links: ["AUTHENTICATED", "TEMPORARY_PUBLIC_READ"],
|
|
7336
|
+
publicRead: "SNAPSHOT"
|
|
7337
|
+
});
|
|
7338
|
+
var humanPresentationInputSchema = z103.object({ packageCode }).strict();
|
|
7339
|
+
var common3 = {
|
|
7340
|
+
linkRef: reference,
|
|
7341
|
+
kind: z103.literal("READABLE_CONTENT"),
|
|
7342
|
+
title: z103.string().min(1).max(500),
|
|
7343
|
+
subjectRef: reference,
|
|
7344
|
+
url: webUrl
|
|
7345
|
+
};
|
|
7346
|
+
var humanReadLinkSchema = z103.discriminatedUnion("access", [
|
|
7347
|
+
z103.object({
|
|
7348
|
+
...common3,
|
|
7349
|
+
access: z103.literal("AUTHENTICATED"),
|
|
7350
|
+
representation: z103.literal("CURRENT_VIEW"),
|
|
7351
|
+
expiresAt: z103.null()
|
|
7352
|
+
}).strict(),
|
|
7353
|
+
z103.object({
|
|
7354
|
+
...common3,
|
|
7355
|
+
access: z103.literal("TEMPORARY_PUBLIC_READ"),
|
|
7356
|
+
representation: z103.literal("SNAPSHOT"),
|
|
7357
|
+
snapshotRef: reference,
|
|
7358
|
+
contentSha256: digest,
|
|
7359
|
+
createdAt: z103.string().datetime(),
|
|
7360
|
+
expiresAt: z103.string().datetime()
|
|
7361
|
+
}).strict()
|
|
7362
|
+
]);
|
|
7363
|
+
var humanInteractionSchema = z103.object({
|
|
7364
|
+
interactionRef: reference,
|
|
7365
|
+
kind: z103.literal("CONTENT_PACKAGE_REVIEW"),
|
|
7366
|
+
subjectRef: reference,
|
|
7367
|
+
title: z103.string().min(1).max(500),
|
|
7368
|
+
summary: z103.string().max(2e3),
|
|
7369
|
+
state: z103.enum(["PENDING", "APPROVED", "REJECTED", "RESOLVED"]),
|
|
7370
|
+
sourceState: z103.string().min(1).max(80),
|
|
7371
|
+
actionDigest: digest,
|
|
7372
|
+
expiresAt: z103.null(),
|
|
7373
|
+
reviewUrl: webUrl,
|
|
7374
|
+
canReview: z103.boolean()
|
|
7375
|
+
}).strict();
|
|
7376
|
+
var humanPresentationSchema = z103.object({
|
|
7377
|
+
schemaVersion: z103.literal(1),
|
|
7378
|
+
interactions: z103.array(humanInteractionSchema).max(16),
|
|
7379
|
+
links: z103.array(humanReadLinkSchema).max(16)
|
|
7380
|
+
}).strict();
|
|
7381
|
+
var humanReadableDocumentSchema = z103.object({
|
|
7382
|
+
schemaVersion: z103.literal(1),
|
|
7383
|
+
title: z103.string().min(1).max(500),
|
|
7384
|
+
subjectRef: reference,
|
|
7385
|
+
manifestHash: digest,
|
|
7386
|
+
sections: z103.array(
|
|
7387
|
+
z103.object({ heading: z103.string().min(1).max(500), text: z103.string().max(131072) }).strict()
|
|
7388
|
+
).min(1).max(128)
|
|
7389
|
+
}).strict();
|
|
7390
|
+
var issueHumanReadLinkInputSchema = z103.object({
|
|
7391
|
+
requestId: z103.string().min(1).max(128),
|
|
7392
|
+
packageCode,
|
|
7393
|
+
expectedManifestHash: digest,
|
|
7394
|
+
access: z103.literal("TEMPORARY_PUBLIC_READ"),
|
|
7395
|
+
targetKeys: z103.array(z103.string().min(1).max(64)).min(1).max(32).refine((keys) => new Set(keys).size === keys.length),
|
|
7396
|
+
ttlSeconds: z103.number().int().min(60).max(86400).default(3600)
|
|
7397
|
+
}).strict();
|
|
7398
|
+
var humanReadLinkLookupSchema = z103.object({ linkRef: z103.string().uuid() }).strict();
|
|
7399
|
+
var humanReadLinkReceiptQuerySchema = z103.object({ requestId: z103.string().min(1).max(128) }).strict();
|
|
7400
|
+
var revokeHumanReadLinkInputSchema = humanReadLinkLookupSchema.extend({ requestId: z103.string().min(1).max(128) }).strict();
|
|
7401
|
+
var humanReadLinkResultSchema = z103.object({
|
|
7402
|
+
linkRef: z103.string().uuid(),
|
|
7403
|
+
issuanceRequestId: z103.string().min(1).max(128),
|
|
7404
|
+
state: z103.enum(["ACTIVE", "EXPIRED", "REVOKED", "UNAVAILABLE"]),
|
|
7405
|
+
packageCode,
|
|
7406
|
+
manifestHash: digest,
|
|
7407
|
+
expiresAt: z103.string().datetime(),
|
|
7408
|
+
human: humanPresentationSchema
|
|
7409
|
+
}).strict();
|
|
7410
|
+
var humanReadLinkReceiptSchema = z103.discriminatedUnion("status", [
|
|
7411
|
+
z103.object({ status: z103.literal("FOUND"), receipt: humanReadLinkResultSchema }).strict(),
|
|
7412
|
+
z103.object({ status: z103.literal("NOT_FOUND") }).strict()
|
|
7413
|
+
]);
|
|
7414
|
+
var cleanupHumanReadLinksInputSchema = z103.object({ limit: z103.number().int().min(1).max(32).default(16) }).strict();
|
|
7415
|
+
var cleanupHumanReadLinksResultSchema = z103.object({
|
|
7416
|
+
reclaimed: z103.number().int().nonnegative().max(32),
|
|
7417
|
+
limit: z103.number().int().min(1).max(32)
|
|
7418
|
+
}).strict();
|
|
7419
|
+
var humanPresentationResultSchema = z103.object({ human: humanPresentationSchema }).strict();
|
|
7420
|
+
|
|
7308
7421
|
// packages/contracts/src/agent/capability-receipts.ts
|
|
7309
7422
|
var rule = (capability, schema2, operation, keys = [], field) => ({ capability, schema: schema2, operation, keys, field });
|
|
7310
7423
|
var foundation = (operation, field) => rule(
|
|
@@ -7531,6 +7644,18 @@ var rules = {
|
|
|
7531
7644
|
};
|
|
7532
7645
|
var object = (value) => value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
7533
7646
|
function capabilityReceiptRead(name, input) {
|
|
7647
|
+
if (name === "cf_issue_human_read_link") {
|
|
7648
|
+
const parsed2 = humanReadLinkReceiptQuerySchema.safeParse({
|
|
7649
|
+
requestId: object(input).requestId
|
|
7650
|
+
});
|
|
7651
|
+
if (!parsed2.success) return void 0;
|
|
7652
|
+
return {
|
|
7653
|
+
capability: "cf_get_human_read_link_receipt",
|
|
7654
|
+
arguments: parsed2.data,
|
|
7655
|
+
requiresDescription: true,
|
|
7656
|
+
requiresCurrentAuthorization: true
|
|
7657
|
+
};
|
|
7658
|
+
}
|
|
7534
7659
|
const r = name && Object.hasOwn(rules, name) ? rules[name] : void 0;
|
|
7535
7660
|
if (!r) return void 0;
|
|
7536
7661
|
const raw = object(input), source = r.field ? object(Object.hasOwn(raw, r.field) ? raw[r.field] : void 0) : raw;
|
|
@@ -7553,13 +7678,18 @@ function capabilityReceiptRead(name, input) {
|
|
|
7553
7678
|
}
|
|
7554
7679
|
|
|
7555
7680
|
// packages/contracts/src/agent/capability-status.ts
|
|
7556
|
-
import { z as
|
|
7681
|
+
import { z as z104 } from "zod";
|
|
7557
7682
|
var verification = {
|
|
7558
7683
|
capability: "cf_material_verification_status",
|
|
7559
7684
|
schema: materialVerificationIdSchema,
|
|
7560
7685
|
key: "jobId"
|
|
7561
7686
|
};
|
|
7562
7687
|
var rules2 = {
|
|
7688
|
+
cf_revoke_human_read_link: {
|
|
7689
|
+
capability: "cf_get_human_read_link",
|
|
7690
|
+
schema: humanReadLinkLookupSchema,
|
|
7691
|
+
key: "linkRef"
|
|
7692
|
+
},
|
|
7563
7693
|
cf_material_verification_start: { ...verification, from: "requestId" },
|
|
7564
7694
|
cf_material_verification_advance: verification,
|
|
7565
7695
|
cf_material_verification_retry: verification,
|
|
@@ -7571,7 +7701,7 @@ var rules2 = {
|
|
|
7571
7701
|
},
|
|
7572
7702
|
cf_tenant_material_scan_advance: {
|
|
7573
7703
|
capability: "cf_tenant_material_scan_status",
|
|
7574
|
-
schema:
|
|
7704
|
+
schema: z104.object({}).strict()
|
|
7575
7705
|
},
|
|
7576
7706
|
cf_sync_materials: {
|
|
7577
7707
|
capability: "cf_reconcile_materials",
|
|
@@ -7598,6 +7728,218 @@ function capabilityStatusRead(name, input) {
|
|
|
7598
7728
|
};
|
|
7599
7729
|
}
|
|
7600
7730
|
|
|
7731
|
+
// packages/contracts/src/client-lifecycle.ts
|
|
7732
|
+
import { z as z105 } from "zod";
|
|
7733
|
+
|
|
7734
|
+
// packages/contracts/src/generated/client-release.ts
|
|
7735
|
+
var nativeClientRelease = {
|
|
7736
|
+
schemaVersion: 1,
|
|
7737
|
+
product: "native-marketing",
|
|
7738
|
+
version: "0.3.8",
|
|
7739
|
+
packages: {
|
|
7740
|
+
sdk: "@native-marketing/sdk",
|
|
7741
|
+
cli: "@native-marketing/cli"
|
|
7742
|
+
},
|
|
7743
|
+
contractVersion: 1,
|
|
7744
|
+
minimumClientVersion: "0.3.6",
|
|
7745
|
+
apiMajor: 1,
|
|
7746
|
+
nodeMajor: 24,
|
|
7747
|
+
changes: [
|
|
7748
|
+
"Unified typed human interaction cards and authenticated reading links across SDK, CLI and MCP.",
|
|
7749
|
+
"Explicitly authorized expiring public read-only package text snapshots with original request recovery and revocation.",
|
|
7750
|
+
"Bound human presentation responses to the configured Project, original issuance request and source version."
|
|
7751
|
+
]
|
|
7752
|
+
};
|
|
7753
|
+
|
|
7754
|
+
// packages/contracts/src/client-lifecycle.ts
|
|
7755
|
+
var nativeReleaseCapability = "com.native-marketing/client-release";
|
|
7756
|
+
var releaseVersionSchema = z105.string().max(128).regex(
|
|
7757
|
+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/
|
|
7758
|
+
);
|
|
7759
|
+
var clientIdentitySchema = z105.object({
|
|
7760
|
+
version: releaseVersionSchema,
|
|
7761
|
+
contractVersion: z105.number().int().positive(),
|
|
7762
|
+
apiMajor: z105.number().int().positive()
|
|
7763
|
+
});
|
|
7764
|
+
var clientReleaseSchema = z105.object({
|
|
7765
|
+
schemaVersion: z105.literal(1),
|
|
7766
|
+
product: z105.literal("native-marketing"),
|
|
7767
|
+
version: releaseVersionSchema,
|
|
7768
|
+
packages: z105.object({
|
|
7769
|
+
sdk: z105.literal("@native-marketing/sdk"),
|
|
7770
|
+
cli: z105.literal("@native-marketing/cli")
|
|
7771
|
+
}),
|
|
7772
|
+
contractVersion: z105.number().int().positive(),
|
|
7773
|
+
minimumClientVersion: releaseVersionSchema,
|
|
7774
|
+
apiMajor: z105.number().int().positive(),
|
|
7775
|
+
nodeMajor: z105.number().int().positive(),
|
|
7776
|
+
changes: z105.array(z105.string().min(1).max(240)).max(8).default([])
|
|
7777
|
+
});
|
|
7778
|
+
var updatePolicySchema = z105.object({
|
|
7779
|
+
mode: z105.enum(["off", "notify", "auto"]).default("notify"),
|
|
7780
|
+
channel: z105.enum(["latest", "next", "beta"]).default("latest"),
|
|
7781
|
+
pin: releaseVersionSchema.nullable().default(null),
|
|
7782
|
+
intervalHours: z105.number().int().min(1).max(168).default(24)
|
|
7783
|
+
}).strict();
|
|
7784
|
+
var defaultUpdatePolicy = updatePolicySchema.parse({});
|
|
7785
|
+
function compareReleaseVersions(left, right) {
|
|
7786
|
+
const parse = (raw) => releaseVersionSchema.parse(raw).split("+")[0].split(/-(.*)/s);
|
|
7787
|
+
const a = parse(left), b = parse(right);
|
|
7788
|
+
const numbers = (x, y) => BigInt(x) < BigInt(y) ? -1 : BigInt(x) > BigInt(y) ? 1 : 0;
|
|
7789
|
+
const ac = a[0].split("."), bc = b[0].split(".");
|
|
7790
|
+
for (let i = 0; i < 3; i++) {
|
|
7791
|
+
const order = numbers(ac[i], bc[i]);
|
|
7792
|
+
if (order) return order;
|
|
7793
|
+
}
|
|
7794
|
+
if (a[1] === b[1]) return 0;
|
|
7795
|
+
if (!a[1] || !b[1]) return a[1] ? -1 : 1;
|
|
7796
|
+
const ap = a[1].split("."), bp = b[1].split(".");
|
|
7797
|
+
for (let i = 0; i < Math.max(ap.length, bp.length); i++) {
|
|
7798
|
+
const x = ap[i], y = bp[i];
|
|
7799
|
+
if (x === void 0 || y === void 0) return x === void 0 ? -1 : 1;
|
|
7800
|
+
if (x === y) continue;
|
|
7801
|
+
const xn = /^\d+$/.test(x), yn = /^\d+$/.test(y);
|
|
7802
|
+
return xn && yn ? numbers(x, y) : xn !== yn ? xn ? -1 : 1 : x < y ? -1 : 1;
|
|
7803
|
+
}
|
|
7804
|
+
return 0;
|
|
7805
|
+
}
|
|
7806
|
+
function assessNativeCompatibility(client, server) {
|
|
7807
|
+
client = clientIdentitySchema.parse(client);
|
|
7808
|
+
const result2 = (status, reason) => ({ status, reason, client, server: server ?? null });
|
|
7809
|
+
if (!server) return result2("UNKNOWN", "SERVER_METADATA_UNAVAILABLE");
|
|
7810
|
+
server = clientReleaseSchema.parse(server);
|
|
7811
|
+
if (client.contractVersion !== server.contractVersion)
|
|
7812
|
+
return result2("INCOMPATIBLE", "CONTRACT_MISMATCH");
|
|
7813
|
+
if (client.apiMajor !== server.apiMajor) return result2("INCOMPATIBLE", "API_MISMATCH");
|
|
7814
|
+
if (compareReleaseVersions(client.version, server.minimumClientVersion) < 0)
|
|
7815
|
+
return result2("INCOMPATIBLE", "CLIENT_TOO_OLD");
|
|
7816
|
+
return compareReleaseVersions(client.version, server.version) < 0 ? result2("UPGRADE_RECOMMENDED", "NEWER_CLIENT_AVAILABLE") : result2("COMPATIBLE", "CURRENT");
|
|
7817
|
+
}
|
|
7818
|
+
|
|
7819
|
+
// packages/contracts/src/client-update-policy.ts
|
|
7820
|
+
import { z as z106 } from "zod";
|
|
7821
|
+
var registryReleaseSchema = z106.object({
|
|
7822
|
+
name: z106.enum(["@native-marketing/sdk", "@native-marketing/cli"]),
|
|
7823
|
+
version: releaseVersionSchema,
|
|
7824
|
+
deprecated: z106.string().optional(),
|
|
7825
|
+
nativeMarketing: z106.object({
|
|
7826
|
+
contractVersion: z106.number().int().positive(),
|
|
7827
|
+
apiMajor: z106.number().int().positive(),
|
|
7828
|
+
nodeMajor: z106.number().int().positive(),
|
|
7829
|
+
changes: z106.array(z106.string().min(1).max(240)).max(8).optional()
|
|
7830
|
+
}).optional(),
|
|
7831
|
+
dist: z106.object({
|
|
7832
|
+
integrity: z106.string().max(512).regex(/^sha512-[A-Za-z0-9+/]{86}==$/)
|
|
7833
|
+
})
|
|
7834
|
+
});
|
|
7835
|
+
var clientUpdateStateSchema = z106.object({
|
|
7836
|
+
schemaVersion: z106.literal(1),
|
|
7837
|
+
policy: updatePolicySchema,
|
|
7838
|
+
lastCheck: z106.object({
|
|
7839
|
+
at: z106.number().int().nonnegative(),
|
|
7840
|
+
selector: z106.string().max(160),
|
|
7841
|
+
target: registryReleaseSchema
|
|
7842
|
+
}).strict().optional(),
|
|
7843
|
+
lastAttempt: z106.object({ at: z106.number().int().nonnegative(), selector: z106.string().max(160) }).strict().optional()
|
|
7844
|
+
}).strict();
|
|
7845
|
+
function planNativeUpdate(input) {
|
|
7846
|
+
const target = registryReleaseSchema.parse(input.target);
|
|
7847
|
+
const current = releaseVersionSchema.parse(input.currentVersion ?? nativeClientRelease.version);
|
|
7848
|
+
const policy = updatePolicySchema.parse(input.policy ?? {});
|
|
7849
|
+
const spec = `${target.name}@${target.version}`;
|
|
7850
|
+
const cli = target.name === nativeClientRelease.packages.cli;
|
|
7851
|
+
const result2 = (status, reason, eligible = false) => ({
|
|
7852
|
+
package: target.name,
|
|
7853
|
+
currentVersion: current,
|
|
7854
|
+
targetVersion: target.version,
|
|
7855
|
+
status,
|
|
7856
|
+
reason,
|
|
7857
|
+
eligibleForAutoUpdate: eligible,
|
|
7858
|
+
policy,
|
|
7859
|
+
commands: {
|
|
7860
|
+
npm: [
|
|
7861
|
+
"npm",
|
|
7862
|
+
"install",
|
|
7863
|
+
...cli ? ["--global"] : ["--save-exact"],
|
|
7864
|
+
spec,
|
|
7865
|
+
"--ignore-scripts",
|
|
7866
|
+
"--registry=https://registry.npmjs.org/",
|
|
7867
|
+
"--@native-marketing:registry=https://registry.npmjs.org/"
|
|
7868
|
+
],
|
|
7869
|
+
pnpm: ["pnpm", "add", ...cli ? ["--global"] : ["--save-exact"], spec, "--ignore-scripts"],
|
|
7870
|
+
yarn: cli ? null : ["yarn", "add", "--exact", spec]
|
|
7871
|
+
}
|
|
7872
|
+
});
|
|
7873
|
+
if (policy.pin && policy.pin !== target.version) return result2("BLOCKED", "PIN_MISMATCH");
|
|
7874
|
+
if (!policy.pin && policy.channel === "latest" && target.version.split("+")[0].includes("-"))
|
|
7875
|
+
return result2("BLOCKED", "CHANNEL_MISMATCH");
|
|
7876
|
+
const order = compareReleaseVersions(target.version, current);
|
|
7877
|
+
if (order < 0) return result2("BLOCKED", "DOWNGRADE_FORBIDDEN");
|
|
7878
|
+
if (target.deprecated !== void 0) return result2("BLOCKED", "DEPRECATED");
|
|
7879
|
+
if (!target.nativeMarketing) return result2("BLOCKED", "METADATA_UNAVAILABLE");
|
|
7880
|
+
const metadata = target.nativeMarketing;
|
|
7881
|
+
if (metadata.nodeMajor !== (input.nodeMajor ?? nativeClientRelease.nodeMajor))
|
|
7882
|
+
return result2("BLOCKED", "NODE_MISMATCH");
|
|
7883
|
+
if (metadata.contractVersion !== nativeClientRelease.contractVersion || metadata.apiMajor !== nativeClientRelease.apiMajor)
|
|
7884
|
+
return result2("BLOCKED", "CONTRACT_MISMATCH");
|
|
7885
|
+
if (input.server && assessNativeCompatibility(
|
|
7886
|
+
{
|
|
7887
|
+
version: target.version,
|
|
7888
|
+
contractVersion: metadata.contractVersion,
|
|
7889
|
+
apiMajor: metadata.apiMajor
|
|
7890
|
+
},
|
|
7891
|
+
input.server
|
|
7892
|
+
).status === "INCOMPATIBLE")
|
|
7893
|
+
return result2("BLOCKED", "SERVER_INCOMPATIBLE");
|
|
7894
|
+
if (order === 0) return result2("CURRENT", "CURRENT");
|
|
7895
|
+
const from = current.split(/[.+-]/), to = target.version.split(/[.+-]/);
|
|
7896
|
+
const compatibleLine = from[0] === to[0] && (from[0] !== "0" || from[1] === to[1]);
|
|
7897
|
+
const stable = !current.split("+")[0].includes("-") && !target.version.split("+")[0].includes("-");
|
|
7898
|
+
return compatibleLine && stable ? result2("UPDATE_AVAILABLE", "COMPATIBLE_UPDATE", true) : result2("UPDATE_AVAILABLE", "REVIEW_REQUIRED");
|
|
7899
|
+
}
|
|
7900
|
+
|
|
7901
|
+
// packages/contracts/src/agent/human-presentation-validation.ts
|
|
7902
|
+
function validateHumanPresentationResource(human, resource, packageCode2) {
|
|
7903
|
+
try {
|
|
7904
|
+
const base2 = new URL(resource);
|
|
7905
|
+
const project = /^\/mcp\/projects\/(PRJ-[0-9]{6,})$/u.exec(base2.pathname)?.[1];
|
|
7906
|
+
if (!project || base2.username || base2.password || base2.search || base2.hash) return false;
|
|
7907
|
+
const review = (raw) => {
|
|
7908
|
+
const url = new URL(raw);
|
|
7909
|
+
return url.origin === base2.origin && !url.username && !url.password && !url.search && !url.hash && (packageCode2 ? url.pathname === `/projects/${project}/packages/${packageCode2}` : new RegExp(`^/projects/${project}/packages/PKG-[0-9]{6,}$`, "u").test(url.pathname));
|
|
7910
|
+
};
|
|
7911
|
+
return human.interactions.every((item) => review(item.reviewUrl)) && human.links.every((link) => {
|
|
7912
|
+
if (link.access === "AUTHENTICATED") return review(link.url);
|
|
7913
|
+
const url = new URL(link.url);
|
|
7914
|
+
return url.origin === base2.origin && !url.username && !url.password && !url.search && url.pathname === `/api/v1/human-read/${link.linkRef}` && /^#[A-Za-z0-9_-]{43}$/u.test(url.hash) && link.snapshotRef === `sha256:${link.contentSha256}` && Date.parse(link.expiresAt) > Date.parse(link.createdAt);
|
|
7915
|
+
});
|
|
7916
|
+
} catch {
|
|
7917
|
+
return false;
|
|
7918
|
+
}
|
|
7919
|
+
}
|
|
7920
|
+
function validateHumanPresentationResponse(parsed, resource, input, operation) {
|
|
7921
|
+
const value = parsed.status === "FOUND" ? parsed.receipt : parsed;
|
|
7922
|
+
if (!("human" in value)) return true;
|
|
7923
|
+
const human = value.human;
|
|
7924
|
+
if (!validateHumanPresentationResource(
|
|
7925
|
+
human,
|
|
7926
|
+
resource,
|
|
7927
|
+
typeof value.packageCode === "string" ? value.packageCode : input.packageCode
|
|
7928
|
+
))
|
|
7929
|
+
return false;
|
|
7930
|
+
if (input.packageCode && value.packageCode && value.packageCode !== input.packageCode)
|
|
7931
|
+
return false;
|
|
7932
|
+
if (input.expectedManifestHash && value.manifestHash !== input.expectedManifestHash) return false;
|
|
7933
|
+
if (input.linkRef && value.linkRef !== input.linkRef) return false;
|
|
7934
|
+
if (input.requestId && operation !== "cf_revoke_human_read_link" && value.issuanceRequestId !== input.requestId)
|
|
7935
|
+
return false;
|
|
7936
|
+
const links = human.links;
|
|
7937
|
+
if (value.state === "ACTIVE" && (links.length !== 1 || links[0]?.access !== "TEMPORARY_PUBLIC_READ" || links[0].linkRef !== value.linkRef || links[0].expiresAt !== value.expiresAt))
|
|
7938
|
+
return false;
|
|
7939
|
+
if (value.state && value.state !== "ACTIVE" && links.length) return false;
|
|
7940
|
+
return true;
|
|
7941
|
+
}
|
|
7942
|
+
|
|
7601
7943
|
// packages/cli-client/src/errors.ts
|
|
7602
7944
|
var CliError = class extends Error {
|
|
7603
7945
|
constructor(code2, message, outcome = "NOT_SENT", details) {
|
|
@@ -7650,6 +7992,9 @@ function verifyCapabilityDefinition(raw, name, expectedHash) {
|
|
|
7650
7992
|
}
|
|
7651
7993
|
var CapabilityDefinitionCache = class {
|
|
7652
7994
|
values = /* @__PURE__ */ new Map();
|
|
7995
|
+
clear() {
|
|
7996
|
+
this.values.clear();
|
|
7997
|
+
}
|
|
7653
7998
|
remember(value) {
|
|
7654
7999
|
const verified = verifyCapabilityDefinition(value, value.definition.name);
|
|
7655
8000
|
const key2 = `${verified.definition.name}:AGENT_V3:${verified.schemaSha256}`;
|
|
@@ -7988,13 +8333,106 @@ function object2(value) {
|
|
|
7988
8333
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
7989
8334
|
}
|
|
7990
8335
|
|
|
8336
|
+
// packages/cli-client/src/updates/version.ts
|
|
8337
|
+
import { readFile, realpath } from "node:fs/promises";
|
|
8338
|
+
import { dirname, join as join2 } from "node:path";
|
|
8339
|
+
function getNativeClientVersion() {
|
|
8340
|
+
return clientReleaseSchema.parse(nativeClientRelease);
|
|
8341
|
+
}
|
|
8342
|
+
async function getNativeCliVersion(executablePath) {
|
|
8343
|
+
const identity = { ...getNativeClientVersion(), sdkVersion: nativeClientRelease.version };
|
|
8344
|
+
if (!executablePath) return identity;
|
|
8345
|
+
try {
|
|
8346
|
+
const root = dirname(dirname(await realpath(executablePath)));
|
|
8347
|
+
const manifest = JSON.parse(await readFile(join2(root, "package.json"), "utf8"));
|
|
8348
|
+
if (manifest.name === nativeClientRelease.packages.cli)
|
|
8349
|
+
return { ...identity, version: releaseVersionSchema.parse(manifest.version) };
|
|
8350
|
+
} catch {
|
|
8351
|
+
}
|
|
8352
|
+
return identity;
|
|
8353
|
+
}
|
|
8354
|
+
function readNativeServerVersion(client) {
|
|
8355
|
+
const raw = client.getServerCapabilities()?.experimental?.[nativeReleaseCapability];
|
|
8356
|
+
let server;
|
|
8357
|
+
if (raw !== void 0) {
|
|
8358
|
+
const parsed = clientReleaseSchema.safeParse(raw);
|
|
8359
|
+
if (!parsed.success)
|
|
8360
|
+
throw new CliError(
|
|
8361
|
+
"INVALID_SERVER_RELEASE",
|
|
8362
|
+
"The advertised Native Marketing release contract is invalid."
|
|
8363
|
+
);
|
|
8364
|
+
server = parsed.data;
|
|
8365
|
+
}
|
|
8366
|
+
return {
|
|
8367
|
+
client: getNativeClientVersion(),
|
|
8368
|
+
serverInfo: client.getServerVersion() ?? null,
|
|
8369
|
+
mcpProtocolVersion: client.getNegotiatedProtocolVersion() ?? null,
|
|
8370
|
+
compatibility: assessNativeCompatibility(nativeClientRelease, server)
|
|
8371
|
+
};
|
|
8372
|
+
}
|
|
8373
|
+
function assertNativeCompatibility(result2, required = false) {
|
|
8374
|
+
if (result2.compatibility.status === "INCOMPATIBLE" || required && result2.compatibility.status === "UNKNOWN")
|
|
8375
|
+
throw new CliError(
|
|
8376
|
+
"CLIENT_INCOMPATIBLE",
|
|
8377
|
+
"Check version --server and update the client or connect to a compatible service. No business operation was sent.",
|
|
8378
|
+
"NOT_SENT",
|
|
8379
|
+
{ compatibility: result2.compatibility }
|
|
8380
|
+
);
|
|
8381
|
+
}
|
|
8382
|
+
async function refreshNativeServerVersion(client, timeout) {
|
|
8383
|
+
const reply = await client.callTool(
|
|
8384
|
+
{ name: "cf_get_client_release", arguments: {} },
|
|
8385
|
+
{
|
|
8386
|
+
timeout,
|
|
8387
|
+
allowInputRequired: true,
|
|
8388
|
+
toolDefinition: {
|
|
8389
|
+
name: "cf_get_client_release",
|
|
8390
|
+
inputSchema: { type: "object", properties: {}, additionalProperties: false },
|
|
8391
|
+
annotations: { readOnlyHint: true }
|
|
8392
|
+
}
|
|
8393
|
+
}
|
|
8394
|
+
).catch(() => {
|
|
8395
|
+
throw new CliError(
|
|
8396
|
+
"VERSION_CHECK_UNAVAILABLE",
|
|
8397
|
+
"Cannot refresh the service release. Reconnect or refresh again before continuing."
|
|
8398
|
+
);
|
|
8399
|
+
});
|
|
8400
|
+
const text3 = reply.content?.find((item) => item.type === "text");
|
|
8401
|
+
let server;
|
|
8402
|
+
try {
|
|
8403
|
+
if (reply.isError) throw new Error();
|
|
8404
|
+
server = clientReleaseSchema.parse(
|
|
8405
|
+
reply.structuredContent ?? (text3?.type === "text" ? JSON.parse(text3.text) : null)
|
|
8406
|
+
);
|
|
8407
|
+
} catch {
|
|
8408
|
+
throw new CliError("INVALID_SERVER_RELEASE", "Cannot verify the current server release.");
|
|
8409
|
+
}
|
|
8410
|
+
const result2 = {
|
|
8411
|
+
...readNativeServerVersion(client),
|
|
8412
|
+
compatibility: assessNativeCompatibility(nativeClientRelease, server)
|
|
8413
|
+
};
|
|
8414
|
+
return result2;
|
|
8415
|
+
}
|
|
8416
|
+
|
|
7991
8417
|
// packages/cli-client/src/transport.ts
|
|
7992
|
-
|
|
8418
|
+
var resources = /* @__PURE__ */ new WeakMap();
|
|
8419
|
+
async function withClient(profile, timeout, operation, options = {}) {
|
|
7993
8420
|
const resource = resourceUrl(profile.resource);
|
|
7994
8421
|
const accessToken = tokenText(profile.accessToken);
|
|
7995
8422
|
const client = new Client(
|
|
7996
|
-
{ name: "
|
|
7997
|
-
{
|
|
8423
|
+
{ name: "@native-marketing/sdk", version: nativeClientRelease.version },
|
|
8424
|
+
{
|
|
8425
|
+
inputRequired: { autoFulfill: false },
|
|
8426
|
+
capabilities: {
|
|
8427
|
+
experimental: {
|
|
8428
|
+
[nativeReleaseCapability]: {
|
|
8429
|
+
version: nativeClientRelease.version,
|
|
8430
|
+
contractVersion: nativeClientRelease.contractVersion,
|
|
8431
|
+
apiMajor: nativeClientRelease.apiMajor
|
|
8432
|
+
}
|
|
8433
|
+
}
|
|
8434
|
+
}
|
|
8435
|
+
}
|
|
7998
8436
|
);
|
|
7999
8437
|
const transport = new StreamableHTTPClientTransport(resource, {
|
|
8000
8438
|
authProvider: { token: async () => accessToken },
|
|
@@ -8006,6 +8444,7 @@ async function withClient(profile, timeout, operation) {
|
|
|
8006
8444
|
reconnectionDelayGrowFactor: 1
|
|
8007
8445
|
}
|
|
8008
8446
|
});
|
|
8447
|
+
resources.set(client, resource.href);
|
|
8009
8448
|
try {
|
|
8010
8449
|
try {
|
|
8011
8450
|
await client.connect(transport, { timeout });
|
|
@@ -8015,8 +8454,13 @@ async function withClient(profile, timeout, operation) {
|
|
|
8015
8454
|
"Cannot authenticate/connect to the configured CF resource. No business operation was sent."
|
|
8016
8455
|
);
|
|
8017
8456
|
}
|
|
8457
|
+
const version = readNativeServerVersion(client);
|
|
8458
|
+
if (!options.allowIncompatible)
|
|
8459
|
+
assertNativeCompatibility(version, options.requireCompatibility);
|
|
8460
|
+
options.onVersion?.(version);
|
|
8018
8461
|
return await operation(client);
|
|
8019
8462
|
} finally {
|
|
8463
|
+
resources.delete(client);
|
|
8020
8464
|
await client.close().catch(() => void 0);
|
|
8021
8465
|
}
|
|
8022
8466
|
}
|
|
@@ -8024,13 +8468,14 @@ async function callTool(client, tool5, input, timeout, readOnly, errorToolName =
|
|
|
8024
8468
|
if (["cf_call_capability", "cf_read_capability", "cf_write_capability"].includes(tool5.name) && errorToolName === tool5.name && typeof input.name === "string" && /^cf_[a-z0-9_]{1,100}$/.test(input.name))
|
|
8025
8469
|
errorToolName = input.name;
|
|
8026
8470
|
const original = ["cf_call_capability", "cf_read_capability", "cf_write_capability"].includes(tool5.name) && input.name === errorToolName ? input.arguments : input;
|
|
8027
|
-
const unknown = (code2, message) => {
|
|
8471
|
+
const unknown = (code2, message, human) => {
|
|
8028
8472
|
const receipt = capabilityReceiptRead(errorToolName, original);
|
|
8029
8473
|
const status = capabilityStatusRead(errorToolName, original);
|
|
8030
8474
|
return new CliError(code2, message, "UNKNOWN", {
|
|
8031
8475
|
recovery: capabilityRecovery(code2, "UNKNOWN", errorToolName),
|
|
8032
8476
|
...receipt ? { receipt } : {},
|
|
8033
|
-
...status ? { status } : {}
|
|
8477
|
+
...status ? { status } : {},
|
|
8478
|
+
...human ? { human } : {}
|
|
8034
8479
|
});
|
|
8035
8480
|
};
|
|
8036
8481
|
let result2;
|
|
@@ -8052,16 +8497,21 @@ async function callTool(client, tool5, input, timeout, readOnly, errorToolName =
|
|
|
8052
8497
|
);
|
|
8053
8498
|
}
|
|
8054
8499
|
if ("resultType" in result2 && result2.resultType === "input_required") {
|
|
8500
|
+
const raw = result2._meta?.[humanPresentationCapability];
|
|
8501
|
+
const parsed = raw && Buffer.byteLength(JSON.stringify(raw)) <= 128 * 1024 ? humanPresentationSchema.safeParse(raw) : null;
|
|
8502
|
+
const resource = resources.get(client);
|
|
8503
|
+
const human = parsed?.success && resource && validateHumanPresentationResource(parsed.data, resource) ? parsed.data : void 0;
|
|
8055
8504
|
if (!readOnly)
|
|
8056
8505
|
throw unknown(
|
|
8057
8506
|
"INPUT_REQUIRED",
|
|
8058
|
-
"Resolve additional input explicitly after confirming the original outcome. No automatic fulfilment or retry was made."
|
|
8507
|
+
"Resolve additional input explicitly after confirming the original outcome. No automatic fulfilment or retry was made.",
|
|
8508
|
+
human
|
|
8059
8509
|
);
|
|
8060
8510
|
throw new CliError(
|
|
8061
8511
|
"INPUT_REQUIRED",
|
|
8062
8512
|
"Resolve additional input explicitly; no automatic fulfilment or retry was made.",
|
|
8063
8513
|
"REJECTED",
|
|
8064
|
-
{ recovery: "RESOLVE_INPUT_EXPLICITLY" }
|
|
8514
|
+
{ recovery: "RESOLVE_INPUT_EXPLICITLY", ...human ? { human } : {} }
|
|
8065
8515
|
);
|
|
8066
8516
|
}
|
|
8067
8517
|
if (result2.isError) {
|
|
@@ -8825,6 +9275,185 @@ async function uploadNativeMaterial(connection, file, timeout = 3e4) {
|
|
|
8825
9275
|
return materialUploadCommandResultSchema.parse(await uploadFile(connection, file, timeout));
|
|
8826
9276
|
}
|
|
8827
9277
|
|
|
9278
|
+
// packages/cli-client/src/human-presentation.ts
|
|
9279
|
+
var humanCommands = {
|
|
9280
|
+
"human show": {
|
|
9281
|
+
name: "cf_get_human_presentation",
|
|
9282
|
+
input: humanPresentationInputSchema,
|
|
9283
|
+
output: humanPresentationResultSchema,
|
|
9284
|
+
readOnly: true
|
|
9285
|
+
},
|
|
9286
|
+
"human issue-link": {
|
|
9287
|
+
name: "cf_issue_human_read_link",
|
|
9288
|
+
input: issueHumanReadLinkInputSchema,
|
|
9289
|
+
output: humanReadLinkResultSchema,
|
|
9290
|
+
readOnly: false
|
|
9291
|
+
},
|
|
9292
|
+
"human link": {
|
|
9293
|
+
name: "cf_get_human_read_link",
|
|
9294
|
+
input: humanReadLinkLookupSchema,
|
|
9295
|
+
output: humanReadLinkResultSchema,
|
|
9296
|
+
readOnly: true
|
|
9297
|
+
},
|
|
9298
|
+
"human receipt": {
|
|
9299
|
+
name: "cf_get_human_read_link_receipt",
|
|
9300
|
+
input: humanReadLinkReceiptQuerySchema,
|
|
9301
|
+
output: humanReadLinkReceiptSchema,
|
|
9302
|
+
readOnly: true
|
|
9303
|
+
},
|
|
9304
|
+
"human revoke-link": {
|
|
9305
|
+
name: "cf_revoke_human_read_link",
|
|
9306
|
+
input: revokeHumanReadLinkInputSchema,
|
|
9307
|
+
output: humanReadLinkResultSchema,
|
|
9308
|
+
readOnly: false
|
|
9309
|
+
},
|
|
9310
|
+
"human cleanup-links": {
|
|
9311
|
+
name: "cf_cleanup_human_read_links",
|
|
9312
|
+
input: cleanupHumanReadLinksInputSchema,
|
|
9313
|
+
output: cleanupHumanReadLinksResultSchema,
|
|
9314
|
+
readOnly: false
|
|
9315
|
+
}
|
|
9316
|
+
};
|
|
9317
|
+
function invalid6() {
|
|
9318
|
+
return new CliError(
|
|
9319
|
+
"INVALID_HUMAN_PRESENTATION",
|
|
9320
|
+
"The human presentation cannot be verified against this exact product resource."
|
|
9321
|
+
);
|
|
9322
|
+
}
|
|
9323
|
+
async function invoke2(client, resource, raw, name, inputSchema, outputSchema, readOnly, timeout) {
|
|
9324
|
+
const request = inputSchema.safeParse(raw);
|
|
9325
|
+
if (!request.success)
|
|
9326
|
+
throw new CliError("INVALID_HUMAN_INPUT", "Use the exact human presentation input schema.");
|
|
9327
|
+
const capability = client.getServerCapabilities()?.experimental?.[humanPresentationCapability];
|
|
9328
|
+
if (capability?.version !== 1)
|
|
9329
|
+
throw new CliError(
|
|
9330
|
+
"HUMAN_PRESENTATION_UNSUPPORTED",
|
|
9331
|
+
"This service has not declared human presentation version 1."
|
|
9332
|
+
);
|
|
9333
|
+
const tool5 = {
|
|
9334
|
+
name,
|
|
9335
|
+
inputSchema: {
|
|
9336
|
+
type: "object",
|
|
9337
|
+
...inputSchema["~standard"].jsonSchema.input({ target: "draft-2020-12" })
|
|
9338
|
+
},
|
|
9339
|
+
annotations: { readOnlyHint: readOnly }
|
|
9340
|
+
};
|
|
9341
|
+
const result2 = await callTool(client, tool5, request.data, timeout, readOnly);
|
|
9342
|
+
try {
|
|
9343
|
+
const parsed = outputSchema.parse(result2);
|
|
9344
|
+
if (Buffer.byteLength(JSON.stringify(parsed)) > 128 * 1024) throw invalid6();
|
|
9345
|
+
if (!validateHumanPresentationResponse(
|
|
9346
|
+
parsed,
|
|
9347
|
+
resource,
|
|
9348
|
+
request.data,
|
|
9349
|
+
name
|
|
9350
|
+
))
|
|
9351
|
+
throw invalid6();
|
|
9352
|
+
return parsed;
|
|
9353
|
+
} catch {
|
|
9354
|
+
const outcome = readOnly ? "REJECTED" : "UNKNOWN";
|
|
9355
|
+
const receipt = capabilityReceiptRead(name, request.data);
|
|
9356
|
+
const status = capabilityStatusRead(name, request.data);
|
|
9357
|
+
throw new CliError(
|
|
9358
|
+
"INVALID_HUMAN_PRESENTATION",
|
|
9359
|
+
"Cannot verify this exact response. Query the original request before another write.",
|
|
9360
|
+
outcome,
|
|
9361
|
+
{
|
|
9362
|
+
recovery: capabilityRecovery("INVALID_HUMAN_PRESENTATION", outcome, name),
|
|
9363
|
+
...!readOnly && receipt ? { receipt } : {},
|
|
9364
|
+
...!readOnly && status ? { status } : {},
|
|
9365
|
+
...request.data.requestId ? { requestId: request.data.requestId } : {},
|
|
9366
|
+
...request.data.linkRef ? { linkRef: request.data.linkRef } : {}
|
|
9367
|
+
}
|
|
9368
|
+
);
|
|
9369
|
+
}
|
|
9370
|
+
}
|
|
9371
|
+
function getNativeHumanPresentation(client, resource, input, timeout = 3e4) {
|
|
9372
|
+
return invoke2(
|
|
9373
|
+
client,
|
|
9374
|
+
resource,
|
|
9375
|
+
input,
|
|
9376
|
+
"cf_get_human_presentation",
|
|
9377
|
+
humanPresentationInputSchema,
|
|
9378
|
+
humanPresentationResultSchema,
|
|
9379
|
+
true,
|
|
9380
|
+
timeout
|
|
9381
|
+
);
|
|
9382
|
+
}
|
|
9383
|
+
function issueNativeHumanReadLink(client, resource, input, timeout = 3e4) {
|
|
9384
|
+
return invoke2(
|
|
9385
|
+
client,
|
|
9386
|
+
resource,
|
|
9387
|
+
input,
|
|
9388
|
+
"cf_issue_human_read_link",
|
|
9389
|
+
issueHumanReadLinkInputSchema,
|
|
9390
|
+
humanReadLinkResultSchema,
|
|
9391
|
+
false,
|
|
9392
|
+
timeout
|
|
9393
|
+
);
|
|
9394
|
+
}
|
|
9395
|
+
function getNativeHumanReadLink(client, resource, input, timeout = 3e4) {
|
|
9396
|
+
return invoke2(
|
|
9397
|
+
client,
|
|
9398
|
+
resource,
|
|
9399
|
+
input,
|
|
9400
|
+
"cf_get_human_read_link",
|
|
9401
|
+
humanReadLinkLookupSchema,
|
|
9402
|
+
humanReadLinkResultSchema,
|
|
9403
|
+
true,
|
|
9404
|
+
timeout
|
|
9405
|
+
);
|
|
9406
|
+
}
|
|
9407
|
+
function getNativeHumanReadLinkReceipt(client, resource, input, timeout = 3e4) {
|
|
9408
|
+
return invoke2(
|
|
9409
|
+
client,
|
|
9410
|
+
resource,
|
|
9411
|
+
input,
|
|
9412
|
+
"cf_get_human_read_link_receipt",
|
|
9413
|
+
humanReadLinkReceiptQuerySchema,
|
|
9414
|
+
humanReadLinkReceiptSchema,
|
|
9415
|
+
true,
|
|
9416
|
+
timeout
|
|
9417
|
+
);
|
|
9418
|
+
}
|
|
9419
|
+
function revokeNativeHumanReadLink(client, resource, input, timeout = 3e4) {
|
|
9420
|
+
return invoke2(
|
|
9421
|
+
client,
|
|
9422
|
+
resource,
|
|
9423
|
+
input,
|
|
9424
|
+
"cf_revoke_human_read_link",
|
|
9425
|
+
revokeHumanReadLinkInputSchema,
|
|
9426
|
+
humanReadLinkResultSchema,
|
|
9427
|
+
false,
|
|
9428
|
+
timeout
|
|
9429
|
+
);
|
|
9430
|
+
}
|
|
9431
|
+
function cleanupNativeHumanReadLinks(client, resource, input = {}, timeout = 3e4) {
|
|
9432
|
+
return invoke2(
|
|
9433
|
+
client,
|
|
9434
|
+
resource,
|
|
9435
|
+
input,
|
|
9436
|
+
"cf_cleanup_human_read_links",
|
|
9437
|
+
cleanupHumanReadLinksInputSchema,
|
|
9438
|
+
cleanupHumanReadLinksResultSchema,
|
|
9439
|
+
false,
|
|
9440
|
+
timeout
|
|
9441
|
+
);
|
|
9442
|
+
}
|
|
9443
|
+
async function runHumanCommand(client, resource, name, input, timeout) {
|
|
9444
|
+
const spec = humanCommands[name];
|
|
9445
|
+
return invoke2(
|
|
9446
|
+
client,
|
|
9447
|
+
resource,
|
|
9448
|
+
input,
|
|
9449
|
+
spec.name,
|
|
9450
|
+
spec.input,
|
|
9451
|
+
spec.output,
|
|
9452
|
+
spec.readOnly,
|
|
9453
|
+
timeout
|
|
9454
|
+
);
|
|
9455
|
+
}
|
|
9456
|
+
|
|
8828
9457
|
// packages/cli-client/src/business-search.ts
|
|
8829
9458
|
var tool4 = (name, schema2) => ({
|
|
8830
9459
|
name,
|
|
@@ -8839,17 +9468,17 @@ var document = tool4("cf_read_business_document", businessDocumentInputSchema);
|
|
|
8839
9468
|
async function searchNativeBusiness(client, raw = {}, timeout = 3e4) {
|
|
8840
9469
|
checkTimeout3(timeout);
|
|
8841
9470
|
const input = businessSearchQuerySchema.safeParse(raw);
|
|
8842
|
-
if (!input.success) throw
|
|
9471
|
+
if (!input.success) throw invalid7("INVALID_BUSINESS_SEARCH_QUERY", "NOT_SENT");
|
|
8843
9472
|
const value = await callTool(client, search, input.data, timeout, true);
|
|
8844
9473
|
const parsed = businessSearchPageSchema.safeParse(value);
|
|
8845
9474
|
if (!parsed.success || Buffer.byteLength(JSON.stringify(value)) > 16 * 1024)
|
|
8846
|
-
throw
|
|
9475
|
+
throw invalid7("INVALID_BUSINESS_SEARCH_REPLY");
|
|
8847
9476
|
return parsed.data;
|
|
8848
9477
|
}
|
|
8849
9478
|
async function readNativeBusinessPage(client, raw, timeout = 3e4) {
|
|
8850
9479
|
checkTimeout3(timeout);
|
|
8851
9480
|
const input = businessContentPageReadSchema.safeParse(raw);
|
|
8852
|
-
if (!input.success) throw
|
|
9481
|
+
if (!input.success) throw invalid7("INVALID_BUSINESS_CONTENT_QUERY", "NOT_SENT");
|
|
8853
9482
|
const { offset, expectedDocumentHash, ...sourceInput } = input.data;
|
|
8854
9483
|
const args = businessDocumentInputSchema.parse({
|
|
8855
9484
|
sourceTool: "cf_read_business_content",
|
|
@@ -8860,18 +9489,18 @@ async function readNativeBusinessPage(client, raw, timeout = 3e4) {
|
|
|
8860
9489
|
const value = await callTool(client, document, args, timeout, true);
|
|
8861
9490
|
const parsed = businessContentPageSchema.safeParse(value);
|
|
8862
9491
|
if (!parsed.success || Buffer.byteLength(JSON.stringify(value)) > 6e3)
|
|
8863
|
-
throw
|
|
9492
|
+
throw invalid7("INVALID_BUSINESS_CONTENT_REPLY");
|
|
8864
9493
|
const p = parsed.data;
|
|
8865
9494
|
if (p.sourceInput.ref !== sourceInput.ref || p.sourceInput.expectedVersion !== sourceInput.expectedVersion || p.offset !== offset || expectedDocumentHash && p.documentHash !== expectedDocumentHash || (p.hasMore ? p.nextOffset !== offset + [...p.text].length : p.nextOffset !== null) || p.hasMore !== offset + [...p.text].length < p.totalCharacters)
|
|
8866
|
-
throw
|
|
9495
|
+
throw invalid7("INVALID_BUSINESS_CONTENT_REPLY");
|
|
8867
9496
|
return p;
|
|
8868
9497
|
}
|
|
8869
|
-
function
|
|
9498
|
+
function invalid7(code2, outcome = "REJECTED") {
|
|
8870
9499
|
return new CliError(code2, "Use the exact bounded search or content-page contract.", outcome);
|
|
8871
9500
|
}
|
|
8872
9501
|
function checkTimeout3(value) {
|
|
8873
9502
|
if (!Number.isInteger(value) || value < 100 || value > 12e4)
|
|
8874
|
-
throw
|
|
9503
|
+
throw invalid7("INVALID_TIMEOUT", "NOT_SENT");
|
|
8875
9504
|
}
|
|
8876
9505
|
|
|
8877
9506
|
// packages/cli-client/src/client.ts
|
|
@@ -8882,43 +9511,103 @@ async function withNativeAgentClient(connection, action, options = {}) {
|
|
|
8882
9511
|
return withClient(
|
|
8883
9512
|
connection,
|
|
8884
9513
|
timeout,
|
|
8885
|
-
(client) =>
|
|
8886
|
-
|
|
8887
|
-
|
|
8888
|
-
|
|
8889
|
-
|
|
8890
|
-
|
|
8891
|
-
|
|
8892
|
-
|
|
8893
|
-
|
|
8894
|
-
|
|
8895
|
-
|
|
8896
|
-
|
|
8897
|
-
|
|
8898
|
-
|
|
8899
|
-
|
|
8900
|
-
|
|
8901
|
-
|
|
8902
|
-
|
|
8903
|
-
|
|
8904
|
-
|
|
8905
|
-
|
|
8906
|
-
|
|
8907
|
-
|
|
8908
|
-
|
|
8909
|
-
|
|
8910
|
-
|
|
8911
|
-
|
|
8912
|
-
|
|
8913
|
-
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
|
|
8920
|
-
|
|
8921
|
-
|
|
9514
|
+
(client) => {
|
|
9515
|
+
let version = readNativeServerVersion(client);
|
|
9516
|
+
let versionUnverified = false;
|
|
9517
|
+
client.setNotificationHandler("notifications/tools/list_changed", () => {
|
|
9518
|
+
definitions.clear();
|
|
9519
|
+
});
|
|
9520
|
+
return action(
|
|
9521
|
+
new Proxy(
|
|
9522
|
+
{
|
|
9523
|
+
getHumanPresentation: (input) => getNativeHumanPresentation(client, connection.resource, input, timeout),
|
|
9524
|
+
issueHumanReadLink: (input) => issueNativeHumanReadLink(client, connection.resource, input, timeout),
|
|
9525
|
+
getHumanReadLink: (input) => getNativeHumanReadLink(client, connection.resource, input, timeout),
|
|
9526
|
+
getHumanReadLinkReceipt: (input) => getNativeHumanReadLinkReceipt(client, connection.resource, input, timeout),
|
|
9527
|
+
revokeHumanReadLink: (input) => revokeNativeHumanReadLink(client, connection.resource, input, timeout),
|
|
9528
|
+
cleanupHumanReadLinks: (input = {}) => cleanupNativeHumanReadLinks(client, connection.resource, input, timeout),
|
|
9529
|
+
getVersion: () => structuredClone(version),
|
|
9530
|
+
refreshVersion: async () => {
|
|
9531
|
+
definitions.clear();
|
|
9532
|
+
try {
|
|
9533
|
+
version = await refreshNativeServerVersion(client, timeout);
|
|
9534
|
+
versionUnverified = false;
|
|
9535
|
+
} catch (error) {
|
|
9536
|
+
version = { ...version, compatibility: assessNativeCompatibility(version.client) };
|
|
9537
|
+
versionUnverified = true;
|
|
9538
|
+
throw error;
|
|
9539
|
+
}
|
|
9540
|
+
assertNativeCompatibility(version, options.requireCompatibility);
|
|
9541
|
+
options.onVersion?.(version);
|
|
9542
|
+
return structuredClone(version);
|
|
9543
|
+
},
|
|
9544
|
+
readPackageFile: (input) => readNativePackageFile(connection, input, timeout),
|
|
9545
|
+
readProjectMediaFile: (input) => readNativeProjectMediaFile(connection, input, timeout),
|
|
9546
|
+
uploadProjectMedia: (file) => uploadNativeProjectMedia(connection, file, timeout),
|
|
9547
|
+
uploadMaterial: (file) => uploadNativeMaterial(connection, file, timeout),
|
|
9548
|
+
inspectTool: (name) => inspectNativeTool(client, name, timeout, definitions),
|
|
9549
|
+
callTool: (name, input = {}, options2) => callNativeTool(
|
|
9550
|
+
client,
|
|
9551
|
+
name,
|
|
9552
|
+
input,
|
|
9553
|
+
connection.resource,
|
|
9554
|
+
options2,
|
|
9555
|
+
timeout,
|
|
9556
|
+
definitions
|
|
9557
|
+
),
|
|
9558
|
+
listToolsPage: (input = {}) => listNativeToolsPage(client, input, timeout),
|
|
9559
|
+
readCapabilitySchemaPage: (input) => readNativeCapabilitySchemaPage(client, input, timeout),
|
|
9560
|
+
readDocumentPage: (input) => readNativeDocumentPage(client, input, timeout),
|
|
9561
|
+
getBusinessSummary: (input) => getNativeBusinessSummary(client, input, timeout),
|
|
9562
|
+
callCapability: (input) => callNativeCapability(client, input, timeout),
|
|
9563
|
+
readCapability: (input) => readNativeCapability(client, input, timeout),
|
|
9564
|
+
writeCapability: (input) => writeNativeCapability(client, input, timeout),
|
|
9565
|
+
describeCapabilitySummary: (name) => readNativeCapabilityDescriptor(client, name, timeout),
|
|
9566
|
+
searchBusiness: (input) => searchNativeBusiness(client, input, timeout),
|
|
9567
|
+
readBusinessPage: (input) => readNativeBusinessPage(client, input, timeout),
|
|
9568
|
+
findCapabilities: (input) => findNativeCapabilities(client, input, timeout),
|
|
9569
|
+
discoverCapabilities: async (input) => {
|
|
9570
|
+
const page2 = await findAgentCapabilities(client, input, timeout);
|
|
9571
|
+
for (const item of page2.items)
|
|
9572
|
+
if (item.definition) definitions.remember(item.definition);
|
|
9573
|
+
return page2;
|
|
9574
|
+
},
|
|
9575
|
+
describeCapability: async (name, expectedHash) => {
|
|
9576
|
+
const cached = expectedHash ? definitions.get(name, expectedHash) : void 0;
|
|
9577
|
+
if (cached) return cached;
|
|
9578
|
+
const definition = await describeNativeCapability(client, name, timeout);
|
|
9579
|
+
if (expectedHash && definition.schemaSha256 !== expectedHash)
|
|
9580
|
+
throw new CliError(
|
|
9581
|
+
"CAPABILITY_SCHEMA_CHANGED",
|
|
9582
|
+
"Discover the current definition again.",
|
|
9583
|
+
"REJECTED"
|
|
9584
|
+
);
|
|
9585
|
+
definitions.remember(definition);
|
|
9586
|
+
return definition;
|
|
9587
|
+
}
|
|
9588
|
+
},
|
|
9589
|
+
{
|
|
9590
|
+
get(target, name, receiver) {
|
|
9591
|
+
const method = Reflect.get(target, name, receiver);
|
|
9592
|
+
if (typeof method !== "function" || name === "getVersion" || name === "refreshVersion")
|
|
9593
|
+
return method;
|
|
9594
|
+
return async (...args) => {
|
|
9595
|
+
if (versionUnverified)
|
|
9596
|
+
throw new CliError(
|
|
9597
|
+
"CLIENT_VERSION_UNVERIFIED",
|
|
9598
|
+
"Verify the service release again or reconnect before continuing. No business operation was sent.",
|
|
9599
|
+
"NOT_SENT",
|
|
9600
|
+
{ compatibility: version.compatibility }
|
|
9601
|
+
);
|
|
9602
|
+
assertNativeCompatibility(version, options.requireCompatibility);
|
|
9603
|
+
return Reflect.apply(method, target, args);
|
|
9604
|
+
};
|
|
9605
|
+
}
|
|
9606
|
+
}
|
|
9607
|
+
)
|
|
9608
|
+
);
|
|
9609
|
+
},
|
|
9610
|
+
options
|
|
8922
9611
|
);
|
|
8923
9612
|
}
|
|
8924
9613
|
function checkTimeout4(timeout) {
|
|
@@ -9073,9 +9762,22 @@ var values = /* @__PURE__ */ new Set([
|
|
|
9073
9762
|
"scope",
|
|
9074
9763
|
"job",
|
|
9075
9764
|
"view",
|
|
9076
|
-
"schema-hash"
|
|
9765
|
+
"schema-hash",
|
|
9766
|
+
"mode",
|
|
9767
|
+
"channel",
|
|
9768
|
+
"pin",
|
|
9769
|
+
"interval-hours"
|
|
9770
|
+
]);
|
|
9771
|
+
var flags = /* @__PURE__ */ new Set([
|
|
9772
|
+
"json",
|
|
9773
|
+
"stdin",
|
|
9774
|
+
"help",
|
|
9775
|
+
"version",
|
|
9776
|
+
"server",
|
|
9777
|
+
"strict",
|
|
9778
|
+
"allow-breaking",
|
|
9779
|
+
"dry-run"
|
|
9077
9780
|
]);
|
|
9078
|
-
var flags = /* @__PURE__ */ new Set(["json", "stdin", "help"]);
|
|
9079
9781
|
function parseArgs(args) {
|
|
9080
9782
|
const options = {};
|
|
9081
9783
|
const words = [];
|
|
@@ -9154,8 +9856,8 @@ async function login(store, rawResource, scope2, timeout, notify) {
|
|
|
9154
9856
|
const state = randomBytes(32).toString("base64url");
|
|
9155
9857
|
let resolveCode;
|
|
9156
9858
|
let rejectCode;
|
|
9157
|
-
const codePromise = new Promise((
|
|
9158
|
-
resolveCode =
|
|
9859
|
+
const codePromise = new Promise((resolve2, reject) => {
|
|
9860
|
+
resolveCode = resolve2;
|
|
9159
9861
|
rejectCode = reject;
|
|
9160
9862
|
});
|
|
9161
9863
|
void codePromise.catch(() => void 0);
|
|
@@ -9186,9 +9888,9 @@ async function login(store, rawResource, scope2, timeout, notify) {
|
|
|
9186
9888
|
});
|
|
9187
9889
|
let timer;
|
|
9188
9890
|
try {
|
|
9189
|
-
await new Promise((
|
|
9891
|
+
await new Promise((resolve2, reject) => {
|
|
9190
9892
|
server.once("error", reject);
|
|
9191
|
-
server.listen(0, "127.0.0.1",
|
|
9893
|
+
server.listen(0, "127.0.0.1", resolve2);
|
|
9192
9894
|
});
|
|
9193
9895
|
const address = server.address();
|
|
9194
9896
|
if (!address || typeof address === "string")
|
|
@@ -9258,7 +9960,7 @@ Waiting up to 5 minutes. For remote/headless Agents, use auth import with a prov
|
|
|
9258
9960
|
} finally {
|
|
9259
9961
|
if (timer) clearTimeout(timer);
|
|
9260
9962
|
server.closeAllConnections();
|
|
9261
|
-
await new Promise((
|
|
9963
|
+
await new Promise((resolve2) => server.close(() => resolve2()));
|
|
9262
9964
|
}
|
|
9263
9965
|
});
|
|
9264
9966
|
}
|
|
@@ -9333,6 +10035,10 @@ var fullHelp = {
|
|
|
9333
10035
|
executable: "cf-agent",
|
|
9334
10036
|
transport: "OAuth-authenticated HTTPS MCP; no local database",
|
|
9335
10037
|
commands: [
|
|
10038
|
+
"version [--server [--strict] [--profile <name>]]",
|
|
10039
|
+
"update check [--channel latest|next|beta] [--pin <exact-version>|none]",
|
|
10040
|
+
"update apply [--dry-run] [--allow-breaking] [--channel latest|next|beta] [--pin <exact-version>|none]",
|
|
10041
|
+
"update policy [--mode off|notify|auto] [--channel latest|next|beta] [--pin <exact-version>|none] [--interval-hours <1..168>]",
|
|
9336
10042
|
"auth login --resource <url> [--scope <scopes>] [--profile <name>]",
|
|
9337
10043
|
"auth import --resource <url> --token-file <private-file> [--profile <name>]",
|
|
9338
10044
|
"auth status|refresh|logout [--profile <name>]",
|
|
@@ -9355,6 +10061,7 @@ var fullHelp = {
|
|
|
9355
10061
|
"tools inspect <cf_tool>",
|
|
9356
10062
|
"tools call <cf_tool> [--input-file <file>|--stdin]",
|
|
9357
10063
|
...Object.keys(commandTools).map((name) => `${name} [--input-file <file>|--stdin]`),
|
|
10064
|
+
...Object.keys(humanCommands).map((name) => `${name} [--input-file <file>|--stdin]`),
|
|
9358
10065
|
"task read <kind> --job JOB-000001",
|
|
9359
10066
|
"result submit <kind> (--input-file <file>|--stdin)"
|
|
9360
10067
|
],
|
|
@@ -9376,6 +10083,8 @@ var help = {
|
|
|
9376
10083
|
executable: "cf-agent",
|
|
9377
10084
|
transport: "OAuth-authenticated MCP; no local database",
|
|
9378
10085
|
commands: [
|
|
10086
|
+
"version [--server [--strict]]",
|
|
10087
|
+
"update check|apply|policy (help update for channels, pins and automatic updates)",
|
|
9379
10088
|
"auth login --resource <url> [--scope <scopes>]",
|
|
9380
10089
|
"search [<text>] [--input-file <query.json>|--stdin]",
|
|
9381
10090
|
"business read (--input-file <ref-and-page.json>|--stdin)",
|
|
@@ -9412,6 +10121,13 @@ function groupHelp(group) {
|
|
|
9412
10121
|
function resolveBaseCommand(parsed) {
|
|
9413
10122
|
const { words, options } = parsed;
|
|
9414
10123
|
const name = words.join(" ");
|
|
10124
|
+
if (Object.hasOwn(humanCommands, name)) {
|
|
10125
|
+
if (Object.keys(options).some(
|
|
10126
|
+
(key2) => !["input-file", "stdin", "profile", "json", "timeout-ms"].includes(key2)
|
|
10127
|
+
))
|
|
10128
|
+
throw new CliError("INVALID_OPTION", "Unsupported human presentation option.");
|
|
10129
|
+
return { mode: "human" };
|
|
10130
|
+
}
|
|
9415
10131
|
if (name === "media file" || name === "packages file") {
|
|
9416
10132
|
if (Object.keys(options).some(
|
|
9417
10133
|
(k) => !["output-file", "profile", "input-file", "stdin", "timeout-ms", "json"].includes(k)
|
|
@@ -9520,6 +10236,21 @@ function resolveBaseCommand(parsed) {
|
|
|
9520
10236
|
throw new CliError("INVALID_COMMAND", "Run help for supported commands.");
|
|
9521
10237
|
}
|
|
9522
10238
|
function resolveCommand(parsed) {
|
|
10239
|
+
if ([
|
|
10240
|
+
"mode",
|
|
10241
|
+
"channel",
|
|
10242
|
+
"pin",
|
|
10243
|
+
"interval-hours",
|
|
10244
|
+
"version",
|
|
10245
|
+
"server",
|
|
10246
|
+
"strict",
|
|
10247
|
+
"allow-breaking",
|
|
10248
|
+
"dry-run"
|
|
10249
|
+
].some((key2) => parsed.options[key2]))
|
|
10250
|
+
throw new CliError(
|
|
10251
|
+
"INVALID_OPTION",
|
|
10252
|
+
"Version/update options apply only to version/update commands."
|
|
10253
|
+
);
|
|
9523
10254
|
const removed = {
|
|
9524
10255
|
doctor: "context",
|
|
9525
10256
|
"knowledge sync-all": "knowledge discover",
|
|
@@ -9550,6 +10281,14 @@ function resolveCommand(parsed) {
|
|
|
9550
10281
|
async function businessCommand(client, parsed, input, resource) {
|
|
9551
10282
|
const resolved = resolveCommand(parsed);
|
|
9552
10283
|
const { timeout, options } = parsed;
|
|
10284
|
+
if (resolved.mode === "human")
|
|
10285
|
+
return runHumanCommand(
|
|
10286
|
+
client,
|
|
10287
|
+
resource,
|
|
10288
|
+
parsed.words.join(" "),
|
|
10289
|
+
input,
|
|
10290
|
+
timeout
|
|
10291
|
+
);
|
|
9553
10292
|
if (resolved.mode === "document")
|
|
9554
10293
|
return readNativeDocumentPage(
|
|
9555
10294
|
client,
|
|
@@ -9617,6 +10356,8 @@ async function businessCommand(client, parsed, input, resource) {
|
|
|
9617
10356
|
// packages/cli-client/src/cli/command-input.ts
|
|
9618
10357
|
function validateCommandInput(parsed, input) {
|
|
9619
10358
|
const mode = resolveCommand(parsed).mode;
|
|
10359
|
+
if (mode === "human" && !humanCommands[parsed.words.join(" ")].input.safeParse(input).success)
|
|
10360
|
+
throw new CliError("INVALID_HUMAN_INPUT", "Use the exact human presentation JSON input.");
|
|
9620
10361
|
if (mode === "upload" && parsed.words.join(" ") === "media upload" && !projectMediaWebUploadSchema.omit({ requestId: true }).safeParse(input).success)
|
|
9621
10362
|
throw new CliError("INVALID_UPLOAD_INPUT", "Supply explicit real-media provenance JSON.");
|
|
9622
10363
|
const schemas = {
|
|
@@ -9654,14 +10395,430 @@ function validateCommandInput(parsed, input) {
|
|
|
9654
10395
|
throw new CliError("INVALID_PAGINATION", "Supply only an optional nonempty cursor.");
|
|
9655
10396
|
}
|
|
9656
10397
|
|
|
10398
|
+
// packages/cli-client/src/updates/registry.ts
|
|
10399
|
+
async function checkNativeUpdates(options = {}) {
|
|
10400
|
+
const policy = updatePolicySchema.parse(options.policy ?? {});
|
|
10401
|
+
const current = releaseVersionSchema.safeParse(
|
|
10402
|
+
options.currentVersion ?? nativeClientRelease.version
|
|
10403
|
+
);
|
|
10404
|
+
if (!current.success)
|
|
10405
|
+
throw new CliError(
|
|
10406
|
+
"INVALID_UPDATE_VERSION",
|
|
10407
|
+
"The installed version must be an exact semantic version."
|
|
10408
|
+
);
|
|
10409
|
+
const timeout = options.timeoutMs ?? 5e3;
|
|
10410
|
+
if (!Number.isInteger(timeout) || timeout < 100 || timeout > 12e4)
|
|
10411
|
+
throw new CliError("INVALID_TIMEOUT", "Timeout must be 100\u2013120000 milliseconds.");
|
|
10412
|
+
const name = nativeClientRelease.packages[options.package ?? "sdk"];
|
|
10413
|
+
if (!name) throw new CliError("INVALID_UPDATE_PACKAGE", "Choose sdk or cli.");
|
|
10414
|
+
const selector = policy.pin ?? policy.channel;
|
|
10415
|
+
const url = `https://registry.npmjs.org/${encodeURIComponent(name)}/${encodeURIComponent(selector)}`;
|
|
10416
|
+
let target;
|
|
10417
|
+
try {
|
|
10418
|
+
const response = await (options.fetch ?? fetch)(url, {
|
|
10419
|
+
redirect: "error",
|
|
10420
|
+
credentials: "omit",
|
|
10421
|
+
signal: AbortSignal.timeout(timeout),
|
|
10422
|
+
headers: { accept: "application/json" }
|
|
10423
|
+
});
|
|
10424
|
+
if (!response.ok || !response.body) throw new Error();
|
|
10425
|
+
const reader = response.body.getReader();
|
|
10426
|
+
const chunks = [];
|
|
10427
|
+
let size = 0;
|
|
10428
|
+
try {
|
|
10429
|
+
for (; ; ) {
|
|
10430
|
+
const { done, value } = await reader.read();
|
|
10431
|
+
if (done) break;
|
|
10432
|
+
size += value.byteLength;
|
|
10433
|
+
if (size > 128 * 1024) throw new Error();
|
|
10434
|
+
chunks.push(value);
|
|
10435
|
+
}
|
|
10436
|
+
} finally {
|
|
10437
|
+
await reader.cancel().catch(() => void 0);
|
|
10438
|
+
reader.releaseLock();
|
|
10439
|
+
}
|
|
10440
|
+
target = registryReleaseSchema.parse(JSON.parse(Buffer.concat(chunks).toString("utf8")));
|
|
10441
|
+
if (target.name !== name || policy.pin && target.version !== policy.pin) throw new Error();
|
|
10442
|
+
} catch {
|
|
10443
|
+
throw new CliError(
|
|
10444
|
+
"UPDATE_CHECK_UNAVAILABLE",
|
|
10445
|
+
"Cannot verify release metadata from the public npm registry. Existing software and credentials are unchanged."
|
|
10446
|
+
);
|
|
10447
|
+
}
|
|
10448
|
+
return {
|
|
10449
|
+
checkedAt: Date.now(),
|
|
10450
|
+
target,
|
|
10451
|
+
plan: planNativeUpdate({
|
|
10452
|
+
target,
|
|
10453
|
+
policy,
|
|
10454
|
+
nodeMajor: Number(process.versions.node.split(".")[0]),
|
|
10455
|
+
currentVersion: current.data,
|
|
10456
|
+
...options.server ? { server: options.server } : {}
|
|
10457
|
+
})
|
|
10458
|
+
};
|
|
10459
|
+
}
|
|
10460
|
+
|
|
10461
|
+
// packages/cli-client/src/updates/store.ts
|
|
10462
|
+
import { lstat as lstat2, open as open6, rename as rename2, unlink as unlink2 } from "node:fs/promises";
|
|
10463
|
+
import { join as join3 } from "node:path";
|
|
10464
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
10465
|
+
var UpdateStore = class {
|
|
10466
|
+
files;
|
|
10467
|
+
constructor(env) {
|
|
10468
|
+
const base2 = new ProfileStore(env).directory;
|
|
10469
|
+
this.files = new ProfileStore({ CF_AGENT_CONFIG_DIR: join3(base2, "client-lifecycle") }, "state");
|
|
10470
|
+
}
|
|
10471
|
+
async read() {
|
|
10472
|
+
try {
|
|
10473
|
+
await lstat2(this.files.path);
|
|
10474
|
+
} catch (error) {
|
|
10475
|
+
if (error.code === "ENOENT")
|
|
10476
|
+
return { schemaVersion: 1, policy: updatePolicySchema.parse({}) };
|
|
10477
|
+
throw error;
|
|
10478
|
+
}
|
|
10479
|
+
let raw;
|
|
10480
|
+
try {
|
|
10481
|
+
raw = JSON.parse(await readFileBounded(this.files.path, true));
|
|
10482
|
+
} catch {
|
|
10483
|
+
throw new CliError(
|
|
10484
|
+
"INVALID_UPDATE_CONFIGURATION",
|
|
10485
|
+
"Update state is unreadable. Inspect the client-lifecycle configuration."
|
|
10486
|
+
);
|
|
10487
|
+
}
|
|
10488
|
+
const parsed = clientUpdateStateSchema.safeParse(raw);
|
|
10489
|
+
if (!parsed.success)
|
|
10490
|
+
throw new CliError(
|
|
10491
|
+
"INVALID_UPDATE_CONFIGURATION",
|
|
10492
|
+
"Update state is invalid. Inspect the client-lifecycle configuration."
|
|
10493
|
+
);
|
|
10494
|
+
return parsed.data;
|
|
10495
|
+
}
|
|
10496
|
+
locked(action) {
|
|
10497
|
+
return this.files.locked(action);
|
|
10498
|
+
}
|
|
10499
|
+
async change(action) {
|
|
10500
|
+
return this.locked(async () => {
|
|
10501
|
+
const state = clientUpdateStateSchema.parse(action(await this.read()));
|
|
10502
|
+
const temporary = `${this.files.path}.${randomUUID3()}.tmp`;
|
|
10503
|
+
const file = await open6(temporary, "wx", 384);
|
|
10504
|
+
try {
|
|
10505
|
+
try {
|
|
10506
|
+
await file.writeFile(JSON.stringify(state) + "\n");
|
|
10507
|
+
await file.sync();
|
|
10508
|
+
} finally {
|
|
10509
|
+
await file.close();
|
|
10510
|
+
}
|
|
10511
|
+
await rename2(temporary, this.files.path);
|
|
10512
|
+
} finally {
|
|
10513
|
+
await unlink2(temporary).catch(() => void 0);
|
|
10514
|
+
}
|
|
10515
|
+
return state;
|
|
10516
|
+
});
|
|
10517
|
+
}
|
|
10518
|
+
};
|
|
10519
|
+
function effectiveUpdatePolicy(policy, env) {
|
|
10520
|
+
const parsed = updatePolicySchema.safeParse({
|
|
10521
|
+
...policy,
|
|
10522
|
+
...env.CF_AGENT_UPDATE_MODE ? { mode: env.CF_AGENT_UPDATE_MODE } : {},
|
|
10523
|
+
...env.CF_AGENT_UPDATE_CHANNEL ? { channel: env.CF_AGENT_UPDATE_CHANNEL } : {},
|
|
10524
|
+
...env.CF_AGENT_UPDATE_PIN ? { pin: env.CF_AGENT_UPDATE_PIN === "none" ? null : env.CF_AGENT_UPDATE_PIN } : {}
|
|
10525
|
+
});
|
|
10526
|
+
if (!parsed.success)
|
|
10527
|
+
throw new CliError("INVALID_UPDATE_CONFIGURATION", "Invalid update environment policy.");
|
|
10528
|
+
return parsed.data;
|
|
10529
|
+
}
|
|
10530
|
+
|
|
10531
|
+
// packages/cli-client/src/updates/install.ts
|
|
10532
|
+
import { execFile } from "node:child_process";
|
|
10533
|
+
import { promisify } from "node:util";
|
|
10534
|
+
import { readFile as readFile2, realpath as realpath2 } from "node:fs/promises";
|
|
10535
|
+
import { dirname as dirname2, join as join4, resolve } from "node:path";
|
|
10536
|
+
var execute = promisify(execFile);
|
|
10537
|
+
async function installCliUpdate(input) {
|
|
10538
|
+
const plan = planNativeUpdate({
|
|
10539
|
+
target: input.target,
|
|
10540
|
+
...input.currentVersion ? { currentVersion: input.currentVersion } : {},
|
|
10541
|
+
policy: input.policy,
|
|
10542
|
+
nodeMajor: Number(process.versions.node.split(".")[0])
|
|
10543
|
+
});
|
|
10544
|
+
if (plan.package !== nativeClientRelease.packages.cli || plan.status !== "UPDATE_AVAILABLE" || !plan.eligibleForAutoUpdate && !input.allowBreaking)
|
|
10545
|
+
throw new CliError(
|
|
10546
|
+
"UPDATE_POLICY_BLOCKED",
|
|
10547
|
+
"This release cannot be installed under the selected policy.",
|
|
10548
|
+
"NOT_SENT",
|
|
10549
|
+
{ plan }
|
|
10550
|
+
);
|
|
10551
|
+
if (!input.executablePath || process.platform === "win32")
|
|
10552
|
+
throw new CliError(
|
|
10553
|
+
"MANAGED_UPDATE_UNAVAILABLE",
|
|
10554
|
+
"Use the package manager that owns this installation.",
|
|
10555
|
+
"NOT_SENT",
|
|
10556
|
+
{ plan }
|
|
10557
|
+
);
|
|
10558
|
+
const environment = Object.fromEntries(
|
|
10559
|
+
Object.entries(input.env).filter(
|
|
10560
|
+
([key2, value]) => value !== void 0 && !/^(?:CF_AGENT_|CONTENT_FACTORY_)/i.test(key2)
|
|
10561
|
+
)
|
|
10562
|
+
);
|
|
10563
|
+
environment.CF_AGENT_UPDATE_MODE = "off";
|
|
10564
|
+
environment.NODE_OPTIONS = "--max-old-space-size=384";
|
|
10565
|
+
const options = { env: environment, timeout: input.timeoutMs, maxBuffer: 128 * 1024 };
|
|
10566
|
+
let packageRoot, prefix;
|
|
10567
|
+
try {
|
|
10568
|
+
packageRoot = dirname2(dirname2(await realpath2(input.executablePath)));
|
|
10569
|
+
const manifest = JSON.parse(await readFile2(join4(packageRoot, "package.json"), "utf8"));
|
|
10570
|
+
const root = await realpath2(
|
|
10571
|
+
(await execute("npm", ["root", "--global"], options)).stdout.trim()
|
|
10572
|
+
);
|
|
10573
|
+
prefix = await realpath2((await execute("npm", ["prefix", "--global"], options)).stdout.trim());
|
|
10574
|
+
if (manifest.name !== nativeClientRelease.packages.cli || manifest.version !== plan.currentVersion || packageRoot !== await realpath2(join4(root, "@native-marketing/cli")) || packageRoot !== resolve(prefix, "lib/node_modules/@native-marketing/cli"))
|
|
10575
|
+
throw new Error();
|
|
10576
|
+
} catch {
|
|
10577
|
+
throw new CliError(
|
|
10578
|
+
"MANAGED_UPDATE_UNAVAILABLE",
|
|
10579
|
+
"Automatic installation supports the active npm global installation. Use the owning project/package manager for other installs.",
|
|
10580
|
+
"NOT_SENT",
|
|
10581
|
+
{ plan }
|
|
10582
|
+
);
|
|
10583
|
+
}
|
|
10584
|
+
const args = [
|
|
10585
|
+
"install",
|
|
10586
|
+
"--global",
|
|
10587
|
+
"--prefix",
|
|
10588
|
+
prefix,
|
|
10589
|
+
`${plan.package}@${plan.targetVersion}`,
|
|
10590
|
+
"--registry=https://registry.npmjs.org/",
|
|
10591
|
+
"--@native-marketing:registry=https://registry.npmjs.org/",
|
|
10592
|
+
"--ignore-scripts",
|
|
10593
|
+
"--no-audit",
|
|
10594
|
+
"--no-fund"
|
|
10595
|
+
];
|
|
10596
|
+
const recovery = [
|
|
10597
|
+
"npm",
|
|
10598
|
+
"install",
|
|
10599
|
+
"--global",
|
|
10600
|
+
"--prefix",
|
|
10601
|
+
prefix,
|
|
10602
|
+
`${plan.package}@${plan.currentVersion}`,
|
|
10603
|
+
"--ignore-scripts",
|
|
10604
|
+
"--registry=https://registry.npmjs.org/",
|
|
10605
|
+
"--@native-marketing:registry=https://registry.npmjs.org/"
|
|
10606
|
+
];
|
|
10607
|
+
const store = new UpdateStore(input.env);
|
|
10608
|
+
return store.locked(async () => {
|
|
10609
|
+
if (input.automatic) {
|
|
10610
|
+
const latest = effectiveUpdatePolicy((await store.read()).policy, input.env);
|
|
10611
|
+
if (latest.mode !== "auto" || (latest.pin ?? latest.channel) !== (input.policy.pin ?? input.policy.channel) || !planNativeUpdate({
|
|
10612
|
+
target: input.target,
|
|
10613
|
+
currentVersion: plan.currentVersion,
|
|
10614
|
+
policy: latest,
|
|
10615
|
+
nodeMajor: Number(process.versions.node.split(".")[0])
|
|
10616
|
+
}).eligibleForAutoUpdate)
|
|
10617
|
+
throw new CliError(
|
|
10618
|
+
"UPDATE_POLICY_CHANGED",
|
|
10619
|
+
"Automatic update policy changed. No installation or business operation was sent."
|
|
10620
|
+
);
|
|
10621
|
+
}
|
|
10622
|
+
const before = JSON.parse(await readFile2(join4(packageRoot, "package.json"), "utf8"));
|
|
10623
|
+
if (before.name !== plan.package || before.version !== plan.currentVersion)
|
|
10624
|
+
throw new CliError(
|
|
10625
|
+
"UPDATE_INSTALLATION_CHANGED",
|
|
10626
|
+
"The installed version changed. Check version before updating again."
|
|
10627
|
+
);
|
|
10628
|
+
try {
|
|
10629
|
+
await execute("npm", args, { ...options, cwd: prefix });
|
|
10630
|
+
const installed = JSON.parse(await readFile2(join4(packageRoot, "package.json"), "utf8"));
|
|
10631
|
+
if (installed.name !== plan.package || releaseVersionSchema.parse(installed.version) !== plan.targetVersion)
|
|
10632
|
+
throw new Error();
|
|
10633
|
+
const verified = await execute(
|
|
10634
|
+
process.execPath,
|
|
10635
|
+
[join4(packageRoot, "dist/cf.js"), "version", "--json"],
|
|
10636
|
+
options
|
|
10637
|
+
);
|
|
10638
|
+
const result2 = JSON.parse(verified.stdout);
|
|
10639
|
+
if (!result2.ok || result2.data?.version !== plan.targetVersion || result2.data?.sdkVersion !== plan.targetVersion)
|
|
10640
|
+
throw new Error();
|
|
10641
|
+
return {
|
|
10642
|
+
state: "UPDATED",
|
|
10643
|
+
package: plan.package,
|
|
10644
|
+
previousVersion: plan.currentVersion,
|
|
10645
|
+
installedVersion: plan.targetVersion,
|
|
10646
|
+
restartRequired: true,
|
|
10647
|
+
originalCommandExecuted: false,
|
|
10648
|
+
recovery
|
|
10649
|
+
};
|
|
10650
|
+
} catch {
|
|
10651
|
+
throw new CliError(
|
|
10652
|
+
"UPDATE_OUTCOME_UNKNOWN",
|
|
10653
|
+
"The installation may have changed. Inspect version before another update; use the recovery command if needed. The original business command was not sent.",
|
|
10654
|
+
"UNKNOWN",
|
|
10655
|
+
{ expectedVersion: plan.targetVersion, recovery, originalCommandExecuted: false }
|
|
10656
|
+
);
|
|
10657
|
+
}
|
|
10658
|
+
});
|
|
10659
|
+
}
|
|
10660
|
+
|
|
10661
|
+
// packages/cli-client/src/updates/commands.ts
|
|
10662
|
+
function validateOptions(parsed, names) {
|
|
10663
|
+
if (Object.keys(parsed.options).some((name) => !["json", "timeout-ms", ...names].includes(name)))
|
|
10664
|
+
throw new CliError("INVALID_OPTION", "Unsupported version/update option. Use help update.");
|
|
10665
|
+
}
|
|
10666
|
+
function selectedPolicy(saved, parsed) {
|
|
10667
|
+
const options = parsed.options;
|
|
10668
|
+
const result2 = updatePolicySchema.safeParse({
|
|
10669
|
+
...saved,
|
|
10670
|
+
...options.mode ? { mode: options.mode } : {},
|
|
10671
|
+
...options.channel ? { channel: options.channel } : {},
|
|
10672
|
+
...options.pin ? { pin: options.pin === "none" ? null : options.pin } : {},
|
|
10673
|
+
...options["interval-hours"] ? { intervalHours: Number(options["interval-hours"]) } : {}
|
|
10674
|
+
});
|
|
10675
|
+
if (!result2.success)
|
|
10676
|
+
throw new CliError(
|
|
10677
|
+
"INVALID_UPDATE_POLICY",
|
|
10678
|
+
"Use mode off/notify/auto, channel latest/next/beta, an exact pin or none, and interval-hours 1\u2013168."
|
|
10679
|
+
);
|
|
10680
|
+
return result2.data;
|
|
10681
|
+
}
|
|
10682
|
+
async function runLifecycleCommand(parsed, env, executablePath) {
|
|
10683
|
+
const { words, options, timeout } = parsed;
|
|
10684
|
+
if (options.version || words[0] === "version") {
|
|
10685
|
+
if (options.version && words.length !== 0 || !options.version && words.length !== 1)
|
|
10686
|
+
throw new CliError("INVALID_COMMAND", "Use version or --version.");
|
|
10687
|
+
validateOptions(parsed, ["version", "server", "strict", "profile"]);
|
|
10688
|
+
if (options.strict && !options.server)
|
|
10689
|
+
throw new CliError("INVALID_OPTION", "--strict requires version --server.");
|
|
10690
|
+
if (options.profile && !options.server)
|
|
10691
|
+
throw new CliError("INVALID_OPTION", "--profile requires version --server.");
|
|
10692
|
+
return options.server ? null : { command: "version", data: await getNativeCliVersion(executablePath) };
|
|
10693
|
+
}
|
|
10694
|
+
if (words[0] !== "update") return null;
|
|
10695
|
+
if (words.length !== 2 || !["check", "apply", "policy"].includes(words[1]))
|
|
10696
|
+
throw new CliError("INVALID_COMMAND", "Use update check/apply/policy.");
|
|
10697
|
+
const policyCommand = words[1] === "policy";
|
|
10698
|
+
validateOptions(
|
|
10699
|
+
parsed,
|
|
10700
|
+
policyCommand ? ["mode", "channel", "pin", "interval-hours"] : ["channel", "pin", ...words[1] === "apply" ? ["allow-breaking", "dry-run"] : []]
|
|
10701
|
+
);
|
|
10702
|
+
const store = new UpdateStore(env);
|
|
10703
|
+
const state = await store.read();
|
|
10704
|
+
if (policyCommand) {
|
|
10705
|
+
const changes = Object.keys(options).some(
|
|
10706
|
+
(name) => ["mode", "channel", "pin", "interval-hours"].includes(name)
|
|
10707
|
+
);
|
|
10708
|
+
const saved = changes ? await store.change((current) => ({
|
|
10709
|
+
...current,
|
|
10710
|
+
policy: selectedPolicy(current.policy, parsed)
|
|
10711
|
+
})) : state;
|
|
10712
|
+
return {
|
|
10713
|
+
command: "update policy",
|
|
10714
|
+
data: {
|
|
10715
|
+
saved: saved.policy,
|
|
10716
|
+
effective: effectiveUpdatePolicy(saved.policy, env),
|
|
10717
|
+
lastCheckedAt: saved.lastCheck?.at ?? null
|
|
10718
|
+
}
|
|
10719
|
+
};
|
|
10720
|
+
}
|
|
10721
|
+
const policy = selectedPolicy(effectiveUpdatePolicy(state.policy, env), parsed);
|
|
10722
|
+
const currentVersion = (await getNativeCliVersion(executablePath)).version;
|
|
10723
|
+
const checked = await checkNativeUpdates({
|
|
10724
|
+
package: "cli",
|
|
10725
|
+
currentVersion,
|
|
10726
|
+
policy,
|
|
10727
|
+
timeoutMs: timeout
|
|
10728
|
+
});
|
|
10729
|
+
await store.change((current) => ({
|
|
10730
|
+
...current,
|
|
10731
|
+
lastAttempt: { at: checked.checkedAt, selector: policy.pin ?? policy.channel },
|
|
10732
|
+
lastCheck: {
|
|
10733
|
+
at: checked.checkedAt,
|
|
10734
|
+
selector: policy.pin ?? policy.channel,
|
|
10735
|
+
target: checked.target
|
|
10736
|
+
}
|
|
10737
|
+
}));
|
|
10738
|
+
if (words[1] === "check" || options["dry-run"] || checked.plan.status === "CURRENT")
|
|
10739
|
+
return { command: words.join(" "), data: checked };
|
|
10740
|
+
const data = await installCliUpdate({
|
|
10741
|
+
target: checked.target,
|
|
10742
|
+
currentVersion,
|
|
10743
|
+
policy,
|
|
10744
|
+
timeoutMs: timeout,
|
|
10745
|
+
env,
|
|
10746
|
+
allowBreaking: Boolean(options["allow-breaking"]),
|
|
10747
|
+
...executablePath ? { executablePath } : {}
|
|
10748
|
+
});
|
|
10749
|
+
return { command: "update apply", data };
|
|
10750
|
+
}
|
|
10751
|
+
async function maybeAutoUpdate(env, io, timeout) {
|
|
10752
|
+
if (!io.executablePath || env.CF_AGENT_UPDATE_MODE === "off" || env.CI && !env.CF_AGENT_UPDATE_MODE)
|
|
10753
|
+
return null;
|
|
10754
|
+
const notify = io.notify ?? ((message) => process.stderr.write(message + "\n"));
|
|
10755
|
+
try {
|
|
10756
|
+
const store = new UpdateStore(env);
|
|
10757
|
+
const state = await store.read();
|
|
10758
|
+
const policy = effectiveUpdatePolicy(state.policy, env);
|
|
10759
|
+
if (policy.mode === "off") return null;
|
|
10760
|
+
const now = Date.now(), selector = policy.pin ?? policy.channel;
|
|
10761
|
+
const age = state.lastAttempt ? now - state.lastAttempt.at : Infinity;
|
|
10762
|
+
if (state.lastAttempt?.selector === selector && age >= 0 && age < policy.intervalHours * 36e5)
|
|
10763
|
+
return null;
|
|
10764
|
+
let claimed = false;
|
|
10765
|
+
await store.change((current) => {
|
|
10766
|
+
const age2 = current.lastAttempt ? now - current.lastAttempt.at : Infinity;
|
|
10767
|
+
if (current.lastAttempt?.selector === selector && age2 >= 0 && age2 < policy.intervalHours * 36e5)
|
|
10768
|
+
return current;
|
|
10769
|
+
claimed = true;
|
|
10770
|
+
return { ...current, lastAttempt: { at: now, selector } };
|
|
10771
|
+
});
|
|
10772
|
+
if (!claimed) return null;
|
|
10773
|
+
const currentVersion = (await getNativeCliVersion(io.executablePath)).version;
|
|
10774
|
+
const checked = await checkNativeUpdates({
|
|
10775
|
+
package: "cli",
|
|
10776
|
+
currentVersion,
|
|
10777
|
+
policy,
|
|
10778
|
+
timeoutMs: Math.min(timeout, 2e3)
|
|
10779
|
+
});
|
|
10780
|
+
await store.change((current) => ({
|
|
10781
|
+
...current,
|
|
10782
|
+
lastCheck: { at: checked.checkedAt, selector, target: checked.target }
|
|
10783
|
+
}));
|
|
10784
|
+
if (checked.plan.status === "CURRENT" || checked.plan.reason === "DOWNGRADE_FORBIDDEN" && !policy.pin)
|
|
10785
|
+
return null;
|
|
10786
|
+
if (policy.mode === "auto" && checked.plan.eligibleForAutoUpdate) {
|
|
10787
|
+
const data = await installCliUpdate({
|
|
10788
|
+
target: checked.target,
|
|
10789
|
+
currentVersion,
|
|
10790
|
+
automatic: true,
|
|
10791
|
+
policy,
|
|
10792
|
+
executablePath: io.executablePath,
|
|
10793
|
+
env,
|
|
10794
|
+
timeoutMs: timeout
|
|
10795
|
+
});
|
|
10796
|
+
notify(
|
|
10797
|
+
`Native Marketing updated to ${checked.plan.targetVersion}. Run the original command again.`
|
|
10798
|
+
);
|
|
10799
|
+
return { command: "update auto", data };
|
|
10800
|
+
}
|
|
10801
|
+
notify(
|
|
10802
|
+
`Native Marketing ${nativeClientRelease.version}: update ${checked.plan.targetVersion} (${checked.plan.reason}). Use update check or update apply.`
|
|
10803
|
+
);
|
|
10804
|
+
} catch (error) {
|
|
10805
|
+
if (error instanceof CliError && error.code === "UPDATE_OUTCOME_UNKNOWN") throw error;
|
|
10806
|
+
notify("Native Marketing update check/install is unavailable; use update check for details.");
|
|
10807
|
+
}
|
|
10808
|
+
return null;
|
|
10809
|
+
}
|
|
10810
|
+
|
|
9657
10811
|
// packages/cli-client/src/cli/run.ts
|
|
9658
10812
|
async function runNetworkCli(args, env = process.env, io = {}, executable = "cf") {
|
|
9659
10813
|
let command5 = executable;
|
|
9660
10814
|
try {
|
|
9661
10815
|
const parsed = parseArgs(args);
|
|
9662
10816
|
const { words, options, timeout } = parsed;
|
|
9663
|
-
if (!words.length || words[0] === "help" || options.help)
|
|
10817
|
+
if ((!words.length || words[0] === "help" || options.help) && !options.version)
|
|
9664
10818
|
return success("help", { ...commandHelp(words), executable });
|
|
10819
|
+
const local = await runLifecycleCommand(parsed, env, io.executablePath);
|
|
10820
|
+
if (local) return success(local.command, local.data);
|
|
10821
|
+
const remoteVersion = (words.join(" ") === "version" || options.version && !words.length) && options.server;
|
|
9665
10822
|
const store = new ProfileStore(env, String(options.profile ?? "default"));
|
|
9666
10823
|
if (words[0] === "auth") {
|
|
9667
10824
|
if (words.length !== 2)
|
|
@@ -9733,10 +10890,14 @@ async function runNetworkCli(args, env = process.env, io = {}, executable = "cf"
|
|
|
9733
10890
|
"AUTH_OPTION_MISUSE",
|
|
9734
10891
|
"Resource/token/scope options belong to auth commands. Business commands use the bound profile or CF_AGENT_RESOURCE and CF_AGENT_ACCESS_TOKEN together."
|
|
9735
10892
|
);
|
|
9736
|
-
resolveCommand(parsed);
|
|
9737
|
-
command5 = words[0] === "search" ? "search" : words[0] === "capabilities" ? words.slice(0, 2).join(" ") : words.join(" ");
|
|
10893
|
+
if (!remoteVersion) resolveCommand(parsed);
|
|
10894
|
+
command5 = remoteVersion ? "version" : words[0] === "search" ? "search" : words[0] === "capabilities" ? words.slice(0, 2).join(" ") : words.join(" ");
|
|
10895
|
+
if (!remoteVersion) {
|
|
10896
|
+
const automatic = await maybeAutoUpdate(env, io, timeout);
|
|
10897
|
+
if (automatic) return success(automatic.command, automatic.data);
|
|
10898
|
+
}
|
|
9738
10899
|
const input = options.stdin ? objectJson(await readStream(io.stdin ?? process.stdin)) : typeof options["input-file"] === "string" ? objectJson(await readFileBounded(options["input-file"])) : {};
|
|
9739
|
-
validateCommandInput(parsed, input);
|
|
10900
|
+
if (!remoteVersion) validateCommandInput(parsed, input);
|
|
9740
10901
|
let profile;
|
|
9741
10902
|
if (env.CF_AGENT_ACCESS_TOKEN || env.CF_AGENT_RESOURCE) {
|
|
9742
10903
|
if (options.profile || !env.CF_AGENT_ACCESS_TOKEN || !env.CF_AGENT_RESOURCE)
|
|
@@ -9749,7 +10910,18 @@ async function runNetworkCli(args, env = process.env, io = {}, executable = "cf"
|
|
|
9749
10910
|
accessToken: tokenText(env.CF_AGENT_ACCESS_TOKEN)
|
|
9750
10911
|
};
|
|
9751
10912
|
} else profile = await refreshProfile(store, timeout);
|
|
9752
|
-
const data =
|
|
10913
|
+
const data = remoteVersion ? await withClient(
|
|
10914
|
+
profile,
|
|
10915
|
+
timeout,
|
|
10916
|
+
async (client) => ({
|
|
10917
|
+
...readNativeServerVersion(client),
|
|
10918
|
+
cli: await getNativeCliVersion(io.executablePath)
|
|
10919
|
+
}),
|
|
10920
|
+
{
|
|
10921
|
+
allowIncompatible: !options.strict,
|
|
10922
|
+
requireCompatibility: Boolean(options.strict)
|
|
10923
|
+
}
|
|
10924
|
+
) : resolveCommand(parsed).mode === "package-file" ? await downloadPackageFile(profile, input, String(options["output-file"]), timeout) : resolveCommand(parsed).mode === "media-file" ? await downloadProjectMedia(profile, input, String(options["output-file"]), timeout) : resolveCommand(parsed).mode === "upload" ? await uploadLocalMaterial(
|
|
9753
10925
|
profile,
|
|
9754
10926
|
String(options.file),
|
|
9755
10927
|
String(options["request-id"]),
|
|
@@ -9758,7 +10930,15 @@ async function runNetworkCli(args, env = process.env, io = {}, executable = "cf"
|
|
|
9758
10930
|
) : await withClient(
|
|
9759
10931
|
profile,
|
|
9760
10932
|
timeout,
|
|
9761
|
-
(client) => businessCommand(client, parsed, input, profile.resource)
|
|
10933
|
+
(client) => businessCommand(client, parsed, input, profile.resource),
|
|
10934
|
+
{
|
|
10935
|
+
onVersion: (version) => {
|
|
10936
|
+
if (version.compatibility.status === "UPGRADE_RECOMMENDED")
|
|
10937
|
+
(io.notify ?? ((message) => process.stderr.write(message + "\n")))(
|
|
10938
|
+
`The service recommends Native Marketing ${version.compatibility.server.version}. Use update check.`
|
|
10939
|
+
);
|
|
10940
|
+
}
|
|
10941
|
+
}
|
|
9762
10942
|
);
|
|
9763
10943
|
return success(command5, data);
|
|
9764
10944
|
} catch (error) {
|
|
@@ -9768,16 +10948,57 @@ async function runNetworkCli(args, env = process.env, io = {}, executable = "cf"
|
|
|
9768
10948
|
function success(command5, data) {
|
|
9769
10949
|
return { exitCode: 0, envelope: { ok: true, command: command5, data, error: null } };
|
|
9770
10950
|
}
|
|
10951
|
+
|
|
10952
|
+
// packages/cli-client/src/cli/output.ts
|
|
10953
|
+
function formatNetworkCliResult(result2, json = false) {
|
|
10954
|
+
const { envelope } = result2;
|
|
10955
|
+
if (!json && envelope.ok && envelope.command.startsWith("human ")) {
|
|
10956
|
+
const data = envelope.data;
|
|
10957
|
+
const value = data.status === "FOUND" ? data.receipt : data;
|
|
10958
|
+
const parsed = humanPresentationSchema.safeParse(value.human);
|
|
10959
|
+
if (parsed.success) {
|
|
10960
|
+
const lines = [envelope.command, ...value.state ? [`\u72B6\u6001\uFF1A${value.state}`] : []];
|
|
10961
|
+
for (const card of parsed.data.interactions)
|
|
10962
|
+
lines.push(
|
|
10963
|
+
`${card.title} \xB7 ${card.state}`,
|
|
10964
|
+
card.summary,
|
|
10965
|
+
`\u6B63\u5F0F\u5BA1\u6838\u5165\u53E3\uFF08\u9700\u8981\u767B\u5F55\uFF09\uFF1A${card.reviewUrl}`
|
|
10966
|
+
);
|
|
10967
|
+
for (const link of parsed.data.links)
|
|
10968
|
+
lines.push(
|
|
10969
|
+
`${link.title} \xB7 \u9605\u8BFB`,
|
|
10970
|
+
link.access === "TEMPORARY_PUBLIC_READ" ? `\u4E34\u65F6\u516C\u5F00\u53EA\u8BFB\u5FEB\u7167\uFF1B\u6301\u94FE\u63A5\u8005\u65E0\u9700\u767B\u5F55\u3002\u5230\u671F\uFF1A${link.expiresAt}` : "\u5F53\u524D\u5185\u5BB9\uFF1B\u9700\u8981\u767B\u5F55\u3002",
|
|
10971
|
+
link.url
|
|
10972
|
+
);
|
|
10973
|
+
if (value.issuanceRequestId) lines.push(`\u539F\u7B7E\u53D1\u8BF7\u6C42\uFF1A${value.issuanceRequestId}`);
|
|
10974
|
+
if (!parsed.data.links.length && !parsed.data.interactions.length)
|
|
10975
|
+
lines.push("\u5F53\u524D\u65E0\u53EF\u7528\u9605\u8BFB\u94FE\u63A5\u6216\u4EA4\u4E92\u3002");
|
|
10976
|
+
return lines.join("\n") + "\n";
|
|
10977
|
+
}
|
|
10978
|
+
}
|
|
10979
|
+
return JSON.stringify(envelope, null, json ? void 0 : 2) + "\n";
|
|
10980
|
+
}
|
|
9771
10981
|
export {
|
|
9772
10982
|
CliError as NativeAgentClientError,
|
|
10983
|
+
assessNativeCompatibility,
|
|
9773
10984
|
callNativeCapability,
|
|
9774
10985
|
callNativeTool,
|
|
10986
|
+
checkNativeUpdates,
|
|
10987
|
+
cleanupNativeHumanReadLinks,
|
|
10988
|
+
defaultUpdatePolicy,
|
|
9775
10989
|
describeNativeCapability,
|
|
9776
10990
|
findAgentCapabilities,
|
|
9777
10991
|
findNativeCapabilities,
|
|
10992
|
+
formatNetworkCliResult,
|
|
9778
10993
|
getNativeBusinessSummary,
|
|
10994
|
+
getNativeClientVersion,
|
|
10995
|
+
getNativeHumanPresentation,
|
|
10996
|
+
getNativeHumanReadLink,
|
|
10997
|
+
getNativeHumanReadLinkReceipt,
|
|
9779
10998
|
inspectNativeTool,
|
|
10999
|
+
issueNativeHumanReadLink,
|
|
9780
11000
|
listNativeToolsPage,
|
|
11001
|
+
planNativeUpdate,
|
|
9781
11002
|
projectMediaFileQuerySchema,
|
|
9782
11003
|
readNativeBusinessPage,
|
|
9783
11004
|
readNativeCapability,
|
|
@@ -9786,6 +11007,7 @@ export {
|
|
|
9786
11007
|
readNativeDocumentPage,
|
|
9787
11008
|
readNativePackageFile,
|
|
9788
11009
|
readNativeProjectMediaFile,
|
|
11010
|
+
revokeNativeHumanReadLink,
|
|
9789
11011
|
runNetworkCli,
|
|
9790
11012
|
searchNativeBusiness,
|
|
9791
11013
|
uploadNativeMaterial,
|