@chalksurf/cli 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -4
- package/dist/bin/chalksurf.js +410 -274
- package/docs/agents.md +12 -20
- package/docs/manual.md +23 -4
- package/docs/mcp.md +22 -10
- package/package.json +1 -1
package/dist/bin/chalksurf.js
CHANGED
|
@@ -20,6 +20,27 @@ var ApiClientError = class extends Error {
|
|
|
20
20
|
var normalizeBaseUrl = (baseUrl) => {
|
|
21
21
|
return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
|
|
22
22
|
};
|
|
23
|
+
var getSafeBaseUrlForError = (baseUrl) => {
|
|
24
|
+
const url = new URL(baseUrl);
|
|
25
|
+
url.username = "";
|
|
26
|
+
url.password = "";
|
|
27
|
+
url.search = "";
|
|
28
|
+
url.hash = "";
|
|
29
|
+
const safeBaseUrl = url.toString();
|
|
30
|
+
return safeBaseUrl.endsWith("/") ? safeBaseUrl : `${safeBaseUrl}/`;
|
|
31
|
+
};
|
|
32
|
+
var getSafeNetworkCause = ({ error, token }) => {
|
|
33
|
+
if (!(error instanceof Error)) {
|
|
34
|
+
return void 0;
|
|
35
|
+
}
|
|
36
|
+
const causeCode = typeof error.cause === "object" && error.cause !== null && "code" in error.cause && typeof error.cause.code === "string" && /^[A-Z0-9_]+$/.test(error.cause.code) ? error.cause.code : void 0;
|
|
37
|
+
const errorMessage = error.message.trim();
|
|
38
|
+
const combinedCause = [causeCode, errorMessage].filter(Boolean).join(": ");
|
|
39
|
+
if (combinedCause.length === 0 || combinedCause.length > 200 || /authorization|bearer|password|secret|token/iu.test(combinedCause) || token && combinedCause.includes(token)) {
|
|
40
|
+
return void 0;
|
|
41
|
+
}
|
|
42
|
+
return combinedCause;
|
|
43
|
+
};
|
|
23
44
|
var getErrorMessage = (payload, status) => {
|
|
24
45
|
return payload?.error?.message ?? `API request failed with status ${status}`;
|
|
25
46
|
};
|
|
@@ -51,6 +72,7 @@ var createApiClient = ({
|
|
|
51
72
|
organizationId
|
|
52
73
|
}) => {
|
|
53
74
|
const normalizedBaseUrl = normalizeBaseUrl(baseUrl);
|
|
75
|
+
const safeBaseUrlForError = getSafeBaseUrlForError(normalizedBaseUrl);
|
|
54
76
|
const createHeaders = ({ includeJsonContentType }) => {
|
|
55
77
|
const headers = new Headers();
|
|
56
78
|
if (token) {
|
|
@@ -64,11 +86,21 @@ var createApiClient = ({
|
|
|
64
86
|
}
|
|
65
87
|
return headers;
|
|
66
88
|
};
|
|
89
|
+
const fetchApi = async (url, init) => {
|
|
90
|
+
try {
|
|
91
|
+
return await fetch(url, init);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
const safeCause = getSafeNetworkCause({ error, token });
|
|
94
|
+
throw new ApiClientError(
|
|
95
|
+
`Could not reach ChalkSurf API at ${safeBaseUrlForError}.${safeCause ? ` Cause: ${safeCause}` : ""}`
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
};
|
|
67
99
|
const query = async (procedureName, input) => {
|
|
68
100
|
const url = new URL(`trpc/${procedureName}`, normalizedBaseUrl);
|
|
69
101
|
url.searchParams.set("batch", "1");
|
|
70
102
|
url.searchParams.set("input", JSON.stringify({ 0: input ?? null }));
|
|
71
|
-
const response = await
|
|
103
|
+
const response = await fetchApi(url.toString(), {
|
|
72
104
|
method: "GET",
|
|
73
105
|
headers: createHeaders({ includeJsonContentType: false })
|
|
74
106
|
});
|
|
@@ -76,7 +108,7 @@ var createApiClient = ({
|
|
|
76
108
|
};
|
|
77
109
|
const mutation = async (procedureName, input) => {
|
|
78
110
|
const isFormDataInput = input instanceof FormData;
|
|
79
|
-
const response = await
|
|
111
|
+
const response = await fetchApi(new URL(`trpc/${procedureName}`, normalizedBaseUrl).toString(), {
|
|
80
112
|
method: "POST",
|
|
81
113
|
headers: createHeaders({ includeJsonContentType: !isFormDataInput }),
|
|
82
114
|
body: isFormDataInput ? input : JSON.stringify(input ?? {})
|
|
@@ -140,9 +172,6 @@ var createApiClient = ({
|
|
|
140
172
|
agentUploadExerciseFigure: async (input) => {
|
|
141
173
|
return await mutation("agentUploadExerciseFigure", input);
|
|
142
174
|
},
|
|
143
|
-
agentAttachExerciseFigures: async (input) => {
|
|
144
|
-
return await mutation("agentAttachExerciseFigures", input);
|
|
145
|
-
},
|
|
146
175
|
agentUpdateExercise: async (input) => {
|
|
147
176
|
return await mutation("agentUpdateExercise", input);
|
|
148
177
|
},
|
|
@@ -182,8 +211,11 @@ var createApiClient = ({
|
|
|
182
211
|
agentBulkUpdateSheets: async (input) => {
|
|
183
212
|
return await mutation("agentBulkUpdateSheets", input);
|
|
184
213
|
},
|
|
185
|
-
|
|
186
|
-
return await query("
|
|
214
|
+
agentListSheets: async (input) => {
|
|
215
|
+
return await query("agentListSheets", input);
|
|
216
|
+
},
|
|
217
|
+
agentListSheetSeries: async (input = {}) => {
|
|
218
|
+
return await query("agentListSheetSeries", input);
|
|
187
219
|
},
|
|
188
220
|
agentSetSheetVisibility: async (input) => {
|
|
189
221
|
return await mutation("agentSetSheetVisibility", input);
|
|
@@ -931,7 +963,6 @@ import { z as z2 } from "zod";
|
|
|
931
963
|
var exerciseStatusOptions = Constants.public.Enums.exercise_status;
|
|
932
964
|
var exerciseQualityIssueSeverities = Constants.public.Enums.exercise_quality_issue_severity;
|
|
933
965
|
var exerciseQualityIssueStatuses = Constants.public.Enums.exercise_quality_issue_status;
|
|
934
|
-
var figureAssetSourceKinds = Constants.public.Enums.figure_asset_source_kind;
|
|
935
966
|
var exerciseFigureRowSourceKinds = Constants.public.Enums.exercise_figure_source_kind;
|
|
936
967
|
var exerciseFigureRenditionPurposes = Constants.public.Enums.exercise_figure_rendition_purpose;
|
|
937
968
|
var exerciseVersionTypes = Constants.public.Enums.exercise_version_type;
|
|
@@ -1440,12 +1471,6 @@ var agentWriteOperationRegistry = {
|
|
|
1440
1471
|
upload_exercise_figure: {
|
|
1441
1472
|
agentToolName: "upload_exercise_figure",
|
|
1442
1473
|
receiptOperation: "upload_exercise_figure",
|
|
1443
|
-
resourceType: "figure_asset",
|
|
1444
|
-
sync: true
|
|
1445
|
-
},
|
|
1446
|
-
attach_exercise_figures: {
|
|
1447
|
-
agentToolName: "attach_exercise_figures",
|
|
1448
|
-
receiptOperation: "attach_exercise_figures",
|
|
1449
1474
|
resourceType: "exercise",
|
|
1450
1475
|
sync: true
|
|
1451
1476
|
},
|
|
@@ -1596,15 +1621,17 @@ var exerciseTranslationSchema = strictObject({
|
|
|
1596
1621
|
status: z3.enum(exerciseStatusOptions)
|
|
1597
1622
|
});
|
|
1598
1623
|
var exerciseFigureWidthSchema = z3.number().finite().min(minExerciseFigureWidthInCm).max(maxExerciseFigureWidthInCm);
|
|
1599
|
-
var
|
|
1624
|
+
var agentExerciseFigureInputSchema = strictObject({
|
|
1600
1625
|
type: z3.enum(exerciseFigureTypes),
|
|
1601
1626
|
url: z3.url(),
|
|
1602
1627
|
widthInCm: exerciseFigureWidthSchema,
|
|
1603
1628
|
exerciseFigureId: uuidSchema.optional(),
|
|
1604
|
-
|
|
1629
|
+
orderIndex: z3.number().int().min(0).optional(),
|
|
1630
|
+
rotationClockwiseDegrees: exerciseFigureRotationSchema.optional(),
|
|
1605
1631
|
provenance: exerciseFigureProvenanceSchema.optional()
|
|
1606
1632
|
});
|
|
1607
|
-
var agentExerciseFigureSchema =
|
|
1633
|
+
var agentExerciseFigureSchema = agentExerciseFigureInputSchema.extend({
|
|
1634
|
+
exerciseFigureId: uuidSchema,
|
|
1608
1635
|
orderIndex: z3.number().int().min(0),
|
|
1609
1636
|
rotationClockwiseDegrees: exerciseFigureRotationSchema
|
|
1610
1637
|
});
|
|
@@ -1703,6 +1730,34 @@ var folderSchema = strictObject({
|
|
|
1703
1730
|
parentId: uuidSchema.nullable(),
|
|
1704
1731
|
updatedAt: dateStringSchema
|
|
1705
1732
|
});
|
|
1733
|
+
var folderPathSegmentSchema = strictObject({
|
|
1734
|
+
id: uuidSchema,
|
|
1735
|
+
name: z3.string().trim().min(1)
|
|
1736
|
+
});
|
|
1737
|
+
var listSheetsAgentInputSchema = strictObject({
|
|
1738
|
+
folderId: uuidSchema.optional(),
|
|
1739
|
+
includeDescendants: z3.boolean().optional().default(false),
|
|
1740
|
+
limit: z3.number().int().min(1).max(100).optional().default(50),
|
|
1741
|
+
offset: z3.number().int().min(0).optional().default(0)
|
|
1742
|
+
}).refine(({ folderId, includeDescendants }) => folderId !== void 0 || !includeDescendants, {
|
|
1743
|
+
message: "folderId is required when includeDescendants is true",
|
|
1744
|
+
path: ["folderId"]
|
|
1745
|
+
});
|
|
1746
|
+
var listSheetsAgentOutputSchema = strictObject({
|
|
1747
|
+
sheets: z3.array(
|
|
1748
|
+
strictObject({
|
|
1749
|
+
id: uuidSchema,
|
|
1750
|
+
name: z3.string().trim().min(1),
|
|
1751
|
+
subject: z3.enum(exerciseSubjects),
|
|
1752
|
+
isPublic: z3.boolean(),
|
|
1753
|
+
folderId: uuidSchema.nullable(),
|
|
1754
|
+
folderPath: z3.array(folderPathSegmentSchema),
|
|
1755
|
+
updatedAt: dateStringSchema,
|
|
1756
|
+
seriesAssignments: sheetSeriesAssignmentsSchema
|
|
1757
|
+
})
|
|
1758
|
+
),
|
|
1759
|
+
totalCount: z3.number().int().min(0)
|
|
1760
|
+
});
|
|
1706
1761
|
var exerciseLabelSchema = strictObject({
|
|
1707
1762
|
id: z3.string().trim().min(1),
|
|
1708
1763
|
subject: z3.enum(exerciseSubjects),
|
|
@@ -1955,7 +2010,7 @@ var getExerciseUsageAgentOutputSchema = strictObject({
|
|
|
1955
2010
|
});
|
|
1956
2011
|
var agentWriteReceiptSchema = strictObject({
|
|
1957
2012
|
resource: strictObject({
|
|
1958
|
-
type: z3.enum(["exercise", "sheet", "folder"
|
|
2013
|
+
type: z3.enum(["exercise", "sheet", "folder"]),
|
|
1959
2014
|
id: uuidSchema
|
|
1960
2015
|
}),
|
|
1961
2016
|
operation: agentWriteReceiptOperationSchema,
|
|
@@ -2031,14 +2086,6 @@ var exerciseCreateFigureSchema = strictObject({
|
|
|
2031
2086
|
widthInCm: z3.number().positive().finite().optional(),
|
|
2032
2087
|
provenance: exerciseFigureProvenanceSchema.optional()
|
|
2033
2088
|
});
|
|
2034
|
-
var agentExerciseFigureInputSchema = strictObject({
|
|
2035
|
-
type: z3.enum(exerciseFigureTypes),
|
|
2036
|
-
url: z3.url(),
|
|
2037
|
-
widthInCm: exerciseFigureWidthSchema.optional(),
|
|
2038
|
-
exerciseFigureId: uuidSchema.optional(),
|
|
2039
|
-
figureAssetId: uuidSchema.optional(),
|
|
2040
|
-
provenance: exerciseFigureProvenanceSchema.optional()
|
|
2041
|
-
});
|
|
2042
2089
|
var figureReviewWarningSchema = strictObject({
|
|
2043
2090
|
code: z3.string().trim().min(1),
|
|
2044
2091
|
message: z3.string().trim().min(1),
|
|
@@ -2066,7 +2113,7 @@ var uploadExerciseFigureSourceSchema = z3.discriminatedUnion("kind", [
|
|
|
2066
2113
|
})
|
|
2067
2114
|
]);
|
|
2068
2115
|
var uploadExerciseFigureAgentInputSchema = strictObject({
|
|
2069
|
-
exerciseId: uuidSchema
|
|
2116
|
+
exerciseId: uuidSchema,
|
|
2070
2117
|
figureType: z3.enum(exerciseFigureTypes),
|
|
2071
2118
|
source: uploadExerciseFigureSourceSchema,
|
|
2072
2119
|
widthInCm: exerciseFigureWidthSchema.optional().default(defaultExerciseFigureWidthInCm),
|
|
@@ -2083,53 +2130,10 @@ var figureUploadReviewSchema = strictObject({
|
|
|
2083
2130
|
nextActions: z3.array(z3.string().trim().min(1))
|
|
2084
2131
|
});
|
|
2085
2132
|
var uploadExerciseFigureAgentOutputSchema = strictObject({
|
|
2086
|
-
figure:
|
|
2133
|
+
figure: agentExerciseFigureSchema,
|
|
2087
2134
|
review: figureUploadReviewSchema,
|
|
2088
2135
|
receipt: agentWriteReceiptSchema
|
|
2089
2136
|
});
|
|
2090
|
-
var attachExerciseFiguresAgentInputSchema = strictObject({
|
|
2091
|
-
exerciseId: uuidSchema,
|
|
2092
|
-
expectedUpdatedAt: expectedUpdatedAtSchema,
|
|
2093
|
-
targetSheetId: uuidSchema.nullable().optional(),
|
|
2094
|
-
allowSharedExerciseUpdate: z3.boolean().optional().default(false),
|
|
2095
|
-
mode: z3.enum(["append", "replace_type", "replace_all"]),
|
|
2096
|
-
figureType: z3.enum(exerciseFigureTypes).optional(),
|
|
2097
|
-
figures: z3.array(agentExerciseFigureInputSchema)
|
|
2098
|
-
}).superRefine((input, ctx) => {
|
|
2099
|
-
if (input.mode === "append" && input.figures.length === 0) {
|
|
2100
|
-
ctx.addIssue({
|
|
2101
|
-
code: z3.ZodIssueCode.custom,
|
|
2102
|
-
message: "append mode requires at least one figure.",
|
|
2103
|
-
path: ["figures"]
|
|
2104
|
-
});
|
|
2105
|
-
}
|
|
2106
|
-
if (input.mode === "replace_type" && !input.figureType) {
|
|
2107
|
-
ctx.addIssue({
|
|
2108
|
-
code: z3.ZodIssueCode.custom,
|
|
2109
|
-
message: "replace_type mode requires figureType.",
|
|
2110
|
-
path: ["figureType"]
|
|
2111
|
-
});
|
|
2112
|
-
}
|
|
2113
|
-
if (input.mode !== "replace_type" && input.figureType) {
|
|
2114
|
-
ctx.addIssue({
|
|
2115
|
-
code: z3.ZodIssueCode.custom,
|
|
2116
|
-
message: "figureType is only supported for replace_type mode.",
|
|
2117
|
-
path: ["figureType"]
|
|
2118
|
-
});
|
|
2119
|
-
}
|
|
2120
|
-
if (input.mode === "replace_type" && input.figureType) {
|
|
2121
|
-
input.figures.forEach((figure, index) => {
|
|
2122
|
-
if (figure.type !== input.figureType) {
|
|
2123
|
-
ctx.addIssue({
|
|
2124
|
-
code: z3.ZodIssueCode.custom,
|
|
2125
|
-
message: "Replacement figures must match figureType.",
|
|
2126
|
-
path: ["figures", index, "type"]
|
|
2127
|
-
});
|
|
2128
|
-
}
|
|
2129
|
-
});
|
|
2130
|
-
}
|
|
2131
|
-
});
|
|
2132
|
-
var attachExerciseFiguresAgentOutputSchema = agentWriteReceiptOutputSchema;
|
|
2133
2137
|
var exercisePatchMetadataSchema = strictObject({
|
|
2134
2138
|
sourceUrl: patchNullableStringSchema,
|
|
2135
2139
|
solutionUrl: patchNullableStringSchema
|
|
@@ -2363,12 +2367,15 @@ var mcpPublicErrorCodes = [
|
|
|
2363
2367
|
"storage_upload_failed",
|
|
2364
2368
|
"unsupported_image",
|
|
2365
2369
|
"validation_failed",
|
|
2370
|
+
"organization_selection_required",
|
|
2371
|
+
"organization_access_denied",
|
|
2366
2372
|
"internal_error"
|
|
2367
2373
|
];
|
|
2374
|
+
var mcpPublicErrorCodeSchema = z5.enum(mcpPublicErrorCodes);
|
|
2368
2375
|
var mcpToolErrorOutputSchema = strictObject2({
|
|
2369
2376
|
isError: z5.literal(true),
|
|
2370
2377
|
error: strictObject2({
|
|
2371
|
-
code:
|
|
2378
|
+
code: mcpPublicErrorCodeSchema,
|
|
2372
2379
|
message: z5.string().trim().min(1),
|
|
2373
2380
|
agentErrorDetails: agentErrorDetailsSchema.optional()
|
|
2374
2381
|
})
|
|
@@ -2416,7 +2423,7 @@ var userSchema = strictObject2({
|
|
|
2416
2423
|
email: z5.string().email().nullable(),
|
|
2417
2424
|
name: z5.string().nullable()
|
|
2418
2425
|
});
|
|
2419
|
-
var
|
|
2426
|
+
var mcpOrganizationSchema = strictObject2({
|
|
2420
2427
|
id: z5.uuid(),
|
|
2421
2428
|
name: z5.string(),
|
|
2422
2429
|
mcpPermission: z5.enum(mcpOAuthGrantPermissions).nullable().optional(),
|
|
@@ -2549,14 +2556,31 @@ var chalksurfMcpScopes = {
|
|
|
2549
2556
|
var getAuthStatusInputSchema = strictObject2({});
|
|
2550
2557
|
var getAuthStatusOutputSchema = strictObject2({
|
|
2551
2558
|
authenticated: z5.literal(true),
|
|
2559
|
+
organizations: z5.array(mcpOrganizationSchema),
|
|
2552
2560
|
selectedOrganizationId: z5.uuid().nullable(),
|
|
2553
2561
|
user: userSchema
|
|
2554
2562
|
});
|
|
2555
2563
|
var listOrganizationsInputSchema = strictObject2({});
|
|
2556
2564
|
var listOrganizationsOutputSchema = strictObject2({
|
|
2557
|
-
organizations: z5.array(
|
|
2565
|
+
organizations: z5.array(mcpOrganizationSchema),
|
|
2558
2566
|
selectedOrganizationId: z5.uuid().nullable()
|
|
2559
2567
|
});
|
|
2568
|
+
var mcpOrganizationRecoveryOutputSchema = strictObject2({
|
|
2569
|
+
isError: z5.literal(true),
|
|
2570
|
+
error: strictObject2({
|
|
2571
|
+
code: z5.enum(["organization_selection_required", "organization_access_denied"]),
|
|
2572
|
+
message: z5.string().trim().min(1)
|
|
2573
|
+
}),
|
|
2574
|
+
organizations: z5.array(
|
|
2575
|
+
strictObject2({
|
|
2576
|
+
id: z5.uuid(),
|
|
2577
|
+
name: z5.string(),
|
|
2578
|
+
permission: z5.enum(mcpOAuthGrantPermissions),
|
|
2579
|
+
role: z5.enum(["owner", "editor", "viewer"]),
|
|
2580
|
+
type: z5.enum(["personal", "team"])
|
|
2581
|
+
})
|
|
2582
|
+
)
|
|
2583
|
+
});
|
|
2560
2584
|
var searchExercisesInputSchema = strictObject2({
|
|
2561
2585
|
organizationId: organizationIdSchema,
|
|
2562
2586
|
age: z5.number().int().nullish(),
|
|
@@ -2587,9 +2611,7 @@ var getExerciseUsageInputSchema = getExerciseUsageAgentInputSchema.extend({
|
|
|
2587
2611
|
organizationId: organizationIdSchema
|
|
2588
2612
|
});
|
|
2589
2613
|
var getExerciseUsageOutputSchema = getExerciseUsageAgentOutputSchema;
|
|
2590
|
-
var listExerciseLabelsInputSchema = listExerciseLabelsAgentInputSchema
|
|
2591
|
-
organizationId: organizationIdSchema
|
|
2592
|
-
});
|
|
2614
|
+
var listExerciseLabelsInputSchema = listExerciseLabelsAgentInputSchema;
|
|
2593
2615
|
var listExerciseLabelsOutputSchema = listExerciseLabelsAgentOutputSchema;
|
|
2594
2616
|
var copyExerciseInputSchema = copyExerciseAgentInputSchema.extend({
|
|
2595
2617
|
organizationId: organizationIdSchema
|
|
@@ -2662,13 +2684,15 @@ var searchSheetsOutputSchema = strictObject2({
|
|
|
2662
2684
|
),
|
|
2663
2685
|
totalCount: z5.number().int().min(0)
|
|
2664
2686
|
});
|
|
2665
|
-
var
|
|
2687
|
+
var listSheetsInputSchema = listSheetsAgentInputSchema.extend({
|
|
2666
2688
|
organizationId: organizationIdSchema
|
|
2667
2689
|
});
|
|
2668
|
-
var
|
|
2669
|
-
var
|
|
2690
|
+
var listSheetsOutputSchema = listSheetsAgentOutputSchema;
|
|
2691
|
+
var getSheetInputSchema = getSheetAgentInputSchema.extend({
|
|
2670
2692
|
organizationId: organizationIdSchema
|
|
2671
2693
|
});
|
|
2694
|
+
var getSheetOutputSchema = getSheetAgentOutputSchema;
|
|
2695
|
+
var listSheetSeriesInputSchema = listSheetSeriesAgentInputSchema;
|
|
2672
2696
|
var listSheetSeriesOutputSchema = listSheetSeriesAgentOutputSchema;
|
|
2673
2697
|
var listSheetVersionsInputSchema = listSheetVersionsAgentInputSchema.extend({
|
|
2674
2698
|
organizationId: organizationIdSchema
|
|
@@ -2738,9 +2762,7 @@ var renameFolderInputSchema = renameFolderAgentInputSchema.extend({
|
|
|
2738
2762
|
organizationId: organizationIdSchema
|
|
2739
2763
|
});
|
|
2740
2764
|
var renameFolderOutputSchema = renameFolderAgentOutputSchema;
|
|
2741
|
-
var validateLatexSnippetsInputSchema = validateLatexSnippetsAgentInputSchema
|
|
2742
|
-
organizationId: organizationIdSchema
|
|
2743
|
-
});
|
|
2765
|
+
var validateLatexSnippetsInputSchema = validateLatexSnippetsAgentInputSchema;
|
|
2744
2766
|
var validateLatexSnippetsOutputSchema = validateLatexSnippetsAgentOutputSchema;
|
|
2745
2767
|
var importSheetInputSchema = strictObject2({
|
|
2746
2768
|
organizationId: organizationIdSchema,
|
|
@@ -3497,6 +3519,7 @@ var uploadExerciseFigureInputSchema = uploadExerciseFigureAgentInputSchema.exten
|
|
|
3497
3519
|
});
|
|
3498
3520
|
var uploadExerciseFigureMcpToolInputSchema = strictObject2({
|
|
3499
3521
|
organizationId: organizationIdSchema,
|
|
3522
|
+
exerciseId: z5.uuid(),
|
|
3500
3523
|
figureType: z5.enum(exerciseFigureTypes),
|
|
3501
3524
|
...chatGptFigureUploadFileParamInputShape,
|
|
3502
3525
|
source: strictObject2({
|
|
@@ -3513,10 +3536,6 @@ var uploadExerciseFigureMcpToolInputSchema = strictObject2({
|
|
|
3513
3536
|
allowNeedsRevision: z5.boolean().optional()
|
|
3514
3537
|
}).passthrough();
|
|
3515
3538
|
var uploadExerciseFigureOutputSchema = uploadExerciseFigureAgentOutputSchema;
|
|
3516
|
-
var attachExerciseFiguresInputSchema = attachExerciseFiguresAgentInputSchema.extend({
|
|
3517
|
-
organizationId: organizationIdSchema
|
|
3518
|
-
});
|
|
3519
|
-
var attachExerciseFiguresOutputSchema = attachExerciseFiguresAgentOutputSchema;
|
|
3520
3539
|
var chalksurfMcpToolCapabilities = {
|
|
3521
3540
|
get_auth_status: {
|
|
3522
3541
|
name: "get_auth_status",
|
|
@@ -3672,6 +3691,16 @@ var chalksurfMcpToolCapabilities = {
|
|
|
3672
3691
|
requiredPermission: "read",
|
|
3673
3692
|
security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
|
|
3674
3693
|
},
|
|
3694
|
+
list_sheets: {
|
|
3695
|
+
name: "list_sheets",
|
|
3696
|
+
title: "List sheets",
|
|
3697
|
+
description: "Use this to list exercise sheets owned by a ChalkSurf organization and inspect their folder paths and series assignments.",
|
|
3698
|
+
inputSchema: listSheetsInputSchema,
|
|
3699
|
+
outputSchema: listSheetsOutputSchema,
|
|
3700
|
+
annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
3701
|
+
requiredPermission: "read",
|
|
3702
|
+
security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
|
|
3703
|
+
},
|
|
3675
3704
|
get_sheet: {
|
|
3676
3705
|
name: "get_sheet",
|
|
3677
3706
|
title: "Get sheet",
|
|
@@ -3950,7 +3979,7 @@ var chalksurfMcpToolCapabilities = {
|
|
|
3950
3979
|
upload_exercise_figure: {
|
|
3951
3980
|
name: "upload_exercise_figure",
|
|
3952
3981
|
title: "Upload exercise figure",
|
|
3953
|
-
description: "Use this to attach one reviewed image, MCP file, HTTPS image, base64 image, or rendered figure to an exercise by providing exerciseId, figureType, source, and width.
|
|
3982
|
+
description: "Use this to attach one reviewed image, MCP file, HTTPS image, base64 image, or rendered figure to an exercise by providing exerciseId, figureType, source, and width.",
|
|
3954
3983
|
inputSchema: uploadExerciseFigureInputSchema,
|
|
3955
3984
|
mcpInputSchema: uploadExerciseFigureMcpToolInputSchema,
|
|
3956
3985
|
outputSchema: uploadExerciseFigureOutputSchema,
|
|
@@ -3958,16 +3987,6 @@ var chalksurfMcpToolCapabilities = {
|
|
|
3958
3987
|
requiredPermission: "write",
|
|
3959
3988
|
security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] },
|
|
3960
3989
|
fileParams: chatGptFigureUploadFileParamNames
|
|
3961
|
-
},
|
|
3962
|
-
attach_exercise_figures: {
|
|
3963
|
-
name: "attach_exercise_figures",
|
|
3964
|
-
title: "Attach exercise figures",
|
|
3965
|
-
description: "Deprecated compatibility tool. Use upload_exercise_figure with exerciseId for new figures; use this only to attach already-uploaded compatibility URLs or replace existing figure lists.",
|
|
3966
|
-
inputSchema: attachExerciseFiguresInputSchema,
|
|
3967
|
-
outputSchema: attachExerciseFiguresOutputSchema,
|
|
3968
|
-
annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
3969
|
-
requiredPermission: "write",
|
|
3970
|
-
security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
|
|
3971
3990
|
}
|
|
3972
3991
|
};
|
|
3973
3992
|
|
|
@@ -8719,29 +8738,106 @@ ${formatOrganizationSummary(result.organization)}`,
|
|
|
8719
8738
|
};
|
|
8720
8739
|
|
|
8721
8740
|
// src/commands/exercise.ts
|
|
8722
|
-
import { readFile as
|
|
8723
|
-
import { basename as basename2, extname as extname2, isAbsolute as isAbsolute2, resolve as
|
|
8741
|
+
import { readFile as readFile4 } from "node:fs/promises";
|
|
8742
|
+
import { basename as basename2, extname as extname2, isAbsolute as isAbsolute2, resolve as resolve5 } from "node:path";
|
|
8724
8743
|
import { z as z13 } from "zod";
|
|
8725
8744
|
|
|
8726
|
-
// src/lib/
|
|
8727
|
-
|
|
8728
|
-
|
|
8745
|
+
// src/lib/json-input.ts
|
|
8746
|
+
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
8747
|
+
import { resolve } from "node:path";
|
|
8748
|
+
var isInteractiveStdin2 = (stdin) => {
|
|
8749
|
+
return stdin.isTTY === true;
|
|
8729
8750
|
};
|
|
8730
|
-
var
|
|
8731
|
-
|
|
8732
|
-
|
|
8751
|
+
var readTextFromStdin = async (stdin) => {
|
|
8752
|
+
const chunks = [];
|
|
8753
|
+
for await (const chunk of stdin) {
|
|
8754
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
8733
8755
|
}
|
|
8756
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
8757
|
+
};
|
|
8758
|
+
var parseJsonObjectText = ({
|
|
8759
|
+
invalidJsonMessage,
|
|
8760
|
+
nonObjectMessage,
|
|
8761
|
+
text
|
|
8762
|
+
}) => {
|
|
8734
8763
|
let parsedValue;
|
|
8735
8764
|
try {
|
|
8736
|
-
parsedValue = JSON.parse(
|
|
8765
|
+
parsedValue = JSON.parse(text);
|
|
8737
8766
|
} catch {
|
|
8738
|
-
throw new CliCommandError(
|
|
8767
|
+
throw new CliCommandError(invalidJsonMessage, 2);
|
|
8739
8768
|
}
|
|
8740
8769
|
if (typeof parsedValue !== "object" || parsedValue === null || Array.isArray(parsedValue)) {
|
|
8741
|
-
throw new CliCommandError(
|
|
8770
|
+
throw new CliCommandError(nonObjectMessage, 2);
|
|
8742
8771
|
}
|
|
8743
8772
|
return parsedValue;
|
|
8744
8773
|
};
|
|
8774
|
+
var loadJsonObjectInput = async ({
|
|
8775
|
+
cwd,
|
|
8776
|
+
inputJson,
|
|
8777
|
+
inputPath,
|
|
8778
|
+
stdin
|
|
8779
|
+
}) => {
|
|
8780
|
+
if (inputPath !== void 0 && inputJson !== void 0) {
|
|
8781
|
+
throw new CliCommandError("Pass --input or --input-json, not both.", 2);
|
|
8782
|
+
}
|
|
8783
|
+
if (inputPath === void 0 && inputJson === void 0) {
|
|
8784
|
+
throw new CliCommandError("One of --input or --input-json is required.", 2);
|
|
8785
|
+
}
|
|
8786
|
+
if (inputJson !== void 0) {
|
|
8787
|
+
return parseJsonObjectText({
|
|
8788
|
+
invalidJsonMessage: "--input-json must be valid JSON.",
|
|
8789
|
+
nonObjectMessage: "--input-json must be a JSON object.",
|
|
8790
|
+
text: inputJson
|
|
8791
|
+
});
|
|
8792
|
+
}
|
|
8793
|
+
if (inputPath === "-") {
|
|
8794
|
+
if (isInteractiveStdin2(stdin)) {
|
|
8795
|
+
throw new CliCommandError('No JSON was piped on stdin. Pipe JSON into "--input -".', 2);
|
|
8796
|
+
}
|
|
8797
|
+
const inputText = await readTextFromStdin(stdin);
|
|
8798
|
+
if (inputText.trim().length === 0) {
|
|
8799
|
+
throw new CliCommandError('No JSON was piped on stdin. Pipe JSON into "--input -".', 2);
|
|
8800
|
+
}
|
|
8801
|
+
return parseJsonObjectText({
|
|
8802
|
+
invalidJsonMessage: "Standard input must contain valid JSON.",
|
|
8803
|
+
nonObjectMessage: "Standard input must contain a JSON object.",
|
|
8804
|
+
text: inputText
|
|
8805
|
+
});
|
|
8806
|
+
}
|
|
8807
|
+
const resolvedInputPath = resolve(cwd, inputPath);
|
|
8808
|
+
let inputStats;
|
|
8809
|
+
try {
|
|
8810
|
+
inputStats = await stat(resolvedInputPath);
|
|
8811
|
+
} catch (error) {
|
|
8812
|
+
if (error.code === "ENOENT") {
|
|
8813
|
+
throw new CliCommandError(`Input file "${inputPath}" does not exist.`, 2);
|
|
8814
|
+
}
|
|
8815
|
+
throw error;
|
|
8816
|
+
}
|
|
8817
|
+
if (!inputStats.isFile()) {
|
|
8818
|
+
throw new CliCommandError(`Input path "${inputPath}" is not a file.`, 2);
|
|
8819
|
+
}
|
|
8820
|
+
return parseJsonObjectText({
|
|
8821
|
+
invalidJsonMessage: `Input file "${inputPath}" must contain valid JSON.`,
|
|
8822
|
+
nonObjectMessage: `Input file "${inputPath}" must contain a JSON object.`,
|
|
8823
|
+
text: await readFile2(resolvedInputPath, "utf8")
|
|
8824
|
+
});
|
|
8825
|
+
};
|
|
8826
|
+
|
|
8827
|
+
// src/lib/agent-patch.ts
|
|
8828
|
+
var formatZodIssues = (issues) => {
|
|
8829
|
+
return issues.map((issue) => `${issue.path.join(".") || "input"}: ${issue.message}`).join("; ");
|
|
8830
|
+
};
|
|
8831
|
+
var parseJsonObjectFlag = ({ label, value }) => {
|
|
8832
|
+
if (value === void 0) {
|
|
8833
|
+
throw new CliCommandError(`${label} is required.`, 2);
|
|
8834
|
+
}
|
|
8835
|
+
return parseJsonObjectText({
|
|
8836
|
+
invalidJsonMessage: `${label} must be valid JSON.`,
|
|
8837
|
+
nonObjectMessage: `${label} must be a JSON object.`,
|
|
8838
|
+
text: value
|
|
8839
|
+
});
|
|
8840
|
+
};
|
|
8745
8841
|
var parseUpdateExerciseAgentInput = (input) => {
|
|
8746
8842
|
const parsedInput = updateExerciseAgentInputSchema.safeParse(input);
|
|
8747
8843
|
if (!parsedInput.success) {
|
|
@@ -8865,8 +8961,8 @@ var toApiOwnership = (ownership) => {
|
|
|
8865
8961
|
|
|
8866
8962
|
// src/lib/import-files.ts
|
|
8867
8963
|
import { openAsBlob } from "node:fs";
|
|
8868
|
-
import { stat } from "node:fs/promises";
|
|
8869
|
-
import { extname, resolve } from "node:path";
|
|
8964
|
+
import { stat as stat2 } from "node:fs/promises";
|
|
8965
|
+
import { extname, resolve as resolve2 } from "node:path";
|
|
8870
8966
|
var guessMimeType = (fileName) => {
|
|
8871
8967
|
return mimeTypesByExtension[extname(fileName).toLowerCase()] ?? "application/octet-stream";
|
|
8872
8968
|
};
|
|
@@ -8937,7 +9033,7 @@ var buildFileImportCommandSources = async ({
|
|
|
8937
9033
|
continue;
|
|
8938
9034
|
}
|
|
8939
9035
|
try {
|
|
8940
|
-
const pathStats = await
|
|
9036
|
+
const pathStats = await stat2(resolve2(cwd, rawSource));
|
|
8941
9037
|
if (pathStats.isDirectory()) {
|
|
8942
9038
|
if (relativePath) {
|
|
8943
9039
|
throw new CliCommandError("--relative-path cannot be used with directory sources.", 2);
|
|
@@ -9065,8 +9161,8 @@ var formatCliImportTranslationJobs = (translationJobs) => {
|
|
|
9065
9161
|
};
|
|
9066
9162
|
|
|
9067
9163
|
// src/lib/manifest.ts
|
|
9068
|
-
import { readFile as
|
|
9069
|
-
import { resolve as
|
|
9164
|
+
import { readFile as readFile3, stat as stat3 } from "node:fs/promises";
|
|
9165
|
+
import { resolve as resolve3 } from "node:path";
|
|
9070
9166
|
import { z as z12 } from "zod";
|
|
9071
9167
|
|
|
9072
9168
|
// src/lib/translation-languages.ts
|
|
@@ -9230,10 +9326,10 @@ var assertUniqueSourceIds = (sources) => {
|
|
|
9230
9326
|
seenSourceIds.add(source.sourceId);
|
|
9231
9327
|
}
|
|
9232
9328
|
};
|
|
9233
|
-
var
|
|
9329
|
+
var isInteractiveStdin3 = (stdin) => {
|
|
9234
9330
|
return stdin.isTTY === true;
|
|
9235
9331
|
};
|
|
9236
|
-
var
|
|
9332
|
+
var readTextFromStdin2 = async (stdin) => {
|
|
9237
9333
|
let text = "";
|
|
9238
9334
|
for await (const chunk of stdin) {
|
|
9239
9335
|
text += typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8");
|
|
@@ -9400,15 +9496,15 @@ var loadManifest = async ({
|
|
|
9400
9496
|
stdin
|
|
9401
9497
|
}) => {
|
|
9402
9498
|
if (manifestPath === "-") {
|
|
9403
|
-
if (
|
|
9499
|
+
if (isInteractiveStdin3(stdin)) {
|
|
9404
9500
|
throw new CliCommandError('No manifest was piped on stdin. Pipe JSON into "--manifest -".', 2);
|
|
9405
9501
|
}
|
|
9406
|
-
return parseManifest(await
|
|
9502
|
+
return parseManifest(await readTextFromStdin2(stdin));
|
|
9407
9503
|
}
|
|
9408
|
-
const resolvedManifestPath =
|
|
9504
|
+
const resolvedManifestPath = resolve3(cwd, manifestPath);
|
|
9409
9505
|
let fileStats;
|
|
9410
9506
|
try {
|
|
9411
|
-
fileStats = await
|
|
9507
|
+
fileStats = await stat3(resolvedManifestPath);
|
|
9412
9508
|
} catch (error) {
|
|
9413
9509
|
if (error.code === "ENOENT") {
|
|
9414
9510
|
throw new CliCommandError(`Manifest file "${manifestPath}" does not exist.`, 2);
|
|
@@ -9418,7 +9514,7 @@ var loadManifest = async ({
|
|
|
9418
9514
|
if (!fileStats.isFile()) {
|
|
9419
9515
|
throw new CliCommandError(`Manifest path "${manifestPath}" is not a file.`, 2);
|
|
9420
9516
|
}
|
|
9421
|
-
return parseManifest(await
|
|
9517
|
+
return parseManifest(await readFile3(resolvedManifestPath, "utf8"));
|
|
9422
9518
|
};
|
|
9423
9519
|
var loadExerciseImportManifest = async ({
|
|
9424
9520
|
cwd,
|
|
@@ -9471,9 +9567,9 @@ var loadSheetImportManifest = async ({
|
|
|
9471
9567
|
|
|
9472
9568
|
// src/lib/source-resolver.ts
|
|
9473
9569
|
import { createWriteStream } from "node:fs";
|
|
9474
|
-
import { mkdtemp, open, readdir, rm as rm2, stat as
|
|
9570
|
+
import { mkdtemp, open, readdir, rm as rm2, stat as stat4 } from "node:fs/promises";
|
|
9475
9571
|
import { tmpdir } from "node:os";
|
|
9476
|
-
import { basename, isAbsolute, relative, resolve as
|
|
9572
|
+
import { basename, isAbsolute, relative, resolve as resolve4 } from "node:path";
|
|
9477
9573
|
import { Readable } from "node:stream";
|
|
9478
9574
|
import { pipeline } from "node:stream/promises";
|
|
9479
9575
|
import pLimit from "p-limit";
|
|
@@ -9498,7 +9594,7 @@ var normalizeRelativePath = (relativePath) => {
|
|
|
9498
9594
|
var ensureExistingFile = async (filePath, label) => {
|
|
9499
9595
|
let fileStats;
|
|
9500
9596
|
try {
|
|
9501
|
-
fileStats = await
|
|
9597
|
+
fileStats = await stat4(filePath);
|
|
9502
9598
|
} catch (error) {
|
|
9503
9599
|
if (error.code === "ENOENT") {
|
|
9504
9600
|
throw createSourceResolutionError(`${label} "${filePath}" does not exist.`);
|
|
@@ -9512,7 +9608,7 @@ var ensureExistingFile = async (filePath, label) => {
|
|
|
9512
9608
|
var ensureExistingDirectory = async (directoryPath, label) => {
|
|
9513
9609
|
let directoryStats;
|
|
9514
9610
|
try {
|
|
9515
|
-
directoryStats = await
|
|
9611
|
+
directoryStats = await stat4(directoryPath);
|
|
9516
9612
|
} catch (error) {
|
|
9517
9613
|
if (error.code === "ENOENT") {
|
|
9518
9614
|
throw createSourceResolutionError(`${label} "${directoryPath}" does not exist.`);
|
|
@@ -9535,7 +9631,7 @@ var collectFilesRecursively = async (directoryPath) => {
|
|
|
9535
9631
|
const sortedEntries = directoryEntries.sort((leftEntry, rightEntry) => leftEntry.name.localeCompare(rightEntry.name));
|
|
9536
9632
|
const filePaths = [];
|
|
9537
9633
|
for (const directoryEntry of sortedEntries) {
|
|
9538
|
-
const entryPath =
|
|
9634
|
+
const entryPath = resolve4(directoryPath, directoryEntry.name);
|
|
9539
9635
|
if (directoryEntry.isDirectory()) {
|
|
9540
9636
|
filePaths.push(...await collectFilesRecursively(entryPath));
|
|
9541
9637
|
continue;
|
|
@@ -9596,7 +9692,7 @@ var resolveLocalFileSource = async ({
|
|
|
9596
9692
|
cwd,
|
|
9597
9693
|
sourceInputIndex
|
|
9598
9694
|
}) => {
|
|
9599
|
-
const resolvedPath =
|
|
9695
|
+
const resolvedPath = resolve4(cwd, source.path);
|
|
9600
9696
|
await ensureExistingFile(resolvedPath, "Local source");
|
|
9601
9697
|
const relativePath = normalizeRelativePath(source.relativePath ?? basename(resolvedPath));
|
|
9602
9698
|
return [
|
|
@@ -9616,8 +9712,8 @@ var resolveDirectorySource = async ({
|
|
|
9616
9712
|
cwd,
|
|
9617
9713
|
sourceInputIndex
|
|
9618
9714
|
}) => {
|
|
9619
|
-
const resolvedDirectoryPath =
|
|
9620
|
-
const resolvedRelativeRoot =
|
|
9715
|
+
const resolvedDirectoryPath = resolve4(cwd, source.path);
|
|
9716
|
+
const resolvedRelativeRoot = resolve4(cwd, source.relativeRoot ?? source.path);
|
|
9621
9717
|
await ensureExistingDirectory(resolvedDirectoryPath, "Directory source");
|
|
9622
9718
|
await ensureExistingDirectory(resolvedRelativeRoot, "Directory relativeRoot");
|
|
9623
9719
|
if (!isContainedWithin({ childPath: resolvedDirectoryPath, parentPath: resolvedRelativeRoot })) {
|
|
@@ -9656,8 +9752,8 @@ var resolveUrlSource = async ({
|
|
|
9656
9752
|
throw createSourceResolutionError(`URL source "${source.url}" must use http or https.`);
|
|
9657
9753
|
}
|
|
9658
9754
|
const relativePath = normalizeRelativePath(source.relativePath ?? deriveRelativePathFromUrl(parsedUrl));
|
|
9659
|
-
const downloadDirectoryPath = await mkdtemp(
|
|
9660
|
-
const downloadedFilePath =
|
|
9755
|
+
const downloadDirectoryPath = await mkdtemp(resolve4(tmpdir(), "chalksurf-cli-source-"));
|
|
9756
|
+
const downloadedFilePath = resolve4(downloadDirectoryPath, basename(relativePath));
|
|
9661
9757
|
try {
|
|
9662
9758
|
const response = await fetch(source.url);
|
|
9663
9759
|
if (!response.ok) {
|
|
@@ -9979,9 +10075,6 @@ var formatUploadExerciseFigureOutput = ({ figure, receipt, review }) => [
|
|
|
9979
10075
|
`figure: ${figure.type} ${figure.url}`,
|
|
9980
10076
|
`image: ${review.pixelWidth ?? "?"}x${review.pixelHeight ?? "?"} ${review.byteLength} bytes`
|
|
9981
10077
|
].join("\n");
|
|
9982
|
-
var formatAttachExerciseFiguresOutput = ({ receipt }) => {
|
|
9983
|
-
return formatAgentWriteReceiptOutput({ receipt });
|
|
9984
|
-
};
|
|
9985
10078
|
var getExerciseTranslationJobIds = ({ jobs }) => jobs.map((job) => job.jobId);
|
|
9986
10079
|
var formatExerciseTranslationOutput = ({ jobs }) => {
|
|
9987
10080
|
if (jobs.length === 0) {
|
|
@@ -9998,16 +10091,6 @@ var resolveVisibilityFlag = ({ privateFlag, publicFlag }) => {
|
|
|
9998
10091
|
}
|
|
9999
10092
|
return Boolean(publicFlag);
|
|
10000
10093
|
};
|
|
10001
|
-
var parseJsonFlagValue = ({ label, value }) => {
|
|
10002
|
-
if (value === void 0) {
|
|
10003
|
-
throw new CliCommandError(`${label} is required.`, 2);
|
|
10004
|
-
}
|
|
10005
|
-
try {
|
|
10006
|
-
return JSON.parse(value);
|
|
10007
|
-
} catch {
|
|
10008
|
-
throw new CliCommandError(`${label} must be valid JSON.`, 2);
|
|
10009
|
-
}
|
|
10010
|
-
};
|
|
10011
10094
|
var resolveExerciseFigureType = ({
|
|
10012
10095
|
label,
|
|
10013
10096
|
required,
|
|
@@ -10024,13 +10107,6 @@ var resolveExerciseFigureType = ({
|
|
|
10024
10107
|
}
|
|
10025
10108
|
return value;
|
|
10026
10109
|
};
|
|
10027
|
-
var resolveAttachFigureMode = (value) => {
|
|
10028
|
-
const mode = value ?? "append";
|
|
10029
|
-
if (mode !== "append" && mode !== "replace_type" && mode !== "replace_all") {
|
|
10030
|
-
throw new CliCommandError("--mode must be one of: append, replace_type, replace_all.", 2);
|
|
10031
|
-
}
|
|
10032
|
-
return mode;
|
|
10033
|
-
};
|
|
10034
10110
|
var parseUploadExerciseFigureInput = (input) => {
|
|
10035
10111
|
const parsedInput = uploadExerciseFigureAgentInputSchema.safeParse(input);
|
|
10036
10112
|
if (!parsedInput.success) {
|
|
@@ -10038,22 +10114,7 @@ var parseUploadExerciseFigureInput = (input) => {
|
|
|
10038
10114
|
}
|
|
10039
10115
|
return parsedInput.data;
|
|
10040
10116
|
};
|
|
10041
|
-
var
|
|
10042
|
-
const parsedInput = attachExerciseFiguresAgentInputSchema.safeParse(input);
|
|
10043
|
-
if (!parsedInput.success) {
|
|
10044
|
-
throw new CliCommandError(`Invalid figure attach input: ${formatZodIssues(parsedInput.error.issues)}`, 2);
|
|
10045
|
-
}
|
|
10046
|
-
return parsedInput.data;
|
|
10047
|
-
};
|
|
10048
|
-
var parseFigureJsonList = (value) => {
|
|
10049
|
-
const parsedValue = parseJsonFlagValue({ label: "--figure-json", value });
|
|
10050
|
-
const figures = Array.isArray(parsedValue) ? parsedValue : [parsedValue];
|
|
10051
|
-
if (!figures.every((figure) => typeof figure === "object" && figure !== null && !Array.isArray(figure))) {
|
|
10052
|
-
throw new CliCommandError("--figure-json must be a figure object or an array of figure objects.", 2);
|
|
10053
|
-
}
|
|
10054
|
-
return figures;
|
|
10055
|
-
};
|
|
10056
|
-
var resolveLocalPath = ({ cwd, path }) => isAbsolute2(path) ? path : resolve4(cwd, path);
|
|
10117
|
+
var resolveLocalPath = ({ cwd, path }) => isAbsolute2(path) ? path : resolve5(cwd, path);
|
|
10057
10118
|
var getMimeTypeFromFileName = (fileName) => mimeTypesByExtension[extname2(fileName).toLowerCase()] ?? "";
|
|
10058
10119
|
var buildLocalFigureUploadFormData = async ({
|
|
10059
10120
|
context,
|
|
@@ -10062,7 +10123,7 @@ var buildLocalFigureUploadFormData = async ({
|
|
|
10062
10123
|
}) => {
|
|
10063
10124
|
const resolvedSourcePath = resolveLocalPath({ cwd: context.cwd, path: source });
|
|
10064
10125
|
const fileName = input.originalFileName ?? basename2(resolvedSourcePath);
|
|
10065
|
-
const fileBuffer = await
|
|
10126
|
+
const fileBuffer = await readFile4(resolvedSourcePath);
|
|
10066
10127
|
const file = new File([new Uint8Array(fileBuffer)], fileName, { type: getMimeTypeFromFileName(fileName) });
|
|
10067
10128
|
const formData = new FormData();
|
|
10068
10129
|
formData.set("payload", JSON.stringify(input));
|
|
@@ -10442,11 +10503,14 @@ var registerExerciseCommands = (exerciseYargs, context) => {
|
|
|
10442
10503
|
}
|
|
10443
10504
|
).command(
|
|
10444
10505
|
"figure <subcommand>",
|
|
10445
|
-
"Exercise figure upload
|
|
10506
|
+
"Exercise figure upload commands",
|
|
10446
10507
|
(figureYargs) => figureYargs.command(
|
|
10447
|
-
"upload [source]",
|
|
10448
|
-
"Upload a reviewed figure image to exercise
|
|
10449
|
-
(uploadYargs) => uploadYargs.positional("
|
|
10508
|
+
"upload <exerciseId> [source]",
|
|
10509
|
+
"Upload and attach a reviewed figure image to an exercise",
|
|
10510
|
+
(uploadYargs) => uploadYargs.positional("exerciseId", {
|
|
10511
|
+
type: "string",
|
|
10512
|
+
describe: "Exercise ID to attach the figure to"
|
|
10513
|
+
}).positional("source", {
|
|
10450
10514
|
type: "string",
|
|
10451
10515
|
describe: "Local image file path. Omit when using --input-json for HTTPS/base64/rendered sources."
|
|
10452
10516
|
}).option("input-json", {
|
|
@@ -10467,15 +10531,21 @@ var registerExerciseCommands = (exerciseYargs, context) => {
|
|
|
10467
10531
|
default: false,
|
|
10468
10532
|
describe: "Allow uploading a rendered figure whose quality status is needs_revision"
|
|
10469
10533
|
}).example(
|
|
10470
|
-
"chalksurf exercise figure upload ./triangle.png --figure-type text --json",
|
|
10534
|
+
"chalksurf exercise figure upload 00000000-0000-4000-8000-000000000001 ./triangle.png --figure-type text --json",
|
|
10471
10535
|
"Upload a local figure image"
|
|
10472
10536
|
).example(
|
|
10473
|
-
`chalksurf exercise figure upload --input-json '{"figureType":"text","source":{"kind":"https_url","url":"https://example.com/figure.png"}}' --json`,
|
|
10537
|
+
`chalksurf exercise figure upload 00000000-0000-4000-8000-000000000001 --input-json '{"exerciseId":"00000000-0000-4000-8000-000000000001","figureType":"text","source":{"kind":"https_url","url":"https://example.com/figure.png"}}' --json`,
|
|
10474
10538
|
"Upload a figure from an HTTPS image URL"
|
|
10475
10539
|
),
|
|
10476
10540
|
async (argv) => {
|
|
10477
10541
|
const source = argv.source;
|
|
10542
|
+
const exerciseId = resolveRequestedUuid({
|
|
10543
|
+
fallbackValue: argv.exerciseId,
|
|
10544
|
+
label: "exerciseId",
|
|
10545
|
+
required: true
|
|
10546
|
+
});
|
|
10478
10547
|
const input = argv.inputJson === void 0 ? parseUploadExerciseFigureInput({
|
|
10548
|
+
exerciseId,
|
|
10479
10549
|
figureType: resolveExerciseFigureType({
|
|
10480
10550
|
label: "--figure-type",
|
|
10481
10551
|
required: true,
|
|
@@ -10485,9 +10555,10 @@ var registerExerciseCommands = (exerciseYargs, context) => {
|
|
|
10485
10555
|
...argv.widthCm === void 0 ? {} : { widthInCm: argv.widthCm },
|
|
10486
10556
|
...argv.originalFileName === void 0 ? {} : { originalFileName: argv.originalFileName },
|
|
10487
10557
|
allowNeedsRevision: argv.allowNeedsRevision ?? false
|
|
10488
|
-
}) : parseUploadExerciseFigureInput(
|
|
10489
|
-
parseJsonObjectFlag({ label: "--input-json", value: argv.inputJson })
|
|
10490
|
-
|
|
10558
|
+
}) : parseUploadExerciseFigureInput({
|
|
10559
|
+
...parseJsonObjectFlag({ label: "--input-json", value: argv.inputJson }),
|
|
10560
|
+
exerciseId
|
|
10561
|
+
});
|
|
10491
10562
|
if (argv.inputJson === void 0 && !source) {
|
|
10492
10563
|
throw new CliCommandError("source is required unless --input-json is provided.", 2);
|
|
10493
10564
|
}
|
|
@@ -10527,91 +10598,6 @@ var registerExerciseCommands = (exerciseYargs, context) => {
|
|
|
10527
10598
|
}
|
|
10528
10599
|
);
|
|
10529
10600
|
}
|
|
10530
|
-
).command(
|
|
10531
|
-
"attach [exerciseId]",
|
|
10532
|
-
"Attach one or more uploaded figures to an exercise",
|
|
10533
|
-
(attachYargs) => attachYargs.positional("exerciseId", {
|
|
10534
|
-
type: "string",
|
|
10535
|
-
describe: "Exercise ID to update"
|
|
10536
|
-
}).option("expected-updated-at", {
|
|
10537
|
-
type: "string",
|
|
10538
|
-
demandOption: true,
|
|
10539
|
-
describe: "Expected current exercise updated_at ISO timestamp"
|
|
10540
|
-
}).option("figure-json", {
|
|
10541
|
-
type: "string",
|
|
10542
|
-
demandOption: true,
|
|
10543
|
-
describe: "Figure object or array of figure objects, usually from exercise figure upload output"
|
|
10544
|
-
}).option("mode", {
|
|
10545
|
-
type: "string",
|
|
10546
|
-
default: "append",
|
|
10547
|
-
choices: ["append", "replace_type", "replace_all"],
|
|
10548
|
-
describe: "How to merge figures into the exercise figure collection"
|
|
10549
|
-
}).option("figure-type", {
|
|
10550
|
-
type: "string",
|
|
10551
|
-
choices: [...exerciseFigureTypes],
|
|
10552
|
-
describe: "Required for --mode replace_type"
|
|
10553
|
-
}).option("target-sheet-id", {
|
|
10554
|
-
type: "string",
|
|
10555
|
-
describe: "Sheet ID whose variant workflow this update targets"
|
|
10556
|
-
}).option("allow-shared-exercise-update", {
|
|
10557
|
-
type: "boolean",
|
|
10558
|
-
default: false,
|
|
10559
|
-
describe: "Acknowledge updating an exercise used outside --target-sheet-id"
|
|
10560
|
-
}).example(
|
|
10561
|
-
`chalksurf exercise figure attach 00000000-0000-4000-8000-000000000001 --expected-updated-at 2026-01-01T00:00:00.000Z --figure-json '{"type":"text","url":"https://...","widthInCm":6}' --json`,
|
|
10562
|
-
"Append one uploaded figure to an exercise"
|
|
10563
|
-
),
|
|
10564
|
-
async (argv) => {
|
|
10565
|
-
const exerciseId = resolveRequestedUuid({
|
|
10566
|
-
fallbackValue: argv.exerciseId,
|
|
10567
|
-
label: "exerciseId",
|
|
10568
|
-
required: true
|
|
10569
|
-
});
|
|
10570
|
-
const targetSheetId = resolveRequestedUuid({
|
|
10571
|
-
flagValue: argv.targetSheetId,
|
|
10572
|
-
label: "--target-sheet-id"
|
|
10573
|
-
});
|
|
10574
|
-
const mode = resolveAttachFigureMode(argv.mode);
|
|
10575
|
-
const figureType = resolveExerciseFigureType({
|
|
10576
|
-
label: "--figure-type",
|
|
10577
|
-
required: mode === "replace_type",
|
|
10578
|
-
value: argv.figureType
|
|
10579
|
-
});
|
|
10580
|
-
const input = parseAttachExerciseFiguresInput({
|
|
10581
|
-
exerciseId,
|
|
10582
|
-
expectedUpdatedAt: argv.expectedUpdatedAt,
|
|
10583
|
-
...targetSheetId === void 0 ? {} : { targetSheetId },
|
|
10584
|
-
allowSharedExerciseUpdate: argv.allowSharedExerciseUpdate ?? false,
|
|
10585
|
-
mode,
|
|
10586
|
-
...figureType === void 0 ? {} : { figureType },
|
|
10587
|
-
figures: parseFigureJsonList(argv.figureJson)
|
|
10588
|
-
});
|
|
10589
|
-
const { apiClient, organizationId } = await createResolvedApiClient({
|
|
10590
|
-
context,
|
|
10591
|
-
baseUrlFlagValue: argv.baseUrl,
|
|
10592
|
-
organizationFlagValue: argv.organization,
|
|
10593
|
-
profileName: argv.profile
|
|
10594
|
-
});
|
|
10595
|
-
let result;
|
|
10596
|
-
try {
|
|
10597
|
-
result = await apiClient.agentAttachExerciseFigures(input);
|
|
10598
|
-
} catch (error) {
|
|
10599
|
-
throw mapApiErrorToCliError(error);
|
|
10600
|
-
}
|
|
10601
|
-
context.output.print(
|
|
10602
|
-
{
|
|
10603
|
-
request: {
|
|
10604
|
-
...input,
|
|
10605
|
-
organizationId: organizationId ?? null
|
|
10606
|
-
},
|
|
10607
|
-
receipt: result.receipt
|
|
10608
|
-
},
|
|
10609
|
-
(output) => formatAttachExerciseFiguresOutput({ receipt: output.receipt }),
|
|
10610
|
-
{
|
|
10611
|
-
command: "exercise figure attach"
|
|
10612
|
-
}
|
|
10613
|
-
);
|
|
10614
|
-
}
|
|
10615
10601
|
).demandCommand(1).strict(),
|
|
10616
10602
|
() => {
|
|
10617
10603
|
}
|
|
@@ -11511,7 +11497,7 @@ var registerFeedbackCommands = (feedbackYargs, context) => {
|
|
|
11511
11497
|
|
|
11512
11498
|
// src/commands/figure.ts
|
|
11513
11499
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
11514
|
-
import { isAbsolute as isAbsolute3, resolve as
|
|
11500
|
+
import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
|
|
11515
11501
|
var parseFigureRenderDraftInput = (value) => {
|
|
11516
11502
|
const parsedInput = figureRenderDraftInputSchema.safeParse(parseJsonObjectFlag({ label: "--input-json", value }));
|
|
11517
11503
|
if (!parsedInput.success) {
|
|
@@ -11519,7 +11505,7 @@ var parseFigureRenderDraftInput = (value) => {
|
|
|
11519
11505
|
}
|
|
11520
11506
|
return parsedInput.data;
|
|
11521
11507
|
};
|
|
11522
|
-
var resolveOutputPath = ({ cwd, outputPath }) => isAbsolute3(outputPath) ? outputPath :
|
|
11508
|
+
var resolveOutputPath = ({ cwd, outputPath }) => isAbsolute3(outputPath) ? outputPath : resolve6(cwd, outputPath);
|
|
11523
11509
|
var writeFigurePng = async ({
|
|
11524
11510
|
cwd,
|
|
11525
11511
|
outputPath,
|
|
@@ -12074,6 +12060,33 @@ var normalizeReadinessFilters = ({
|
|
|
12074
12060
|
}) ?? []
|
|
12075
12061
|
};
|
|
12076
12062
|
};
|
|
12063
|
+
var normalizeSheetSeriesPath = (value) => {
|
|
12064
|
+
const normalizedValue = normalizeOptionalText(value);
|
|
12065
|
+
if (normalizedValue === null) {
|
|
12066
|
+
return null;
|
|
12067
|
+
}
|
|
12068
|
+
const parsedValue = sheetSeriesPathSchema.safeParse(normalizedValue);
|
|
12069
|
+
if (!parsedValue.success) {
|
|
12070
|
+
throw new CliCommandError(
|
|
12071
|
+
'--series-path is unknown. Run "chalksurf sheet series list --json" to inspect valid paths.',
|
|
12072
|
+
2
|
|
12073
|
+
);
|
|
12074
|
+
}
|
|
12075
|
+
return parsedValue.data;
|
|
12076
|
+
};
|
|
12077
|
+
var normalizeSheetSeriesYearFilter = ({ fromYear, toYear }) => {
|
|
12078
|
+
if (fromYear === void 0 && toYear === void 0) {
|
|
12079
|
+
return null;
|
|
12080
|
+
}
|
|
12081
|
+
if (fromYear !== void 0 && toYear !== void 0 && fromYear > toYear) {
|
|
12082
|
+
throw new CliCommandError("--from-year must be less than or equal to --to-year.", 2);
|
|
12083
|
+
}
|
|
12084
|
+
const parsedFilter = sheetSeriesYearFilterSchema.safeParse({ fromYear, toYear });
|
|
12085
|
+
if (!parsedFilter.success) {
|
|
12086
|
+
throw new CliCommandError("--from-year and --to-year must be four-digit years.", 2);
|
|
12087
|
+
}
|
|
12088
|
+
return parsedFilter.data;
|
|
12089
|
+
};
|
|
12077
12090
|
var hasUniqueItems2 = (values) => new Set(values).size === values.length;
|
|
12078
12091
|
var sheetImportComponentIdPattern3 = /^[a-zA-Z0-9_-]{1,80}$/;
|
|
12079
12092
|
var isValidTargetFolderPath2 = (value) => {
|
|
@@ -12501,6 +12514,19 @@ var formatSheetSearchOutput = ({
|
|
|
12501
12514
|
)
|
|
12502
12515
|
].join("\n");
|
|
12503
12516
|
};
|
|
12517
|
+
var formatSheetListOutput = ({ sheets, totalCount }) => {
|
|
12518
|
+
if (sheets.length === 0) {
|
|
12519
|
+
return "No sheets found.";
|
|
12520
|
+
}
|
|
12521
|
+
return [
|
|
12522
|
+
`${sheets.length} of ${totalCount} sheet${totalCount === 1 ? "" : "s"} returned.`,
|
|
12523
|
+
...sheets.map((sheet) => {
|
|
12524
|
+
const folderPath = sheet.folderPath.map(({ name }) => name).join(" / ") || "(root)";
|
|
12525
|
+
const assignments = sheet.seriesAssignments.map(({ editionYear, seriesPath }) => `${seriesPath}@${editionYear}`).join(", ") || "unassigned";
|
|
12526
|
+
return `${sheet.id} ${sheet.name} ${folderPath} ${assignments}`;
|
|
12527
|
+
})
|
|
12528
|
+
].join("\n");
|
|
12529
|
+
};
|
|
12504
12530
|
var formatSheetReadinessSummary = (readinessSummary) => {
|
|
12505
12531
|
if (!readinessSummary.hasIssues) {
|
|
12506
12532
|
return "OK";
|
|
@@ -12649,6 +12675,73 @@ var resolveVisibilityFlag2 = ({ privateFlag, publicFlag }) => {
|
|
|
12649
12675
|
};
|
|
12650
12676
|
var registerSheetCommands = (sheetYargs, context) => {
|
|
12651
12677
|
return sheetYargs.command(
|
|
12678
|
+
"list",
|
|
12679
|
+
"List exercise sheets owned by the selected organization",
|
|
12680
|
+
(listYargs) => listYargs.option("folder-id", {
|
|
12681
|
+
type: "string",
|
|
12682
|
+
describe: "Only include sheets placed directly in this folder"
|
|
12683
|
+
}).option("include-descendants", {
|
|
12684
|
+
type: "boolean",
|
|
12685
|
+
default: false,
|
|
12686
|
+
describe: "Include sheets in descendant folders; requires --folder-id"
|
|
12687
|
+
}).option("limit", {
|
|
12688
|
+
type: "number",
|
|
12689
|
+
default: 50,
|
|
12690
|
+
describe: "Maximum number of sheets to return"
|
|
12691
|
+
}).option("offset", {
|
|
12692
|
+
type: "number",
|
|
12693
|
+
default: 0,
|
|
12694
|
+
describe: "Number of organization-owned sheets to skip"
|
|
12695
|
+
}).example("chalksurf --profile prod-codex sheet list --json", "List sheets owned by the selected organization").example(
|
|
12696
|
+
"chalksurf --profile prod-codex sheet list --folder-id 00000000-0000-4000-8000-000000000001 --include-descendants --json",
|
|
12697
|
+
"List a folder subtree"
|
|
12698
|
+
),
|
|
12699
|
+
async (argv) => {
|
|
12700
|
+
const folderId = resolveRequestedUuid2({
|
|
12701
|
+
flagValue: argv.folderId,
|
|
12702
|
+
label: "--folder-id"
|
|
12703
|
+
});
|
|
12704
|
+
const includeDescendants = Boolean(argv.includeDescendants);
|
|
12705
|
+
if (includeDescendants && !folderId) {
|
|
12706
|
+
throw new CliCommandError("--folder-id is required with --include-descendants.", 2);
|
|
12707
|
+
}
|
|
12708
|
+
const limit = normalizeLimit(argv.limit);
|
|
12709
|
+
const offset = normalizeOffset(argv.offset);
|
|
12710
|
+
const { apiClient, organizationId } = await createResolvedApiClient({
|
|
12711
|
+
context,
|
|
12712
|
+
baseUrlFlagValue: argv.baseUrl,
|
|
12713
|
+
organizationFlagValue: argv.organization,
|
|
12714
|
+
profileName: argv.profile
|
|
12715
|
+
});
|
|
12716
|
+
let result;
|
|
12717
|
+
try {
|
|
12718
|
+
result = await apiClient.agentListSheets({
|
|
12719
|
+
folderId,
|
|
12720
|
+
includeDescendants,
|
|
12721
|
+
limit,
|
|
12722
|
+
offset
|
|
12723
|
+
});
|
|
12724
|
+
} catch (error) {
|
|
12725
|
+
throw mapApiErrorToCliError(error);
|
|
12726
|
+
}
|
|
12727
|
+
context.output.print(
|
|
12728
|
+
{
|
|
12729
|
+
request: {
|
|
12730
|
+
folderId: folderId ?? null,
|
|
12731
|
+
includeDescendants,
|
|
12732
|
+
limit,
|
|
12733
|
+
offset,
|
|
12734
|
+
organizationId: organizationId ?? null
|
|
12735
|
+
},
|
|
12736
|
+
...result
|
|
12737
|
+
},
|
|
12738
|
+
(output) => formatSheetListOutput(output),
|
|
12739
|
+
{
|
|
12740
|
+
command: "sheet list"
|
|
12741
|
+
}
|
|
12742
|
+
);
|
|
12743
|
+
}
|
|
12744
|
+
).command(
|
|
12652
12745
|
"search",
|
|
12653
12746
|
"Search exercise sheets visible to the selected organization",
|
|
12654
12747
|
(searchYargs) => searchYargs.option("text", {
|
|
@@ -12661,6 +12754,15 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12661
12754
|
}).option("subject", {
|
|
12662
12755
|
type: "string",
|
|
12663
12756
|
describe: `Only include sheets in this subject (${exerciseSubjects.join(", ")})`
|
|
12757
|
+
}).option("series-path", {
|
|
12758
|
+
type: "string",
|
|
12759
|
+
describe: "Only include sheets with an assignment at or below this authoritative series path"
|
|
12760
|
+
}).option("from-year", {
|
|
12761
|
+
type: "number",
|
|
12762
|
+
describe: "Only include matching series assignments from this edition year"
|
|
12763
|
+
}).option("to-year", {
|
|
12764
|
+
type: "number",
|
|
12765
|
+
describe: "Only include matching series assignments through this edition year"
|
|
12664
12766
|
}).option("limit", {
|
|
12665
12767
|
type: "number",
|
|
12666
12768
|
default: 20,
|
|
@@ -12696,6 +12798,11 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12696
12798
|
label: "--subject",
|
|
12697
12799
|
value: argv.subject
|
|
12698
12800
|
});
|
|
12801
|
+
const seriesPath = normalizeSheetSeriesPath(argv.seriesPath);
|
|
12802
|
+
const yearFilter = normalizeSheetSeriesYearFilter({
|
|
12803
|
+
fromYear: argv.fromYear,
|
|
12804
|
+
toYear: argv.toYear
|
|
12805
|
+
});
|
|
12699
12806
|
const limit = normalizeLimit(argv.limit);
|
|
12700
12807
|
const offset = normalizeOffset(argv.offset);
|
|
12701
12808
|
const readinessFilters = normalizeReadinessFilters({
|
|
@@ -12716,6 +12823,8 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12716
12823
|
issueTypes: readinessFilters.issueTypes,
|
|
12717
12824
|
text,
|
|
12718
12825
|
subject,
|
|
12826
|
+
seriesPath,
|
|
12827
|
+
yearFilter,
|
|
12719
12828
|
ownership: toApiOwnership(ownership),
|
|
12720
12829
|
limit,
|
|
12721
12830
|
offset
|
|
@@ -12728,6 +12837,8 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12728
12837
|
request: {
|
|
12729
12838
|
text,
|
|
12730
12839
|
subject,
|
|
12840
|
+
seriesPath,
|
|
12841
|
+
yearFilter,
|
|
12731
12842
|
ownership,
|
|
12732
12843
|
hasIssues: readinessFilters.hasIssues,
|
|
12733
12844
|
issueTypes: readinessFilters.issueTypes,
|
|
@@ -12934,8 +13045,16 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12934
13045
|
(seriesYargs) => seriesYargs.command(
|
|
12935
13046
|
"list",
|
|
12936
13047
|
"List valid sheet-series paths",
|
|
12937
|
-
(listYargs) => listYargs.
|
|
13048
|
+
(listYargs) => listYargs.option("subject", {
|
|
13049
|
+
type: "string",
|
|
13050
|
+
describe: `Only include series paths valid for this subject (${exerciseSubjects.join(", ")})`
|
|
13051
|
+
}).example("chalksurf sheet series list --json", "Inspect valid paths before assigning sheets").example("chalksurf sheet series list --subject math --json", "Inspect mathematics series paths"),
|
|
12938
13052
|
async (argv) => {
|
|
13053
|
+
const subject = normalizeChoiceValue({
|
|
13054
|
+
allowedValues: exerciseSubjects,
|
|
13055
|
+
label: "--subject",
|
|
13056
|
+
value: argv.subject
|
|
13057
|
+
});
|
|
12939
13058
|
const { apiClient, organizationId } = await createResolvedApiClient({
|
|
12940
13059
|
context,
|
|
12941
13060
|
baseUrlFlagValue: argv.baseUrl,
|
|
@@ -12944,13 +13063,15 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
12944
13063
|
});
|
|
12945
13064
|
let result;
|
|
12946
13065
|
try {
|
|
12947
|
-
result = await apiClient.agentListSheetSeries(
|
|
13066
|
+
result = await apiClient.agentListSheetSeries({
|
|
13067
|
+
subject: subject ?? void 0
|
|
13068
|
+
});
|
|
12948
13069
|
} catch (error) {
|
|
12949
13070
|
throw mapApiErrorToCliError(error);
|
|
12950
13071
|
}
|
|
12951
13072
|
context.output.print(
|
|
12952
13073
|
{
|
|
12953
|
-
request: { organizationId: organizationId ?? null },
|
|
13074
|
+
request: { organizationId: organizationId ?? null, subject },
|
|
12954
13075
|
series: result.series
|
|
12955
13076
|
},
|
|
12956
13077
|
(output) => formatSheetSeriesOutput({ series: output.series }),
|
|
@@ -13612,17 +13733,32 @@ var registerSheetCommands = (sheetYargs, context) => {
|
|
|
13612
13733
|
).command(
|
|
13613
13734
|
"bulk-update",
|
|
13614
13735
|
"Dry-run or apply up to 100 sheet patches",
|
|
13615
|
-
(bulkUpdateYargs) => bulkUpdateYargs.option("input
|
|
13736
|
+
(bulkUpdateYargs) => bulkUpdateYargs.option("input", {
|
|
13616
13737
|
type: "string",
|
|
13617
|
-
|
|
13618
|
-
describe:
|
|
13738
|
+
nargs: 1,
|
|
13739
|
+
describe: 'Read the bulk update JSON object from a UTF-8 file, or "-" for stdin'
|
|
13740
|
+
}).option("input-json", {
|
|
13741
|
+
type: "string",
|
|
13742
|
+
nargs: 1,
|
|
13743
|
+
describe: "Inline JSON matching the bulk update contract: mode, updates, and confirmationDigest for apply mode"
|
|
13619
13744
|
}).example(
|
|
13745
|
+
"chalksurf sheet bulk-update --input batch-001.json --json",
|
|
13746
|
+
"Validate a reviewed bulk-update batch from a file"
|
|
13747
|
+
).example(
|
|
13748
|
+
"cat batch-001.json | chalksurf sheet bulk-update --input - --json",
|
|
13749
|
+
"Validate a reviewed bulk-update batch from stdin"
|
|
13750
|
+
).example(
|
|
13620
13751
|
`chalksurf sheet bulk-update --input-json '{"mode":"dry_run","updates":[{"id":"00000000-0000-4000-8000-000000000001","expectedUpdatedAt":"2026-01-01T00:00:00.000Z","patch":{"seriesAssignments":[{"seriesPath":"international.imo","editionYear":2025}]}}]}' --json`,
|
|
13621
13752
|
"Validate sheet-series assignments and obtain a confirmation digest"
|
|
13622
13753
|
),
|
|
13623
13754
|
async (argv) => {
|
|
13624
13755
|
const input = parseBulkUpdateSheetsAgentInput(
|
|
13625
|
-
|
|
13756
|
+
await loadJsonObjectInput({
|
|
13757
|
+
cwd: context.cwd,
|
|
13758
|
+
inputJson: argv.inputJson,
|
|
13759
|
+
inputPath: argv.input,
|
|
13760
|
+
stdin: context.stdin
|
|
13761
|
+
})
|
|
13626
13762
|
);
|
|
13627
13763
|
const { apiClient, organizationId } = await createResolvedApiClient({
|
|
13628
13764
|
context,
|
|
@@ -14255,7 +14391,7 @@ var parseCliWithCapturedOutput = async ({
|
|
|
14255
14391
|
argv,
|
|
14256
14392
|
stdout
|
|
14257
14393
|
}) => {
|
|
14258
|
-
await new Promise((
|
|
14394
|
+
await new Promise((resolve7, reject) => {
|
|
14259
14395
|
cli.parse(argv, (error, _parsedArgv, output) => {
|
|
14260
14396
|
if (output) {
|
|
14261
14397
|
stdout.write(output);
|
|
@@ -14264,7 +14400,7 @@ var parseCliWithCapturedOutput = async ({
|
|
|
14264
14400
|
reject(error);
|
|
14265
14401
|
return;
|
|
14266
14402
|
}
|
|
14267
|
-
|
|
14403
|
+
resolve7();
|
|
14268
14404
|
});
|
|
14269
14405
|
});
|
|
14270
14406
|
};
|
|
@@ -14295,7 +14431,7 @@ var runCli = async ({
|
|
|
14295
14431
|
configPath,
|
|
14296
14432
|
env = process.env,
|
|
14297
14433
|
nowImpl = Date.now,
|
|
14298
|
-
sleepImpl = (milliseconds) => new Promise((
|
|
14434
|
+
sleepImpl = (milliseconds) => new Promise((resolve7) => setTimeout(resolve7, milliseconds)),
|
|
14299
14435
|
stdin = process.stdin,
|
|
14300
14436
|
stdout = process.stdout,
|
|
14301
14437
|
stderr = process.stderr
|