@01.software/cli 0.9.0 → 0.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +414 -28
- package/dist/index.js.map +1 -1
- package/dist/mcp/{chunk-GJOQ4SE2.js → chunk-2ECTVUKU.js} +1127 -531
- package/dist/mcp/chunk-2ECTVUKU.js.map +1 -0
- package/dist/mcp/http.js +43 -11
- package/dist/mcp/http.js.map +1 -1
- package/dist/mcp/stdio.js +1 -1
- package/dist/mcp/vercel.js +1162 -540
- package/package.json +17 -9
- package/dist/mcp/chunk-GJOQ4SE2.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -128,7 +128,7 @@ ${entry}
|
|
|
128
128
|
// src/lib/output.ts
|
|
129
129
|
import pc from "picocolors";
|
|
130
130
|
|
|
131
|
-
// src/lib/
|
|
131
|
+
// src/lib/admin-error.ts
|
|
132
132
|
var PERMISSION_CODES = [
|
|
133
133
|
"tenant_mismatch",
|
|
134
134
|
"account_suspended",
|
|
@@ -515,6 +515,40 @@ function failArg(label, value, expectedKind) {
|
|
|
515
515
|
detail: { message, value, field: label }
|
|
516
516
|
});
|
|
517
517
|
}
|
|
518
|
+
function stringifyValue(value) {
|
|
519
|
+
try {
|
|
520
|
+
return JSON.stringify(value);
|
|
521
|
+
} catch {
|
|
522
|
+
return String(value);
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
function formatSchemaIssues(label, issues) {
|
|
526
|
+
return issues.map((issue) => {
|
|
527
|
+
const path = issue.path.length > 0 ? issue.path.join(".") : label;
|
|
528
|
+
return `${path}: ${issue.message}`;
|
|
529
|
+
}).join("; ");
|
|
530
|
+
}
|
|
531
|
+
function parseWithSchema(value, label, schema) {
|
|
532
|
+
const parsed = schema.safeParse(value);
|
|
533
|
+
if (parsed.success) return parsed.data;
|
|
534
|
+
const issues = parsed.error.issues.map((issue) => ({
|
|
535
|
+
path: issue.path.map(String),
|
|
536
|
+
message: issue.message
|
|
537
|
+
}));
|
|
538
|
+
const message = `Invalid value for --${label}: ${formatSchemaIssues(label, issues)}`;
|
|
539
|
+
exitWithError({
|
|
540
|
+
type: "validation",
|
|
541
|
+
code: "invalid_argument",
|
|
542
|
+
field: label,
|
|
543
|
+
message,
|
|
544
|
+
detail: {
|
|
545
|
+
message,
|
|
546
|
+
value: stringifyValue(value),
|
|
547
|
+
field: label,
|
|
548
|
+
issues
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
}
|
|
518
552
|
function parseJson(value, label, options = {}) {
|
|
519
553
|
let parsed;
|
|
520
554
|
try {
|
|
@@ -736,15 +770,65 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
736
770
|
}
|
|
737
771
|
|
|
738
772
|
// src/commands/order.ts
|
|
773
|
+
import { z } from "zod";
|
|
774
|
+
var idSchema = z.union([z.string().min(1), z.number()]).transform(String);
|
|
775
|
+
var customerSnapshotSchema = z.object({
|
|
776
|
+
email: z.string().email("Invalid email format"),
|
|
777
|
+
name: z.string().optional(),
|
|
778
|
+
phone: z.string().optional()
|
|
779
|
+
}).strict();
|
|
780
|
+
var shippingAddressSchema = z.object({
|
|
781
|
+
postalCode: z.string().optional(),
|
|
782
|
+
address: z.string().optional(),
|
|
783
|
+
detailAddress: z.string().optional(),
|
|
784
|
+
deliveryMessage: z.string().optional(),
|
|
785
|
+
recipientName: z.string().optional(),
|
|
786
|
+
phone: z.string().optional()
|
|
787
|
+
}).strict();
|
|
788
|
+
var orderItemSchema = z.object({
|
|
789
|
+
product: idSchema,
|
|
790
|
+
variant: idSchema,
|
|
791
|
+
option: idSchema,
|
|
792
|
+
quantity: z.number().int().positive("quantity must be a positive integer"),
|
|
793
|
+
unitPrice: z.number().optional(),
|
|
794
|
+
totalPrice: z.number().optional()
|
|
795
|
+
}).strict();
|
|
796
|
+
var orderItemsSchema = z.array(orderItemSchema).min(1, "At least one order item is required").max(100, "Maximum 100 items per order");
|
|
797
|
+
var orderStatusSchema = z.enum([
|
|
798
|
+
"pending",
|
|
799
|
+
"paid",
|
|
800
|
+
"failed",
|
|
801
|
+
"canceled",
|
|
802
|
+
"preparing",
|
|
803
|
+
"shipped",
|
|
804
|
+
"delivered",
|
|
805
|
+
"confirmed"
|
|
806
|
+
]);
|
|
807
|
+
var fulfillmentItemsSchema = z.array(
|
|
808
|
+
z.object({
|
|
809
|
+
orderItem: idSchema,
|
|
810
|
+
quantity: z.number().int().positive("quantity must be a positive integer")
|
|
811
|
+
}).strict()
|
|
812
|
+
).min(1, "At least one fulfillment item is required").max(100, "Maximum 100 items per fulfillment");
|
|
739
813
|
function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
740
814
|
const order = program2.command("order").description("Order management");
|
|
741
815
|
order.command("create").description("Create a new order").option("--payment-id <id>", "Payment ID").requiredOption("--order-number <num>", "Order number").requiredOption("--email <email>", "Customer email").option("--customer <id>", "Customer ID").option("--name <name>", "Customer name").option("--phone <phone>", "Customer phone").requiredOption("--shipping-address <json>", "Shipping address (JSON)").requiredOption("--products <json>", "Order products array (JSON)").requiredOption("--total-amount <n>", "Total amount", parseFloat).option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
742
816
|
try {
|
|
743
|
-
const shippingAddress =
|
|
744
|
-
opts.shippingAddress,
|
|
745
|
-
"shipping-address"
|
|
817
|
+
const shippingAddress = parseWithSchema(
|
|
818
|
+
parseJson(opts.shippingAddress, "shipping-address"),
|
|
819
|
+
"shipping-address",
|
|
820
|
+
shippingAddressSchema
|
|
821
|
+
);
|
|
822
|
+
const orderItems = parseWithSchema(
|
|
823
|
+
parseJsonArray(opts.products, "products"),
|
|
824
|
+
"products",
|
|
825
|
+
orderItemsSchema
|
|
826
|
+
);
|
|
827
|
+
const totalAmount = parseWithSchema(
|
|
828
|
+
opts.totalAmount,
|
|
829
|
+
"total-amount",
|
|
830
|
+
z.number().nonnegative("totalAmount must be non-negative")
|
|
746
831
|
);
|
|
747
|
-
const orderItems = parseJsonArray(opts.products, "products");
|
|
748
832
|
const data = {
|
|
749
833
|
pgPaymentId: opts.paymentId,
|
|
750
834
|
orderNumber: opts.orderNumber,
|
|
@@ -756,7 +840,7 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
756
840
|
customer: opts.customer,
|
|
757
841
|
shippingAddress,
|
|
758
842
|
orderItems,
|
|
759
|
-
totalAmount
|
|
843
|
+
totalAmount
|
|
760
844
|
};
|
|
761
845
|
if (opts.dryRun) {
|
|
762
846
|
printResult(
|
|
@@ -787,7 +871,8 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
787
871
|
});
|
|
788
872
|
order.command("update <orderNumber>").description("Update order status").requiredOption("--status <status>", "New status").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
789
873
|
try {
|
|
790
|
-
const
|
|
874
|
+
const status = parseWithSchema(opts.status, "status", orderStatusSchema);
|
|
875
|
+
const data = { orderNumber, status };
|
|
791
876
|
if (opts.dryRun) {
|
|
792
877
|
printResult(
|
|
793
878
|
{ dryRun: true, valid: true, action: "order update", data },
|
|
@@ -804,7 +889,11 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
804
889
|
});
|
|
805
890
|
order.command("checkout").description("Convert a cart to an order").requiredOption("--cart-id <id>", "Cart ID").option("--payment-id <id>", "Payment ID (optional for free orders)").requiredOption("--order-number <num>", "Order number").requiredOption("--customer <json>", "Customer snapshot (JSON)").option("--dry-run", "Validate inputs without executing").action(async (opts) => {
|
|
806
891
|
try {
|
|
807
|
-
const customerSnapshot =
|
|
892
|
+
const customerSnapshot = parseWithSchema(
|
|
893
|
+
parseJson(opts.customer, "customer"),
|
|
894
|
+
"customer",
|
|
895
|
+
customerSnapshotSchema
|
|
896
|
+
);
|
|
808
897
|
const data = {
|
|
809
898
|
cartId: opts.cartId,
|
|
810
899
|
pgPaymentId: opts.paymentId,
|
|
@@ -830,7 +919,11 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
830
919
|
});
|
|
831
920
|
order.command("fulfill <orderNumber>").description("Create a fulfillment for an order").requiredOption("--items <json>", "Fulfillment items array (JSON)").option("--carrier <name>", "Shipping carrier").option("--tracking-number <num>", "Tracking number").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
832
921
|
try {
|
|
833
|
-
const items =
|
|
922
|
+
const items = parseWithSchema(
|
|
923
|
+
parseJsonArray(opts.items, "items"),
|
|
924
|
+
"items",
|
|
925
|
+
fulfillmentItemsSchema
|
|
926
|
+
);
|
|
834
927
|
const data = {
|
|
835
928
|
orderNumber,
|
|
836
929
|
items,
|
|
@@ -857,6 +950,23 @@ function registerOrderCommands(program2, getClient2, getFormat2) {
|
|
|
857
950
|
}
|
|
858
951
|
|
|
859
952
|
// src/commands/return.ts
|
|
953
|
+
import { z as z2 } from "zod";
|
|
954
|
+
var idSchema2 = z2.union([z2.string().min(1), z2.number()]).transform(String);
|
|
955
|
+
var returnReasonSchema = z2.enum(["change_of_mind", "defective", "wrong_delivery", "damaged", "other"]).optional();
|
|
956
|
+
var returnItemsSchema = z2.array(
|
|
957
|
+
z2.object({
|
|
958
|
+
orderItem: idSchema2,
|
|
959
|
+
quantity: z2.number().int().positive("quantity must be a positive integer"),
|
|
960
|
+
restockAction: z2.enum(["return_to_stock", "discard"]).default("return_to_stock")
|
|
961
|
+
}).strict()
|
|
962
|
+
).min(1, "At least one return item is required").max(100, "Too many return items");
|
|
963
|
+
var returnStatusSchema = z2.enum([
|
|
964
|
+
"processing",
|
|
965
|
+
"approved",
|
|
966
|
+
"rejected",
|
|
967
|
+
"completed"
|
|
968
|
+
]);
|
|
969
|
+
var refundAmountSchema = z2.number().nonnegative("refundAmount must be non-negative");
|
|
860
970
|
function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
861
971
|
const ret = program2.command("return").description("Return management");
|
|
862
972
|
ret.command("create <orderNumber>").description("Create a return request").requiredOption("--products <json>", "Return products array (JSON)").requiredOption("--refund-amount <n>", "Refund amount", parseFloat).option(
|
|
@@ -864,12 +974,26 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
864
974
|
"Return reason (change_of_mind, defective, wrong_delivery, damaged, other)"
|
|
865
975
|
).option("--reason-detail <text>", "Detailed reason").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
866
976
|
try {
|
|
867
|
-
const returnItems =
|
|
977
|
+
const returnItems = parseWithSchema(
|
|
978
|
+
parseJsonArray(opts.products, "products"),
|
|
979
|
+
"products",
|
|
980
|
+
returnItemsSchema
|
|
981
|
+
);
|
|
982
|
+
const refundAmount = parseWithSchema(
|
|
983
|
+
opts.refundAmount,
|
|
984
|
+
"refund-amount",
|
|
985
|
+
refundAmountSchema
|
|
986
|
+
);
|
|
987
|
+
const reason = parseWithSchema(
|
|
988
|
+
opts.reason,
|
|
989
|
+
"reason",
|
|
990
|
+
returnReasonSchema
|
|
991
|
+
);
|
|
868
992
|
const data = {
|
|
869
993
|
orderNumber,
|
|
870
994
|
returnItems,
|
|
871
|
-
refundAmount
|
|
872
|
-
reason
|
|
995
|
+
refundAmount,
|
|
996
|
+
reason,
|
|
873
997
|
reasonDetail: opts.reasonDetail
|
|
874
998
|
};
|
|
875
999
|
if (opts.dryRun) {
|
|
@@ -894,7 +1018,8 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
894
1018
|
"New status (processing, approved, rejected, completed)"
|
|
895
1019
|
).option("--dry-run", "Validate inputs without executing").action(async (returnId, opts) => {
|
|
896
1020
|
try {
|
|
897
|
-
const
|
|
1021
|
+
const status = parseWithSchema(opts.status, "status", returnStatusSchema);
|
|
1022
|
+
const data = { returnId, status };
|
|
898
1023
|
if (opts.dryRun) {
|
|
899
1024
|
printResult(
|
|
900
1025
|
{ dryRun: true, valid: true, action: "return update", data },
|
|
@@ -911,13 +1036,27 @@ function registerReturnCommands(program2, getClient2, getFormat2) {
|
|
|
911
1036
|
});
|
|
912
1037
|
ret.command("refund <orderNumber>").description("Return with refund").requiredOption("--products <json>", "Return products array (JSON)").requiredOption("--refund-amount <n>", "Refund amount", parseFloat).requiredOption("--payment-id <id>", "Payment ID").option("--reason <reason>", "Return reason").option("--reason-detail <text>", "Detailed reason").option("--refund-receipt-url <url>", "Refund receipt URL").option("--dry-run", "Validate inputs without executing").action(async (orderNumber, opts) => {
|
|
913
1038
|
try {
|
|
914
|
-
const returnItems =
|
|
1039
|
+
const returnItems = parseWithSchema(
|
|
1040
|
+
parseJsonArray(opts.products, "products"),
|
|
1041
|
+
"products",
|
|
1042
|
+
returnItemsSchema
|
|
1043
|
+
);
|
|
1044
|
+
const refundAmount = parseWithSchema(
|
|
1045
|
+
opts.refundAmount,
|
|
1046
|
+
"refund-amount",
|
|
1047
|
+
refundAmountSchema
|
|
1048
|
+
);
|
|
1049
|
+
const reason = parseWithSchema(
|
|
1050
|
+
opts.reason,
|
|
1051
|
+
"reason",
|
|
1052
|
+
returnReasonSchema
|
|
1053
|
+
);
|
|
915
1054
|
const data = {
|
|
916
1055
|
orderNumber,
|
|
917
1056
|
returnItems,
|
|
918
|
-
refundAmount
|
|
1057
|
+
refundAmount,
|
|
919
1058
|
pgPaymentId: opts.paymentId,
|
|
920
|
-
reason
|
|
1059
|
+
reason,
|
|
921
1060
|
reasonDetail: opts.reasonDetail,
|
|
922
1061
|
refundReceiptUrl: opts.refundReceiptUrl
|
|
923
1062
|
};
|
|
@@ -1413,25 +1552,265 @@ function registerSchemaCommands(program2, getClient2, getFormat2) {
|
|
|
1413
1552
|
});
|
|
1414
1553
|
}
|
|
1415
1554
|
|
|
1555
|
+
// ../contracts/src/tenant/index.ts
|
|
1556
|
+
import { z as z3 } from "zod";
|
|
1557
|
+
var tenantFieldConfigStateSchema = z3.object({
|
|
1558
|
+
hiddenFields: z3.array(z3.string()),
|
|
1559
|
+
isHidden: z3.boolean()
|
|
1560
|
+
}).strict();
|
|
1561
|
+
var tenantContextQuerySchema = z3.object({
|
|
1562
|
+
counts: z3.literal("true").optional()
|
|
1563
|
+
}).strict();
|
|
1564
|
+
var tenantContextToolInputSchema = z3.object({
|
|
1565
|
+
includeCounts: z3.boolean().optional().default(false).describe(
|
|
1566
|
+
"Include per-collection document counts and config status (bypasses cache, slower)"
|
|
1567
|
+
)
|
|
1568
|
+
}).strict();
|
|
1569
|
+
var tenantContextResponseSchema = z3.object({
|
|
1570
|
+
tenant: z3.object({
|
|
1571
|
+
id: z3.string(),
|
|
1572
|
+
name: z3.string(),
|
|
1573
|
+
plan: z3.string(),
|
|
1574
|
+
planSource: z3.string().optional(),
|
|
1575
|
+
authoritative: z3.boolean().optional(),
|
|
1576
|
+
capabilityVersion: z3.string().optional()
|
|
1577
|
+
}).strict(),
|
|
1578
|
+
features: z3.array(z3.string()),
|
|
1579
|
+
collections: z3.object({
|
|
1580
|
+
active: z3.array(z3.string()),
|
|
1581
|
+
inactive: z3.array(z3.string())
|
|
1582
|
+
}).strict(),
|
|
1583
|
+
fieldConfigs: z3.record(z3.string(), tenantFieldConfigStateSchema),
|
|
1584
|
+
counts: z3.record(z3.string(), z3.number()).optional(),
|
|
1585
|
+
config: z3.object({
|
|
1586
|
+
webhookConfigured: z3.boolean()
|
|
1587
|
+
}).strict().optional()
|
|
1588
|
+
}).strict();
|
|
1589
|
+
var tenantFeatureProgressFeatureSchema = z3.enum(["ecommerce"]);
|
|
1590
|
+
var tenantFeatureProgressInputSchema = z3.object({
|
|
1591
|
+
feature: tenantFeatureProgressFeatureSchema.describe(
|
|
1592
|
+
"Feature to inspect for tenant implementation readiness"
|
|
1593
|
+
),
|
|
1594
|
+
includeEvidence: z3.boolean().optional().default(false).describe("Include sanitized counts and static surface evidence")
|
|
1595
|
+
}).strict();
|
|
1596
|
+
var tenantFeatureProgressStatusSchema = z3.enum([
|
|
1597
|
+
"ready",
|
|
1598
|
+
"attention",
|
|
1599
|
+
"blocked"
|
|
1600
|
+
]);
|
|
1601
|
+
var tenantFeatureProgressItemStateSchema = z3.enum([
|
|
1602
|
+
"complete",
|
|
1603
|
+
"incomplete",
|
|
1604
|
+
"blocked",
|
|
1605
|
+
"attention",
|
|
1606
|
+
"optional",
|
|
1607
|
+
"unknown",
|
|
1608
|
+
"manual",
|
|
1609
|
+
"not-applicable"
|
|
1610
|
+
]);
|
|
1611
|
+
var tenantFeatureProgressSeveritySchema = z3.enum([
|
|
1612
|
+
"required",
|
|
1613
|
+
"recommended",
|
|
1614
|
+
"optional"
|
|
1615
|
+
]);
|
|
1616
|
+
var tenantFeatureProgressEvidenceValueSchema = z3.union([
|
|
1617
|
+
z3.string(),
|
|
1618
|
+
z3.number(),
|
|
1619
|
+
z3.boolean(),
|
|
1620
|
+
z3.null()
|
|
1621
|
+
]);
|
|
1622
|
+
var tenantFeatureProgressItemSchema = z3.object({
|
|
1623
|
+
id: z3.string(),
|
|
1624
|
+
title: z3.string(),
|
|
1625
|
+
state: tenantFeatureProgressItemStateSchema,
|
|
1626
|
+
severity: tenantFeatureProgressSeveritySchema,
|
|
1627
|
+
summary: z3.string(),
|
|
1628
|
+
evidence: z3.record(z3.string(), tenantFeatureProgressEvidenceValueSchema).optional()
|
|
1629
|
+
}).strict();
|
|
1630
|
+
var tenantFeatureProgressGroupSchema = z3.object({
|
|
1631
|
+
id: z3.string(),
|
|
1632
|
+
title: z3.string(),
|
|
1633
|
+
summary: z3.string().optional(),
|
|
1634
|
+
items: z3.array(tenantFeatureProgressItemSchema)
|
|
1635
|
+
}).strict();
|
|
1636
|
+
var tenantFeatureProgressResponseSchema = z3.object({
|
|
1637
|
+
schemaVersion: z3.literal(1),
|
|
1638
|
+
feature: tenantFeatureProgressFeatureSchema,
|
|
1639
|
+
status: tenantFeatureProgressStatusSchema,
|
|
1640
|
+
generatedAt: z3.string(),
|
|
1641
|
+
tenant: z3.object({
|
|
1642
|
+
id: z3.string(),
|
|
1643
|
+
name: z3.string(),
|
|
1644
|
+
plan: z3.string()
|
|
1645
|
+
}).strict(),
|
|
1646
|
+
capability: z3.object({
|
|
1647
|
+
effectiveFeatures: z3.array(z3.string()),
|
|
1648
|
+
planBlocked: z3.array(z3.string()),
|
|
1649
|
+
closureAdded: z3.array(z3.string())
|
|
1650
|
+
}).strict(),
|
|
1651
|
+
summary: z3.object({
|
|
1652
|
+
complete: z3.number().int().nonnegative(),
|
|
1653
|
+
total: z3.number().int().nonnegative(),
|
|
1654
|
+
blocking: z3.number().int().nonnegative(),
|
|
1655
|
+
manual: z3.number().int().nonnegative(),
|
|
1656
|
+
unknown: z3.number().int().nonnegative()
|
|
1657
|
+
}).strict(),
|
|
1658
|
+
groups: z3.array(tenantFeatureProgressGroupSchema)
|
|
1659
|
+
}).strict();
|
|
1660
|
+
var COLLECTION_SCHEMA_CONTRACT_VERSION = 1;
|
|
1661
|
+
var collectionSchemaEndpointParamsSchema = z3.object({
|
|
1662
|
+
collectionSlug: z3.string().min(1, "collectionSlug is required")
|
|
1663
|
+
}).strict();
|
|
1664
|
+
var collectionFieldOptionSchema = z3.object({
|
|
1665
|
+
label: z3.string(),
|
|
1666
|
+
value: z3.string()
|
|
1667
|
+
}).strict();
|
|
1668
|
+
var collectionFieldSchema = z3.lazy(
|
|
1669
|
+
() => z3.object({
|
|
1670
|
+
name: z3.string(),
|
|
1671
|
+
path: z3.string(),
|
|
1672
|
+
type: z3.string(),
|
|
1673
|
+
required: z3.literal(true).optional(),
|
|
1674
|
+
unique: z3.literal(true).optional(),
|
|
1675
|
+
hasMany: z3.literal(true).optional(),
|
|
1676
|
+
relationTo: z3.union([z3.string(), z3.array(z3.string())]).optional(),
|
|
1677
|
+
options: z3.array(collectionFieldOptionSchema).optional(),
|
|
1678
|
+
hidden: z3.literal(true).optional(),
|
|
1679
|
+
systemManaged: z3.literal(true).optional(),
|
|
1680
|
+
writable: z3.boolean().optional(),
|
|
1681
|
+
fields: z3.array(collectionFieldSchema).optional()
|
|
1682
|
+
}).strict()
|
|
1683
|
+
);
|
|
1684
|
+
var collectionSchemaResponseSchema = z3.object({
|
|
1685
|
+
contractVersion: z3.literal(COLLECTION_SCHEMA_CONTRACT_VERSION),
|
|
1686
|
+
mode: z3.literal("effective"),
|
|
1687
|
+
collection: z3.object({
|
|
1688
|
+
slug: z3.string(),
|
|
1689
|
+
timestamps: z3.boolean(),
|
|
1690
|
+
alwaysActive: z3.boolean(),
|
|
1691
|
+
feature: z3.string().nullable(),
|
|
1692
|
+
systemFields: z3.array(z3.string()),
|
|
1693
|
+
visibility: z3.object({
|
|
1694
|
+
collectionHidden: z3.boolean(),
|
|
1695
|
+
hiddenFields: z3.array(z3.string())
|
|
1696
|
+
}).strict(),
|
|
1697
|
+
fields: z3.array(collectionFieldSchema)
|
|
1698
|
+
}).strict()
|
|
1699
|
+
}).strict();
|
|
1700
|
+
|
|
1701
|
+
// src/commands/feature.ts
|
|
1702
|
+
function getApiUrl2() {
|
|
1703
|
+
return (process.env.SOFTWARE_API_URL || process.env.NEXT_PUBLIC_SOFTWARE_API_URL || "https://api.01.software").replace(/\/$/, "");
|
|
1704
|
+
}
|
|
1705
|
+
function flattenProgress(progress) {
|
|
1706
|
+
return progress.groups.flatMap(
|
|
1707
|
+
(group) => group.items.map((item) => ({
|
|
1708
|
+
group: group.title,
|
|
1709
|
+
item: item.title,
|
|
1710
|
+
state: item.state,
|
|
1711
|
+
severity: item.severity,
|
|
1712
|
+
summary: item.summary
|
|
1713
|
+
}))
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
function registerFeatureCommands(program2, getClient2, getFormat2) {
|
|
1717
|
+
const feature = program2.command("feature").description("Feature implementation progress checks");
|
|
1718
|
+
feature.command("check <feature>").description("Check tenant implementation progress for a feature").option("--evidence", "Include sanitized evidence counts and surface flags").action(async (featureName, options) => {
|
|
1719
|
+
try {
|
|
1720
|
+
const input = parseWithSchema(
|
|
1721
|
+
{
|
|
1722
|
+
feature: featureName,
|
|
1723
|
+
includeEvidence: Boolean(options.evidence)
|
|
1724
|
+
},
|
|
1725
|
+
"feature",
|
|
1726
|
+
tenantFeatureProgressInputSchema
|
|
1727
|
+
);
|
|
1728
|
+
const client = getClient2();
|
|
1729
|
+
const baseUrl = getApiUrl2();
|
|
1730
|
+
const search = new URLSearchParams({ feature: input.feature });
|
|
1731
|
+
if (input.includeEvidence) search.set("includeEvidence", "true");
|
|
1732
|
+
const response = await fetch(
|
|
1733
|
+
`${baseUrl}/api/tenants/feature-progress?${search.toString()}`,
|
|
1734
|
+
{
|
|
1735
|
+
headers: {
|
|
1736
|
+
"X-Publishable-Key": client.publishableKey,
|
|
1737
|
+
Authorization: `Bearer ${client.secretKey}`
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
);
|
|
1741
|
+
if (!response.ok) {
|
|
1742
|
+
const body = await response.json().catch(() => ({ error: response.statusText }));
|
|
1743
|
+
const err = new Error(
|
|
1744
|
+
body.error || `HTTP ${response.status}`
|
|
1745
|
+
);
|
|
1746
|
+
Object.assign(err, { status: response.status });
|
|
1747
|
+
throw err;
|
|
1748
|
+
}
|
|
1749
|
+
const result = tenantFeatureProgressResponseSchema.parse(
|
|
1750
|
+
await response.json()
|
|
1751
|
+
);
|
|
1752
|
+
const format = getFormat2();
|
|
1753
|
+
printResult(
|
|
1754
|
+
format === "table" ? flattenProgress(result) : result,
|
|
1755
|
+
format
|
|
1756
|
+
);
|
|
1757
|
+
} catch (error) {
|
|
1758
|
+
exitWithError(error);
|
|
1759
|
+
}
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1416
1763
|
// src/commands/mcp.ts
|
|
1417
1764
|
import { resolve, dirname } from "path";
|
|
1418
1765
|
import { existsSync as existsSync2 } from "fs";
|
|
1419
1766
|
import { spawn } from "child_process";
|
|
1420
1767
|
import { fileURLToPath } from "url";
|
|
1421
1768
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
1422
|
-
function
|
|
1423
|
-
const
|
|
1424
|
-
|
|
1769
|
+
function getStdioEntryCandidates(baseDir = __dirname) {
|
|
1770
|
+
const candidates = [
|
|
1771
|
+
{
|
|
1772
|
+
label: "packaged CLI artifact",
|
|
1773
|
+
path: resolve(baseDir, "mcp/stdio.js")
|
|
1774
|
+
}
|
|
1775
|
+
];
|
|
1425
1776
|
const roots = ["../../../..", "../../..", "../.."];
|
|
1426
|
-
const entries = [
|
|
1777
|
+
const entries = [
|
|
1778
|
+
{
|
|
1779
|
+
label: "monorepo build output",
|
|
1780
|
+
path: "apps/mcp/dist/stdio.js"
|
|
1781
|
+
},
|
|
1782
|
+
{
|
|
1783
|
+
label: "xmcp build output",
|
|
1784
|
+
path: "apps/mcp/.xmcp/stdio.js"
|
|
1785
|
+
}
|
|
1786
|
+
];
|
|
1427
1787
|
for (const entry of entries) {
|
|
1428
1788
|
for (const root of roots) {
|
|
1429
|
-
|
|
1430
|
-
|
|
1789
|
+
candidates.push({
|
|
1790
|
+
label: entry.label,
|
|
1791
|
+
path: resolve(baseDir, root, entry.path)
|
|
1792
|
+
});
|
|
1431
1793
|
}
|
|
1432
1794
|
}
|
|
1795
|
+
return candidates;
|
|
1796
|
+
}
|
|
1797
|
+
function findStdioEntry(baseDir = __dirname) {
|
|
1798
|
+
for (const candidate of getStdioEntryCandidates(baseDir)) {
|
|
1799
|
+
if (existsSync2(candidate.path)) return candidate.path;
|
|
1800
|
+
}
|
|
1433
1801
|
return null;
|
|
1434
1802
|
}
|
|
1803
|
+
function formatMissingStdioEntryMessage(baseDir = __dirname) {
|
|
1804
|
+
const checked = getStdioEntryCandidates(baseDir).map((candidate) => ` - ${candidate.label}: ${candidate.path}`).join("\n");
|
|
1805
|
+
return [
|
|
1806
|
+
"MCP stdio entry not found.",
|
|
1807
|
+
"Checked:",
|
|
1808
|
+
checked,
|
|
1809
|
+
"Fix:",
|
|
1810
|
+
" - Monorepo checkout: run pnpm --filter mcp build.",
|
|
1811
|
+
" - Published CLI: reinstall or update @01.software/cli so dist/mcp/stdio.js is included."
|
|
1812
|
+
].join("\n");
|
|
1813
|
+
}
|
|
1435
1814
|
function createMcpEnv(baseEnv, client) {
|
|
1436
1815
|
const env = {
|
|
1437
1816
|
...baseEnv,
|
|
@@ -1442,15 +1821,21 @@ function createMcpEnv(baseEnv, client) {
|
|
|
1442
1821
|
return env;
|
|
1443
1822
|
}
|
|
1444
1823
|
function registerMcpCommands(program2) {
|
|
1445
|
-
program2.command("mcp").description("Start MCP server
|
|
1824
|
+
program2.command("mcp").description("Start local MCP stdio server for trusted server-key workflows").addHelpText(
|
|
1825
|
+
"after",
|
|
1826
|
+
`
|
|
1827
|
+
Prerequisites:
|
|
1828
|
+
Run 01 login, or set SOFTWARE_PUBLISHABLE_KEY and SOFTWARE_SECRET_KEY.
|
|
1829
|
+
Local stdio exposes the full MCP tool surface; HTTP OAuth MCP uses the
|
|
1830
|
+
narrower remote surface documented in the web integration guide.
|
|
1831
|
+
In a monorepo checkout, build the stdio artifact first:
|
|
1832
|
+
pnpm --filter mcp build
|
|
1833
|
+
`
|
|
1834
|
+
).action(() => {
|
|
1446
1835
|
const client = resolveClient(program2.opts().apiKey);
|
|
1447
1836
|
const stdioEntry = findStdioEntry();
|
|
1448
1837
|
if (!stdioEntry) {
|
|
1449
|
-
exitWithError(
|
|
1450
|
-
new Error(
|
|
1451
|
-
"MCP server not found. Ensure apps/mcp is built (pnpm --filter mcp build)."
|
|
1452
|
-
)
|
|
1453
|
-
);
|
|
1838
|
+
exitWithError(new Error(formatMissingStdioEntryMessage()));
|
|
1454
1839
|
}
|
|
1455
1840
|
const child = spawn(process.execPath, [stdioEntry], {
|
|
1456
1841
|
env: createMcpEnv(process.env, client),
|
|
@@ -1487,6 +1872,7 @@ registerCartCommands(program, getClient, getFormat);
|
|
|
1487
1872
|
registerStockCommands(program, getClient, getFormat);
|
|
1488
1873
|
registerTransactionCommands(program, getClient, getFormat);
|
|
1489
1874
|
registerSchemaCommands(program, getClient, getFormat);
|
|
1875
|
+
registerFeatureCommands(program, getClient, getFormat);
|
|
1490
1876
|
registerMcpCommands(program);
|
|
1491
1877
|
registerAuthCommands(program);
|
|
1492
1878
|
program.parse();
|