@chalksurf/cli 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,20 +7,33 @@ import { hideBin } from "yargs/helpers";
7
7
  import yargs from "yargs/yargs";
8
8
 
9
9
  // src/lib/api-client.ts
10
+ var ApiClientError = class extends Error {
11
+ agentErrorCode;
12
+ constructor(message, options = {}) {
13
+ super(message);
14
+ this.name = "ApiClientError";
15
+ this.agentErrorCode = options.agentErrorCode;
16
+ }
17
+ };
10
18
  var normalizeBaseUrl = (baseUrl) => {
11
19
  return baseUrl.endsWith("/") ? baseUrl : `${baseUrl}/`;
12
20
  };
13
21
  var getErrorMessage = (payload, status) => {
14
22
  return payload?.error?.message ?? `API request failed with status ${status}`;
15
23
  };
24
+ var getAgentErrorCode = (payload) => payload?.error?.data?.agentErrorCode;
16
25
  var getResponseData = async ({ response, batched }) => {
17
26
  const body = await response.json();
18
27
  const payload = batched ? body[0] : body;
19
28
  if (!response.ok) {
20
- throw new Error(getErrorMessage(payload, response.status));
29
+ throw new ApiClientError(getErrorMessage(payload, response.status), {
30
+ agentErrorCode: getAgentErrorCode(payload)
31
+ });
21
32
  }
22
33
  if (payload?.error) {
23
- throw new Error(payload.error.message);
34
+ throw new ApiClientError(payload.error.message, {
35
+ agentErrorCode: getAgentErrorCode(payload)
36
+ });
24
37
  }
25
38
  if (!payload?.result) {
26
39
  throw new Error("API response is missing a result payload");
@@ -101,30 +114,66 @@ var createApiClient = ({
101
114
  agentGetExerciseUsage: async (id) => {
102
115
  return await query("agentGetExerciseUsage", { id });
103
116
  },
117
+ agentListExerciseLabels: async () => {
118
+ return await query("agentListExerciseLabels", {});
119
+ },
104
120
  agentCopyExercise: async (id) => {
105
121
  return await mutation("agentCopyExercise", { id });
106
122
  },
123
+ agentDeleteExercise: async (input) => {
124
+ return await mutation("agentDeleteExercise", input);
125
+ },
126
+ agentCreateExercise: async (input) => {
127
+ return await mutation("agentCreateExercise", input);
128
+ },
107
129
  agentUpdateExercise: async (input) => {
108
130
  return await mutation("agentUpdateExercise", input);
109
131
  },
132
+ agentSetExerciseVisibility: async (input) => {
133
+ return await mutation("agentSetExerciseVisibility", input);
134
+ },
110
135
  agentGetSheet: async (id) => {
111
136
  return await query("agentGetSheet", { id });
112
137
  },
138
+ agentListSheetVersions: async (id) => {
139
+ return await query("agentListSheetVersions", { id });
140
+ },
141
+ agentGetSheetVersion: async (exerciseSheetId, versionId) => {
142
+ return await query("agentGetSheetVersion", { exerciseSheetId, versionId });
143
+ },
113
144
  agentGetSheetIssues: async (id) => {
114
145
  return await query("agentGetSheetIssues", { id });
115
146
  },
116
147
  agentCopySheet: async (input) => {
117
148
  return await mutation("agentCopySheet", input);
118
149
  },
150
+ agentDeleteSheet: async (input) => {
151
+ return await mutation("agentDeleteSheet", input);
152
+ },
153
+ agentCreateSheet: async (input) => {
154
+ return await mutation("agentCreateSheet", input);
155
+ },
119
156
  agentUpdateSheet: async (input) => {
120
157
  return await mutation("agentUpdateSheet", input);
121
158
  },
159
+ agentSetSheetVisibility: async (input) => {
160
+ return await mutation("agentSetSheetVisibility", input);
161
+ },
122
162
  agentAppendExercisesToSheet: async (input) => {
123
163
  return await mutation("agentAppendExercisesToSheet", input);
124
164
  },
125
165
  agentListFolders: async () => {
126
166
  return await query("agentListFolders", {});
127
167
  },
168
+ agentSendUserFeedback: async (input) => {
169
+ return await mutation("agentSendUserFeedback", input);
170
+ },
171
+ agentSendAgentFeedback: async (input) => {
172
+ return await mutation("agentSendAgentFeedback", input);
173
+ },
174
+ agentDeleteFolder: async (input) => {
175
+ return await mutation("agentDeleteFolder", input);
176
+ },
128
177
  agentCreateFolder: async (input) => {
129
178
  return await mutation("agentCreateFolder", input);
130
179
  },
@@ -157,14 +206,16 @@ var createSerializableCliError = ({
157
206
  code,
158
207
  exitCode,
159
208
  message,
160
- retryable
209
+ retryable,
210
+ agentErrorCode
161
211
  }) => {
162
212
  const resolvedCode = code ?? getCliErrorCode(exitCode);
163
213
  return {
164
214
  code: resolvedCode,
165
215
  exitCode,
166
216
  message,
167
- retryable: retryable ?? isRetryableCliErrorCode(resolvedCode)
217
+ retryable: retryable ?? isRetryableCliErrorCode(resolvedCode),
218
+ ...agentErrorCode ? { agentErrorCode } : {}
168
219
  };
169
220
  };
170
221
  var CliCommandError = class extends Error {
@@ -172,6 +223,7 @@ var CliCommandError = class extends Error {
172
223
  exitCode;
173
224
  retryable;
174
225
  shouldReport;
226
+ agentErrorCode;
175
227
  constructor(message, exitCode, shouldReport = true, options = {}) {
176
228
  super(message);
177
229
  this.name = "CliCommandError";
@@ -179,6 +231,7 @@ var CliCommandError = class extends Error {
179
231
  this.exitCode = exitCode;
180
232
  this.retryable = options.retryable ?? isRetryableCliErrorCode(this.code);
181
233
  this.shouldReport = shouldReport;
234
+ this.agentErrorCode = options.agentErrorCode;
182
235
  }
183
236
  };
184
237
  var serializeCliError = (error) => {
@@ -186,7 +239,8 @@ var serializeCliError = (error) => {
186
239
  code: error.code,
187
240
  exitCode: error.exitCode,
188
241
  message: error.message,
189
- retryable: error.retryable
242
+ retryable: error.retryable,
243
+ agentErrorCode: error.agentErrorCode
190
244
  });
191
245
  };
192
246
 
@@ -587,10 +641,15 @@ var normalizeOptionalString2 = (value) => {
587
641
  };
588
642
  var mapApiErrorToCliError = (error) => {
589
643
  const message = error instanceof Error ? error.message : "Unknown API error";
644
+ const agentErrorCode = error instanceof ApiClientError ? error.agentErrorCode : void 0;
590
645
  if (message.includes("UNAUTHORIZED")) {
591
- return new CliCommandError("Authentication failed. The CLI token is invalid or revoked.", 3);
646
+ return new CliCommandError("Authentication failed. The CLI token is invalid or revoked.", 3, true, {
647
+ agentErrorCode
648
+ });
592
649
  }
593
- return new CliCommandError(`API request failed: ${message}`, 5);
650
+ return new CliCommandError(`API request failed: ${message}`, 5, true, {
651
+ agentErrorCode
652
+ });
594
653
  };
595
654
  var requireResolvedBaseUrl = ({
596
655
  flagValue,
@@ -867,7 +926,461 @@ ${formatOrganizationSummary(result.organization)}`,
867
926
  };
868
927
 
869
928
  // src/commands/exercise.ts
870
- import { z as z8 } from "zod";
929
+ import { z as z11 } from "zod";
930
+
931
+ // ../shared/src/labels.json
932
+ var labels_default = [
933
+ {
934
+ id: "algebra",
935
+ name: "algebra",
936
+ children: [
937
+ {
938
+ id: "algebra.identities",
939
+ name: "identities"
940
+ },
941
+ {
942
+ id: "algebra.inequalities",
943
+ name: "inequalities"
944
+ },
945
+ {
946
+ id: "algebra.equations",
947
+ name: "equations",
948
+ children: [
949
+ {
950
+ id: "algebra.equations.linear_equation",
951
+ name: "linear equation"
952
+ },
953
+ {
954
+ id: "algebra.equations.quadratic_equation",
955
+ name: "quadratic equation"
956
+ },
957
+ {
958
+ id: "algebra.equations.higher_order_equation",
959
+ name: "higher order equation"
960
+ },
961
+ {
962
+ id: "algebra.equations.absolute_value_equation",
963
+ name: "absolute value equation"
964
+ },
965
+ {
966
+ id: "algebra.equations.diophantine_equation",
967
+ name: "Diophantine equation"
968
+ },
969
+ {
970
+ id: "algebra.equations.square_root_equation",
971
+ name: "square root equation"
972
+ },
973
+ {
974
+ id: "algebra.equations.exponential_logarithmic_equation",
975
+ name: "exponential, logarithmic equation"
976
+ },
977
+ {
978
+ id: "algebra.equations.trigonometric_equation",
979
+ name: "trigonometric equation"
980
+ },
981
+ {
982
+ id: "algebra.equations.parametric_equation",
983
+ name: "parametric equation"
984
+ },
985
+ {
986
+ id: "algebra.equations.equation_systems",
987
+ name: "equation systems"
988
+ }
989
+ ]
990
+ },
991
+ {
992
+ id: "algebra.means",
993
+ name: "means"
994
+ }
995
+ ]
996
+ },
997
+ {
998
+ id: "arithmetic",
999
+ name: "arithmetic",
1000
+ children: [
1001
+ {
1002
+ id: "arithmetic.counting",
1003
+ name: "counting"
1004
+ },
1005
+ {
1006
+ id: "arithmetic.fractions",
1007
+ name: "fractions"
1008
+ },
1009
+ {
1010
+ id: "arithmetic.proportionality",
1011
+ name: "proportionality"
1012
+ },
1013
+ {
1014
+ id: "arithmetic.digits",
1015
+ name: "digits"
1016
+ },
1017
+ {
1018
+ id: "arithmetic.powers",
1019
+ name: "powers"
1020
+ },
1021
+ {
1022
+ id: "arithmetic.percentage",
1023
+ name: "percentage"
1024
+ },
1025
+ {
1026
+ id: "arithmetic.square_roots",
1027
+ name: "(square) roots"
1028
+ },
1029
+ {
1030
+ id: "arithmetic.numeral_systems",
1031
+ name: "numeral systems"
1032
+ },
1033
+ {
1034
+ id: "arithmetic.units_of_measurement",
1035
+ name: "units of measurement"
1036
+ }
1037
+ ]
1038
+ },
1039
+ {
1040
+ id: "number_theory",
1041
+ name: "number theory",
1042
+ children: [
1043
+ {
1044
+ id: "number_theory.divisibility",
1045
+ name: "divisibility"
1046
+ },
1047
+ {
1048
+ id: "number_theory.prime_factorization",
1049
+ name: "prime factorization"
1050
+ },
1051
+ {
1052
+ id: "number_theory.primes_not_factorization",
1053
+ name: "primes (not factorization)"
1054
+ },
1055
+ {
1056
+ id: "number_theory.digits",
1057
+ name: "digits"
1058
+ },
1059
+ {
1060
+ id: "number_theory.modular_arithmetic",
1061
+ name: "modular arithmetic"
1062
+ }
1063
+ ]
1064
+ },
1065
+ {
1066
+ id: "analysis_functions",
1067
+ name: "analysis / functions",
1068
+ children: [
1069
+ {
1070
+ id: "analysis_functions.graph_of_a_function",
1071
+ name: "graph of a function"
1072
+ },
1073
+ {
1074
+ id: "analysis_functions.polynomials",
1075
+ name: "polynomials"
1076
+ },
1077
+ {
1078
+ id: "analysis_functions.monotonicity_of_function",
1079
+ name: "monotonicity of function"
1080
+ },
1081
+ {
1082
+ id: "analysis_functions.minimum_maximum_of_function",
1083
+ name: "minimum, maximum of function"
1084
+ },
1085
+ {
1086
+ id: "analysis_functions.zero_point_of_function",
1087
+ name: "zero point of function"
1088
+ },
1089
+ {
1090
+ id: "analysis_functions.derivatives",
1091
+ name: "derivatives"
1092
+ },
1093
+ {
1094
+ id: "analysis_functions.integration",
1095
+ name: "integration"
1096
+ },
1097
+ {
1098
+ id: "analysis_functions.limit_of_function",
1099
+ name: "limit of function"
1100
+ }
1101
+ ]
1102
+ },
1103
+ {
1104
+ id: "sequences",
1105
+ name: "sequences",
1106
+ children: [
1107
+ {
1108
+ id: "sequences.arithmetic_progression",
1109
+ name: "arithmetic progression"
1110
+ },
1111
+ {
1112
+ id: "sequences.geometric_progression",
1113
+ name: "geometric progression"
1114
+ },
1115
+ {
1116
+ id: "sequences.recursion",
1117
+ name: "recursion"
1118
+ },
1119
+ {
1120
+ id: "sequences.periodic",
1121
+ name: "periodic"
1122
+ },
1123
+ {
1124
+ id: "sequences.fibonacci",
1125
+ name: "Fibonacci"
1126
+ },
1127
+ {
1128
+ id: "sequences.monotonicity_boundedness",
1129
+ name: "monotonicity, boundedness"
1130
+ },
1131
+ {
1132
+ id: "sequences.limit",
1133
+ name: "limit"
1134
+ }
1135
+ ]
1136
+ },
1137
+ {
1138
+ id: "geometry",
1139
+ name: "geometry",
1140
+ children: [
1141
+ {
1142
+ id: "geometry.3d_geometry",
1143
+ name: "3D geometry",
1144
+ children: [
1145
+ {
1146
+ id: "geometry.3d_geometry.surface_area_volume",
1147
+ name: "surface area, volume"
1148
+ },
1149
+ {
1150
+ id: "geometry.3d_geometry.polyhedron_net",
1151
+ name: "polyhedron net"
1152
+ },
1153
+ {
1154
+ id: "geometry.3d_geometry.platonic_solids",
1155
+ name: "Platonic solids"
1156
+ },
1157
+ {
1158
+ id: "geometry.3d_geometry.cylinder",
1159
+ name: "cylinder"
1160
+ },
1161
+ {
1162
+ id: "geometry.3d_geometry.prism",
1163
+ name: "prism"
1164
+ },
1165
+ {
1166
+ id: "geometry.3d_geometry.pyramid",
1167
+ name: "pyramid"
1168
+ },
1169
+ {
1170
+ id: "geometry.3d_geometry.cone",
1171
+ name: "cone"
1172
+ },
1173
+ {
1174
+ id: "geometry.3d_geometry.3d_transformations",
1175
+ name: "3D transformations"
1176
+ }
1177
+ ]
1178
+ },
1179
+ {
1180
+ id: "geometry.vectors",
1181
+ name: "vectors"
1182
+ },
1183
+ {
1184
+ id: "geometry.coordinate_geometry",
1185
+ name: "coordinate geometry"
1186
+ },
1187
+ {
1188
+ id: "geometry.pythagorean_theorem",
1189
+ name: "Pythagorean theorem"
1190
+ },
1191
+ {
1192
+ id: "geometry.thales_theorem",
1193
+ name: "Thales theorem"
1194
+ },
1195
+ {
1196
+ id: "geometry.circumference_area",
1197
+ name: "circumference, area"
1198
+ },
1199
+ {
1200
+ id: "geometry.triangle",
1201
+ name: "triangle"
1202
+ },
1203
+ {
1204
+ id: "geometry.rectangle",
1205
+ name: "rectangle"
1206
+ },
1207
+ {
1208
+ id: "geometry.polygon",
1209
+ name: "polygon"
1210
+ },
1211
+ {
1212
+ id: "geometry.regular_polygon",
1213
+ name: "regular polygon"
1214
+ },
1215
+ {
1216
+ id: "geometry.circle",
1217
+ name: "circle"
1218
+ },
1219
+ {
1220
+ id: "geometry.conic_section",
1221
+ name: "conic section"
1222
+ },
1223
+ {
1224
+ id: "geometry.angles",
1225
+ name: "angles"
1226
+ },
1227
+ {
1228
+ id: "geometry.trigonometry",
1229
+ name: "trigonometry"
1230
+ },
1231
+ {
1232
+ id: "geometry.transformations",
1233
+ name: "transformations"
1234
+ },
1235
+ {
1236
+ id: "geometry.symmetry",
1237
+ name: "symmetry"
1238
+ },
1239
+ {
1240
+ id: "geometry.similarity",
1241
+ name: "similarity"
1242
+ }
1243
+ ]
1244
+ },
1245
+ {
1246
+ id: "probability_and_statistics",
1247
+ name: "probability and statistics",
1248
+ children: [
1249
+ {
1250
+ id: "probability_and_statistics.combinatorial_probability",
1251
+ name: "combinatorial probability"
1252
+ },
1253
+ {
1254
+ id: "probability_and_statistics.geometric_probability",
1255
+ name: "geometric probability"
1256
+ },
1257
+ {
1258
+ id: "probability_and_statistics.bayes_theorem",
1259
+ name: "Bayes theorem"
1260
+ },
1261
+ {
1262
+ id: "probability_and_statistics.independence",
1263
+ name: "independence"
1264
+ },
1265
+ {
1266
+ id: "probability_and_statistics.mean_variance",
1267
+ name: "mean, variance"
1268
+ },
1269
+ {
1270
+ id: "probability_and_statistics.statistics",
1271
+ name: "statistics"
1272
+ }
1273
+ ]
1274
+ },
1275
+ {
1276
+ id: "combinatorics",
1277
+ name: "combinatorics",
1278
+ children: [
1279
+ {
1280
+ id: "combinatorics.combination_variation",
1281
+ name: "combination, variation"
1282
+ },
1283
+ {
1284
+ id: "combinatorics.permutation",
1285
+ name: "permutation"
1286
+ },
1287
+ {
1288
+ id: "combinatorics.inclusion_exclusion",
1289
+ name: "inclusion exclusion"
1290
+ },
1291
+ {
1292
+ id: "combinatorics.geometric_combinatorics",
1293
+ name: "geometric combinatorics"
1294
+ }
1295
+ ]
1296
+ },
1297
+ {
1298
+ id: "graphs",
1299
+ name: "graphs",
1300
+ children: [
1301
+ {
1302
+ id: "graphs.plane_graphs",
1303
+ name: "plane graphs"
1304
+ },
1305
+ {
1306
+ id: "graphs.paths_walks",
1307
+ name: "paths, walks"
1308
+ },
1309
+ {
1310
+ id: "graphs.degrees",
1311
+ name: "degrees"
1312
+ },
1313
+ {
1314
+ id: "graphs.subgraph",
1315
+ name: "subgraph"
1316
+ },
1317
+ {
1318
+ id: "graphs.bipartite_graph",
1319
+ name: "bipartite graph"
1320
+ },
1321
+ {
1322
+ id: "graphs.oriented_graph",
1323
+ name: "oriented graph"
1324
+ }
1325
+ ]
1326
+ },
1327
+ {
1328
+ id: "set_theory",
1329
+ name: "set theory",
1330
+ children: [
1331
+ {
1332
+ id: "set_theory.set_arithmetics",
1333
+ name: "set arithmetics"
1334
+ },
1335
+ {
1336
+ id: "set_theory.inclusion_exclusion",
1337
+ name: "inclusion exclusion"
1338
+ },
1339
+ {
1340
+ id: "set_theory.de_morgan_identities",
1341
+ name: "de Morgan identities"
1342
+ },
1343
+ {
1344
+ id: "set_theory.intervals",
1345
+ name: "intervals"
1346
+ },
1347
+ {
1348
+ id: "set_theory.number_sets",
1349
+ name: "number sets"
1350
+ }
1351
+ ]
1352
+ },
1353
+ {
1354
+ id: "logic",
1355
+ name: "logic",
1356
+ children: [
1357
+ {
1358
+ id: "logic.logic_arithmetics",
1359
+ name: "logic arithmetics"
1360
+ },
1361
+ {
1362
+ id: "logic.true_false",
1363
+ name: "true false"
1364
+ },
1365
+ {
1366
+ id: "logic.recursive_logic",
1367
+ name: "recursive logic"
1368
+ },
1369
+ {
1370
+ id: "logic.winning_strategy",
1371
+ name: "winning strategy"
1372
+ },
1373
+ {
1374
+ id: "logic.tiling",
1375
+ name: "tiling"
1376
+ },
1377
+ {
1378
+ id: "logic.algorithm",
1379
+ name: "algorithm"
1380
+ }
1381
+ ]
1382
+ }
1383
+ ];
871
1384
 
872
1385
  // ../shared/src/agent-tools/index.ts
873
1386
  import { z } from "zod";
@@ -910,8 +1423,38 @@ var Constants = {
910
1423
  },
911
1424
  public: {
912
1425
  Enums: {
913
- event_type: ["feedback_sent", "feedback_abandoned", "error_report"],
1426
+ agent_audit_actor_kind: ["cli_token", "mcp_oauth"],
1427
+ agent_audit_operation: [
1428
+ "send_user_feedback",
1429
+ "send_agent_feedback",
1430
+ "copy_exercise",
1431
+ "copy_sheet",
1432
+ "update_exercise",
1433
+ "update_sheet",
1434
+ "append_exercises_to_sheet",
1435
+ "create_folder",
1436
+ "rename_folder",
1437
+ "delete_exercise",
1438
+ "delete_sheet",
1439
+ "delete_folder",
1440
+ "create_sheet",
1441
+ "create_exercise",
1442
+ "set_exercise_visibility",
1443
+ "set_sheet_visibility",
1444
+ "import_exercise_started",
1445
+ "import_exercise_completed",
1446
+ "import_exercise_solution_started",
1447
+ "import_exercise_solution_completed",
1448
+ "import_sheet_started",
1449
+ "import_sheet_completed",
1450
+ "import_sheet_solutions_started",
1451
+ "import_sheet_solutions_completed"
1452
+ ],
1453
+ agent_audit_outcome: ["started", "success", "failed", "denied"],
1454
+ agent_audit_resource_type: ["exercise", "sheet", "folder", "job", "event"],
1455
+ event_type: ["feedback_sent", "feedback_abandoned", "error_report", "user_feedback_sent", "agent_feedback_sent"],
914
1456
  exercise_sheet_translation_status: ["ready", "preparing", "failed"],
1457
+ exercise_sheet_version_type: ["backfill", "create", "manual_edit", "copy", "sheet_import", "revert"],
915
1458
  exercise_status: ["verified", "unverified", "invalid"],
916
1459
  exercise_subject: ["math", "physics", "chemistry", "informatics"],
917
1460
  exercise_version_type: [
@@ -966,12 +1509,23 @@ var latexValidationIssueCodes = [
966
1509
  // ../shared/src/types/types.ts
967
1510
  var exerciseStatusOptions = Constants.public.Enums.exercise_status;
968
1511
  var exerciseVersionTypes = Constants.public.Enums.exercise_version_type;
1512
+ var agentAuditActorKinds = Constants.public.Enums.agent_audit_actor_kind;
1513
+ var agentAuditOutcomes = Constants.public.Enums.agent_audit_outcome;
1514
+ var agentAuditOperations = Constants.public.Enums.agent_audit_operation;
1515
+ var agentAuditResourceTypes = Constants.public.Enums.agent_audit_resource_type;
969
1516
  var exerciseSheetTranslationStatuses = Constants.public.Enums.exercise_sheet_translation_status;
1517
+ var exerciseSheetVersionTypes = Constants.public.Enums.exercise_sheet_version_type;
970
1518
  var mcpOAuthGrantPermissions = ["read", "write"];
971
1519
  var jobTypes = Constants.public.Enums.job_type;
972
1520
  var userJobStatuses = Constants.public.Enums.user_job_status;
973
1521
  var eventTypes = Constants.public.Enums.event_type;
974
1522
  var exerciseSubjects = Constants.public.Enums.exercise_subject;
1523
+ var exportTemplateIds = [
1524
+ "exercises",
1525
+ "exercises-with-workspace",
1526
+ "exercises-with-solutions",
1527
+ "exercises-with-answers"
1528
+ ];
975
1529
  var organizationTypes = Constants.public.Enums.organization_type;
976
1530
  var organizationMemberRoles = Constants.public.Enums.organization_member_role;
977
1531
  var organizationInvitationStatuses = Constants.public.Enums.organization_invitation_status;
@@ -989,6 +1543,147 @@ var exerciseSheetTranslationFields = [
989
1543
  "description"
990
1544
  ];
991
1545
 
1546
+ // ../shared/src/agent-tools/operations.ts
1547
+ var agentWriteOperationRegistry = {
1548
+ send_user_feedback: {
1549
+ agentToolName: "send_user_feedback",
1550
+ receiptOperation: null,
1551
+ resourceType: "event",
1552
+ sync: true
1553
+ },
1554
+ send_agent_feedback: {
1555
+ agentToolName: "send_agent_feedback",
1556
+ receiptOperation: null,
1557
+ resourceType: "event",
1558
+ sync: true
1559
+ },
1560
+ copy_exercise: {
1561
+ agentToolName: "copy_exercise",
1562
+ receiptOperation: "copy_exercise",
1563
+ resourceType: "exercise",
1564
+ sync: true
1565
+ },
1566
+ copy_sheet: {
1567
+ agentToolName: "copy_sheet",
1568
+ receiptOperation: "copy_sheet",
1569
+ resourceType: "sheet",
1570
+ sync: true
1571
+ },
1572
+ update_exercise: {
1573
+ agentToolName: "update_exercise",
1574
+ receiptOperation: "update_exercise",
1575
+ resourceType: "exercise",
1576
+ sync: true
1577
+ },
1578
+ update_sheet: {
1579
+ agentToolName: "update_sheet",
1580
+ receiptOperation: "update_sheet",
1581
+ resourceType: "sheet",
1582
+ sync: true
1583
+ },
1584
+ append_exercises_to_sheet: {
1585
+ agentToolName: "append_exercises_to_sheet",
1586
+ receiptOperation: "append_exercises_to_sheet",
1587
+ resourceType: "sheet",
1588
+ sync: true
1589
+ },
1590
+ create_folder: {
1591
+ agentToolName: "create_folder",
1592
+ receiptOperation: "create_folder",
1593
+ resourceType: "folder",
1594
+ sync: true
1595
+ },
1596
+ rename_folder: {
1597
+ agentToolName: "rename_folder",
1598
+ receiptOperation: "rename_folder",
1599
+ resourceType: "folder",
1600
+ sync: true
1601
+ },
1602
+ delete_exercise: {
1603
+ agentToolName: "delete_exercise",
1604
+ receiptOperation: "delete_exercise",
1605
+ resourceType: "exercise",
1606
+ sync: true
1607
+ },
1608
+ delete_sheet: {
1609
+ agentToolName: "delete_sheet",
1610
+ receiptOperation: "delete_sheet",
1611
+ resourceType: "sheet",
1612
+ sync: true
1613
+ },
1614
+ delete_folder: {
1615
+ agentToolName: "delete_folder",
1616
+ receiptOperation: "delete_folder",
1617
+ resourceType: "folder",
1618
+ sync: true
1619
+ },
1620
+ create_sheet: {
1621
+ agentToolName: "create_sheet",
1622
+ receiptOperation: "create_sheet",
1623
+ resourceType: "sheet",
1624
+ sync: true
1625
+ },
1626
+ create_exercise: {
1627
+ agentToolName: "create_exercise",
1628
+ receiptOperation: "create_exercise",
1629
+ resourceType: "exercise",
1630
+ sync: true
1631
+ },
1632
+ set_exercise_visibility: {
1633
+ agentToolName: "set_exercise_visibility",
1634
+ receiptOperation: "set_exercise_visibility",
1635
+ resourceType: "exercise",
1636
+ sync: true
1637
+ },
1638
+ set_sheet_visibility: {
1639
+ agentToolName: "set_sheet_visibility",
1640
+ receiptOperation: "set_sheet_visibility",
1641
+ resourceType: "sheet",
1642
+ sync: true
1643
+ },
1644
+ import_exercise_started: {
1645
+ receiptOperation: null,
1646
+ resourceType: "job",
1647
+ sync: false
1648
+ },
1649
+ import_exercise_completed: {
1650
+ receiptOperation: null,
1651
+ resourceType: "exercise",
1652
+ sync: false
1653
+ },
1654
+ import_exercise_solution_started: {
1655
+ receiptOperation: null,
1656
+ resourceType: "job",
1657
+ sync: false
1658
+ },
1659
+ import_exercise_solution_completed: {
1660
+ receiptOperation: null,
1661
+ resourceType: "exercise",
1662
+ sync: false
1663
+ },
1664
+ import_sheet_started: {
1665
+ receiptOperation: null,
1666
+ resourceType: "job",
1667
+ sync: false
1668
+ },
1669
+ import_sheet_completed: {
1670
+ receiptOperation: null,
1671
+ resourceType: "sheet",
1672
+ sync: false
1673
+ },
1674
+ import_sheet_solutions_started: {
1675
+ receiptOperation: null,
1676
+ resourceType: "job",
1677
+ sync: false
1678
+ },
1679
+ import_sheet_solutions_completed: {
1680
+ receiptOperation: null,
1681
+ resourceType: "sheet",
1682
+ sync: false
1683
+ }
1684
+ };
1685
+ var agentWriteReceiptOperations = Object.values(agentWriteOperationRegistry).map((operation) => operation.receiptOperation).filter((operation) => Boolean(operation));
1686
+
992
1687
  // ../shared/src/agent-tools/index.ts
993
1688
  var strictObject = (shape) => z.object(shape).strict();
994
1689
  var uuidSchema = z.uuid();
@@ -998,6 +1693,21 @@ var optionalNullableStringSchema = z.string().trim().min(1).nullable().optional(
998
1693
  var metadataSchema = z.unknown().nullable();
999
1694
  var patchNullableStringSchema = z.string().nullable().optional();
1000
1695
  var expectedUpdatedAtSchema = z.string().trim().min(1);
1696
+ var feedbackContextSchema = z.record(z.string(), z.unknown()).optional();
1697
+ var feedbackMessageSchema = z.string().trim().min(1).max(5e3);
1698
+ var agentErrorCodes = [
1699
+ "precondition_failed",
1700
+ "confirmation_required",
1701
+ "resource_in_use",
1702
+ "feature_disabled",
1703
+ "invalid_label",
1704
+ "forbidden",
1705
+ "not_found",
1706
+ "validation_failed",
1707
+ "unauthorized"
1708
+ ];
1709
+ var agentErrorCodeSchema = z.enum(agentErrorCodes);
1710
+ var agentWriteReceiptOperationSchema = z.enum(agentWriteReceiptOperations);
1001
1711
  var exerciseTranslationFieldNames = [
1002
1712
  "exercise_text",
1003
1713
  "description",
@@ -1069,6 +1779,37 @@ var sheetTranslationSchema = strictObject({
1069
1779
  var sheetTranslationStatusSchema = strictObject({
1070
1780
  status: z.enum(exerciseSheetTranslationStatuses)
1071
1781
  });
1782
+ var sheetVersionTranslationSchema = strictObject({
1783
+ name: z.string(),
1784
+ title: z.string().nullable(),
1785
+ description: z.string().nullable()
1786
+ });
1787
+ var sheetVersionExerciseSchema = strictObject({
1788
+ exerciseId: uuidSchema,
1789
+ orderIndex: z.number().int().min(1),
1790
+ scorePoints: z.number().nullable()
1791
+ });
1792
+ var sheetVersionSnapshotSchema = strictObject({
1793
+ subject: z.enum(exerciseSubjects),
1794
+ private_notes: z.string().nullable(),
1795
+ scoring_enabled: z.boolean(),
1796
+ translations: z.record(z.string(), sheetVersionTranslationSchema),
1797
+ exercises: z.array(sheetVersionExerciseSchema)
1798
+ });
1799
+ var sheetVersionListItemSchema = strictObject({
1800
+ id: uuidSchema,
1801
+ exerciseSheetId: uuidSchema,
1802
+ versionNumber: z.number().int().positive(),
1803
+ createdAt: dateStringSchema,
1804
+ createdByUserId: uuidSchema.nullable(),
1805
+ createdByName: z.string().nullable(),
1806
+ type: z.enum(exerciseSheetVersionTypes),
1807
+ sourceVersionId: uuidSchema.nullable()
1808
+ });
1809
+ var sheetVersionDetailSchema = sheetVersionListItemSchema.extend({
1810
+ snapshot: sheetVersionSnapshotSchema,
1811
+ exercises: z.array(exerciseSummarySchema)
1812
+ });
1072
1813
  var sheetDetailsSchema = strictObject({
1073
1814
  id: uuidSchema,
1074
1815
  created_at: dateStringSchema,
@@ -1094,6 +1835,22 @@ var folderSchema = strictObject({
1094
1835
  parentId: uuidSchema.nullable(),
1095
1836
  updatedAt: dateStringSchema
1096
1837
  });
1838
+ var exerciseLabelSchema = strictObject({
1839
+ id: z.string().trim().min(1),
1840
+ name: z.string().trim().min(1),
1841
+ parentId: z.string().trim().min(1).nullable(),
1842
+ depth: z.number().int().min(0),
1843
+ pathIds: z.array(z.string().trim().min(1)),
1844
+ pathNames: z.array(z.string().trim().min(1)),
1845
+ displayPath: z.string().trim().min(1),
1846
+ childIds: z.array(z.string().trim().min(1))
1847
+ });
1848
+ var agentFeedbackEventTypeSchema = z.enum(["user_feedback_sent", "agent_feedback_sent"]);
1849
+ var feedbackReceiptSchema = strictObject({
1850
+ eventId: uuidSchema,
1851
+ eventType: agentFeedbackEventTypeSchema,
1852
+ submittedAt: dateStringSchema
1853
+ });
1097
1854
  var exerciseUsageSheetSchema = strictObject({
1098
1855
  id: uuidSchema,
1099
1856
  name: z.string(),
@@ -1103,6 +1860,19 @@ var exerciseUsageSchema = strictObject({
1103
1860
  sheets: z.array(exerciseUsageSheetSchema),
1104
1861
  otherOrganizationSheetCount: z.number().int().min(0)
1105
1862
  });
1863
+ var agentWriteReceiptVersionSchema = z.discriminatedUnion("created", [
1864
+ strictObject({
1865
+ resourceType: z.literal("sheet"),
1866
+ created: z.literal(true),
1867
+ versionId: uuidSchema,
1868
+ versionNumber: z.number().int().positive()
1869
+ }),
1870
+ strictObject({
1871
+ resourceType: z.literal("sheet"),
1872
+ created: z.literal(false),
1873
+ reason: z.string().trim().min(1)
1874
+ })
1875
+ ]);
1106
1876
  var latexValidationIssueSchema = strictObject({
1107
1877
  code: z.enum(latexValidationIssueCodes),
1108
1878
  message: z.string(),
@@ -1170,6 +1940,19 @@ var getSheetAgentInputSchema = strictObject({
1170
1940
  var getSheetAgentOutputSchema = strictObject({
1171
1941
  sheet: sheetDetailsSchema
1172
1942
  });
1943
+ var listSheetVersionsAgentInputSchema = strictObject({
1944
+ id: uuidSchema
1945
+ });
1946
+ var listSheetVersionsAgentOutputSchema = strictObject({
1947
+ versions: z.array(sheetVersionListItemSchema)
1948
+ });
1949
+ var getSheetVersionAgentInputSchema = strictObject({
1950
+ exerciseSheetId: uuidSchema,
1951
+ versionId: uuidSchema
1952
+ });
1953
+ var getSheetVersionAgentOutputSchema = strictObject({
1954
+ version: sheetVersionDetailSchema
1955
+ });
1173
1956
  var getSheetIssuesAgentInputSchema = strictObject({
1174
1957
  id: uuidSchema
1175
1958
  });
@@ -1181,6 +1964,10 @@ var listFoldersAgentInputSchema = strictObject({});
1181
1964
  var listFoldersAgentOutputSchema = strictObject({
1182
1965
  folders: z.array(folderSchema)
1183
1966
  });
1967
+ var listExerciseLabelsAgentInputSchema = strictObject({});
1968
+ var listExerciseLabelsAgentOutputSchema = strictObject({
1969
+ labels: z.array(exerciseLabelSchema)
1970
+ });
1184
1971
  var validateLatexSnippetsAgentInputSchema = strictObject({
1185
1972
  snippets: z.array(
1186
1973
  strictObject({
@@ -1192,6 +1979,22 @@ var validateLatexSnippetsAgentInputSchema = strictObject({
1192
1979
  var validateLatexSnippetsAgentOutputSchema = strictObject({
1193
1980
  results: z.array(latexValidationResultSchema)
1194
1981
  });
1982
+ var sendUserFeedbackAgentInputSchema = strictObject({
1983
+ message: feedbackMessageSchema,
1984
+ userConsent: z.literal(true),
1985
+ category: z.enum(["bug_report", "feature_request", "frustration", "blocked_request", "other"]).optional(),
1986
+ context: feedbackContextSchema
1987
+ });
1988
+ var sendAgentFeedbackAgentInputSchema = strictObject({
1989
+ message: feedbackMessageSchema,
1990
+ category: z.enum(["api_inconsistency", "documentation_issue", "missing_capability", "unexpected_behavior", "other"]).optional(),
1991
+ context: feedbackContextSchema
1992
+ });
1993
+ var feedbackReceiptOutputSchema = strictObject({
1994
+ receipt: feedbackReceiptSchema
1995
+ });
1996
+ var sendUserFeedbackAgentOutputSchema = feedbackReceiptOutputSchema;
1997
+ var sendAgentFeedbackAgentOutputSchema = feedbackReceiptOutputSchema;
1195
1998
  var getExerciseUsageAgentInputSchema = strictObject({
1196
1999
  id: uuidSchema
1197
2000
  });
@@ -1203,7 +2006,7 @@ var agentWriteReceiptSchema = strictObject({
1203
2006
  type: z.enum(["exercise", "sheet", "folder"]),
1204
2007
  id: uuidSchema
1205
2008
  }),
1206
- operation: z.string(),
2009
+ operation: agentWriteReceiptOperationSchema,
1207
2010
  changedPaths: z.array(z.string()),
1208
2011
  precondition: strictObject({
1209
2012
  expectedUpdatedAt: optionalNullableStringSchema,
@@ -1217,6 +2020,7 @@ var agentWriteReceiptSchema = strictObject({
1217
2020
  details: z.unknown().optional()
1218
2021
  })
1219
2022
  ),
2023
+ version: agentWriteReceiptVersionSchema.optional(),
1220
2024
  details: z.unknown()
1221
2025
  });
1222
2026
  var agentWriteReceiptOutputSchema = strictObject({
@@ -1234,6 +2038,23 @@ var copySheetAgentInputSchema = strictObject({
1234
2038
  exerciseCopyMode: z.enum(exerciseSheetExerciseCopyModes).optional().default("keep_references")
1235
2039
  });
1236
2040
  var copySheetAgentOutputSchema = agentWriteReceiptOutputSchema;
2041
+ var deleteExerciseAgentInputSchema = strictObject({
2042
+ id: uuidSchema,
2043
+ expectedUpdatedAt: expectedUpdatedAtSchema,
2044
+ confirmResourceId: uuidSchema
2045
+ });
2046
+ var deleteExerciseAgentOutputSchema = agentWriteReceiptOutputSchema;
2047
+ var deleteSheetAgentInputSchema = strictObject({
2048
+ id: uuidSchema,
2049
+ expectedUpdatedAt: expectedUpdatedAtSchema,
2050
+ confirmResourceId: uuidSchema
2051
+ });
2052
+ var deleteSheetAgentOutputSchema = agentWriteReceiptOutputSchema;
2053
+ var deleteFolderAgentInputSchema = strictObject({
2054
+ id: uuidSchema,
2055
+ confirmResourceId: uuidSchema
2056
+ });
2057
+ var deleteFolderAgentOutputSchema = agentWriteReceiptOutputSchema;
1237
2058
  var createFolderAgentInputSchema = strictObject({
1238
2059
  name: z.string().trim().min(1),
1239
2060
  parentId: uuidSchema.nullable().optional()
@@ -1257,11 +2078,34 @@ var exercisePatchFigureSchema = strictObject({
1257
2078
  url: z.url(),
1258
2079
  widthInCm: z.number().positive().finite().nullable().optional()
1259
2080
  });
2081
+ var exerciseCreateFigureSchema = strictObject({
2082
+ type: z.enum(exerciseFigureTypes),
2083
+ url: z.url(),
2084
+ widthInCm: z.number().positive().finite().optional()
2085
+ });
1260
2086
  var exercisePatchMetadataSchema = strictObject({
1261
2087
  sourceUrl: patchNullableStringSchema,
1262
2088
  solutionUrl: patchNullableStringSchema,
1263
2089
  figures: z.array(exercisePatchFigureSchema).optional()
1264
2090
  });
2091
+ var exerciseCreateMetadataSchema = strictObject({
2092
+ sourceUrl: z.url().optional(),
2093
+ solutionUrl: z.url().optional(),
2094
+ figures: z.array(exerciseCreateFigureSchema).optional()
2095
+ });
2096
+ var createExerciseAgentInputSchema = strictObject({
2097
+ difficulty: z.number().min(1).max(100).nullable().optional(),
2098
+ min_age: z.number().min(0).max(100).nullable().optional(),
2099
+ max_age: z.number().min(0).max(100).nullable().optional(),
2100
+ source: z.string().trim().min(1).optional(),
2101
+ metadata: exerciseCreateMetadataSchema.optional(),
2102
+ labels: z.array(z.string()).max(30).optional(),
2103
+ private_notes: z.string().optional(),
2104
+ translations: z.record(z.string(), exercisePatchTranslationSchema),
2105
+ exerciseSheetId: uuidSchema.optional(),
2106
+ confirmMakeExercisesPublic: z.boolean().optional().default(false)
2107
+ });
2108
+ var createExerciseAgentOutputSchema = agentWriteReceiptOutputSchema;
1265
2109
  var updateExerciseAgentInputSchema = strictObject({
1266
2110
  id: uuidSchema,
1267
2111
  expectedUpdatedAt: expectedUpdatedAtSchema,
@@ -1295,12 +2139,43 @@ var updateSheetAgentInputSchema = strictObject({
1295
2139
  })
1296
2140
  });
1297
2141
  var updateSheetAgentOutputSchema = agentWriteReceiptOutputSchema;
2142
+ var createSheetScoredExerciseSchema = strictObject({
2143
+ id: uuidSchema,
2144
+ scorePoints: z.number().min(0).max(99999.9).refine((value) => Number.isInteger(value * 10), "Score can have at most 1 decimal place").nullable()
2145
+ });
2146
+ var createSheetAgentInputSchema = strictObject({
2147
+ name: z.string().trim().min(1),
2148
+ title: z.string().trim().nullable().optional(),
2149
+ description: z.string().trim().optional(),
2150
+ language: z.enum(translationLanguages),
2151
+ exerciseIds: z.array(uuidSchema).max(200).optional(),
2152
+ exercises: z.array(createSheetScoredExerciseSchema).max(200).optional(),
2153
+ scoringEnabled: z.boolean().optional().default(false),
2154
+ private_notes: z.string().optional()
2155
+ }).refine((data) => data.exerciseIds === void 0 || data.exercises === void 0, {
2156
+ message: "Use exercises instead of exerciseIds when creating score values"
2157
+ });
2158
+ var createSheetAgentOutputSchema = agentWriteReceiptOutputSchema;
1298
2159
  var appendExercisesToSheetAgentInputSchema = strictObject({
1299
2160
  sheetId: uuidSchema,
1300
2161
  exerciseIds: z.array(uuidSchema).min(1),
1301
2162
  confirmMakeExercisesPublic: z.boolean().optional().default(false)
1302
2163
  });
1303
2164
  var appendExercisesToSheetAgentOutputSchema = agentWriteReceiptOutputSchema;
2165
+ var setExerciseVisibilityAgentInputSchema = strictObject({
2166
+ id: uuidSchema,
2167
+ expectedUpdatedAt: expectedUpdatedAtSchema,
2168
+ isPublic: z.boolean(),
2169
+ confirmMakePublicResourceId: uuidSchema.optional()
2170
+ });
2171
+ var setExerciseVisibilityAgentOutputSchema = agentWriteReceiptOutputSchema;
2172
+ var setSheetVisibilityAgentInputSchema = strictObject({
2173
+ id: uuidSchema,
2174
+ expectedUpdatedAt: expectedUpdatedAtSchema,
2175
+ isPublic: z.boolean(),
2176
+ confirmMakePublicResourceId: uuidSchema.optional()
2177
+ });
2178
+ var setSheetVisibilityAgentOutputSchema = agentWriteReceiptOutputSchema;
1304
2179
 
1305
2180
  // ../shared/src/agent-tools/mcp-tools.ts
1306
2181
  import { z as z3 } from "zod";
@@ -1516,14 +2391,30 @@ var getExerciseUsageInputSchema = getExerciseUsageAgentInputSchema.extend({
1516
2391
  organizationId: organizationIdSchema
1517
2392
  });
1518
2393
  var getExerciseUsageOutputSchema = getExerciseUsageAgentOutputSchema;
2394
+ var listExerciseLabelsInputSchema = listExerciseLabelsAgentInputSchema.extend({
2395
+ organizationId: organizationIdSchema
2396
+ });
2397
+ var listExerciseLabelsOutputSchema = listExerciseLabelsAgentOutputSchema;
1519
2398
  var copyExerciseInputSchema = copyExerciseAgentInputSchema.extend({
1520
2399
  organizationId: organizationIdSchema
1521
2400
  });
1522
2401
  var copyExerciseOutputSchema = copyExerciseAgentOutputSchema;
2402
+ var deleteExerciseInputSchema = deleteExerciseAgentInputSchema.extend({
2403
+ organizationId: organizationIdSchema
2404
+ });
2405
+ var deleteExerciseOutputSchema = deleteExerciseAgentOutputSchema;
2406
+ var createExerciseInputSchema = createExerciseAgentInputSchema.extend({
2407
+ organizationId: organizationIdSchema
2408
+ });
2409
+ var createExerciseOutputSchema = createExerciseAgentOutputSchema;
1523
2410
  var updateExerciseInputSchema = updateExerciseAgentInputSchema.extend({
1524
2411
  organizationId: organizationIdSchema
1525
2412
  });
1526
2413
  var updateExerciseOutputSchema = updateExerciseAgentOutputSchema;
2414
+ var setExerciseVisibilityInputSchema = setExerciseVisibilityAgentInputSchema.extend({
2415
+ organizationId: organizationIdSchema
2416
+ });
2417
+ var setExerciseVisibilityOutputSchema = setExerciseVisibilityAgentOutputSchema;
1527
2418
  var importExerciseInputSchema = strictObject2({
1528
2419
  organizationId: organizationIdSchema,
1529
2420
  sources: importSourcesSchema,
@@ -1562,6 +2453,14 @@ var getSheetInputSchema = getSheetAgentInputSchema.extend({
1562
2453
  organizationId: organizationIdSchema
1563
2454
  });
1564
2455
  var getSheetOutputSchema = getSheetAgentOutputSchema;
2456
+ var listSheetVersionsInputSchema = listSheetVersionsAgentInputSchema.extend({
2457
+ organizationId: organizationIdSchema
2458
+ });
2459
+ var listSheetVersionsOutputSchema = listSheetVersionsAgentOutputSchema;
2460
+ var getSheetVersionInputSchema = getSheetVersionAgentInputSchema.extend({
2461
+ organizationId: organizationIdSchema
2462
+ });
2463
+ var getSheetVersionOutputSchema = getSheetVersionAgentOutputSchema;
1565
2464
  var getSheetIssuesInputSchema = getSheetIssuesAgentInputSchema.extend({
1566
2465
  organizationId: organizationIdSchema
1567
2466
  });
@@ -1570,10 +2469,22 @@ var copySheetInputSchema = copySheetAgentInputSchema.extend({
1570
2469
  organizationId: organizationIdSchema
1571
2470
  });
1572
2471
  var copySheetOutputSchema = copySheetAgentOutputSchema;
2472
+ var deleteSheetInputSchema = deleteSheetAgentInputSchema.extend({
2473
+ organizationId: organizationIdSchema
2474
+ });
2475
+ var deleteSheetOutputSchema = deleteSheetAgentOutputSchema;
2476
+ var createSheetInputSchema = createSheetAgentInputSchema.extend({
2477
+ organizationId: organizationIdSchema
2478
+ });
2479
+ var createSheetOutputSchema = createSheetAgentOutputSchema;
1573
2480
  var updateSheetInputSchema = updateSheetAgentInputSchema.extend({
1574
2481
  organizationId: organizationIdSchema
1575
2482
  });
1576
2483
  var updateSheetOutputSchema = updateSheetAgentOutputSchema;
2484
+ var setSheetVisibilityInputSchema = setSheetVisibilityAgentInputSchema.extend({
2485
+ organizationId: organizationIdSchema
2486
+ });
2487
+ var setSheetVisibilityOutputSchema = setSheetVisibilityAgentOutputSchema;
1577
2488
  var appendExercisesToSheetInputSchema = appendExercisesToSheetAgentInputSchema.extend({
1578
2489
  organizationId: organizationIdSchema
1579
2490
  });
@@ -1582,6 +2493,18 @@ var listFoldersInputSchema = listFoldersAgentInputSchema.extend({
1582
2493
  organizationId: organizationIdSchema
1583
2494
  });
1584
2495
  var listFoldersOutputSchema = listFoldersAgentOutputSchema;
2496
+ var sendUserFeedbackInputSchema = sendUserFeedbackAgentInputSchema.extend({
2497
+ organizationId: organizationIdSchema
2498
+ });
2499
+ var sendUserFeedbackOutputSchema = sendUserFeedbackAgentOutputSchema;
2500
+ var sendAgentFeedbackInputSchema = sendAgentFeedbackAgentInputSchema.extend({
2501
+ organizationId: organizationIdSchema
2502
+ });
2503
+ var sendAgentFeedbackOutputSchema = sendAgentFeedbackAgentOutputSchema;
2504
+ var deleteFolderInputSchema = deleteFolderAgentInputSchema.extend({
2505
+ organizationId: organizationIdSchema
2506
+ });
2507
+ var deleteFolderOutputSchema = deleteFolderAgentOutputSchema;
1585
2508
  var createFolderInputSchema = createFolderAgentInputSchema.extend({
1586
2509
  organizationId: organizationIdSchema
1587
2510
  });
@@ -1693,6 +2616,16 @@ var chalksurfMcpToolCapabilities = {
1693
2616
  requiredPermission: "read",
1694
2617
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
1695
2618
  },
2619
+ list_exercise_labels: {
2620
+ name: "list_exercise_labels",
2621
+ title: "List exercise labels",
2622
+ description: "Use this to discover canonical ChalkSurf exercise label IDs before creating or updating exercises.",
2623
+ inputSchema: listExerciseLabelsInputSchema,
2624
+ outputSchema: listExerciseLabelsOutputSchema,
2625
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
2626
+ requiredPermission: "read",
2627
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
2628
+ },
1696
2629
  copy_exercise: {
1697
2630
  name: "copy_exercise",
1698
2631
  title: "Copy exercise",
@@ -1703,6 +2636,26 @@ var chalksurfMcpToolCapabilities = {
1703
2636
  requiredPermission: "write",
1704
2637
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
1705
2638
  },
2639
+ delete_exercise: {
2640
+ name: "delete_exercise",
2641
+ title: "Delete exercise",
2642
+ description: "Use this to soft-delete one writable exercise after checking updated_at and exact destructive confirmation.",
2643
+ inputSchema: deleteExerciseInputSchema,
2644
+ outputSchema: deleteExerciseOutputSchema,
2645
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
2646
+ requiredPermission: "write",
2647
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2648
+ },
2649
+ create_exercise: {
2650
+ name: "create_exercise",
2651
+ title: "Create exercise",
2652
+ description: "Use this to create one exercise in the selected ChalkSurf organization.",
2653
+ inputSchema: createExerciseInputSchema,
2654
+ outputSchema: createExerciseOutputSchema,
2655
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2656
+ requiredPermission: "write",
2657
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2658
+ },
1706
2659
  update_exercise: {
1707
2660
  name: "update_exercise",
1708
2661
  title: "Update exercise",
@@ -1713,6 +2666,16 @@ var chalksurfMcpToolCapabilities = {
1713
2666
  requiredPermission: "write",
1714
2667
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
1715
2668
  },
2669
+ set_exercise_visibility: {
2670
+ name: "set_exercise_visibility",
2671
+ title: "Set exercise visibility",
2672
+ description: "Use this to make one writable exercise public or private after checking updated_at and visibility policy.",
2673
+ inputSchema: setExerciseVisibilityInputSchema,
2674
+ outputSchema: setExerciseVisibilityOutputSchema,
2675
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2676
+ requiredPermission: "write",
2677
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2678
+ },
1716
2679
  import_exercise: {
1717
2680
  name: "import_exercise",
1718
2681
  title: "Import exercise",
@@ -1753,6 +2716,26 @@ var chalksurfMcpToolCapabilities = {
1753
2716
  requiredPermission: "read",
1754
2717
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
1755
2718
  },
2719
+ list_sheet_versions: {
2720
+ name: "list_sheet_versions",
2721
+ title: "List sheet versions",
2722
+ description: "Use this to inspect the version history for one owned exercise sheet.",
2723
+ inputSchema: listSheetVersionsInputSchema,
2724
+ outputSchema: listSheetVersionsOutputSchema,
2725
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
2726
+ requiredPermission: "read",
2727
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
2728
+ },
2729
+ get_sheet_version: {
2730
+ name: "get_sheet_version",
2731
+ title: "Get sheet version",
2732
+ description: "Use this to fetch one owned exercise sheet version snapshot with its referenced exercise details.",
2733
+ inputSchema: getSheetVersionInputSchema,
2734
+ outputSchema: getSheetVersionOutputSchema,
2735
+ annotations: { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false },
2736
+ requiredPermission: "read",
2737
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
2738
+ },
1756
2739
  get_sheet_issues: {
1757
2740
  name: "get_sheet_issues",
1758
2741
  title: "Get sheet issues",
@@ -1773,6 +2756,26 @@ var chalksurfMcpToolCapabilities = {
1773
2756
  requiredPermission: "write",
1774
2757
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
1775
2758
  },
2759
+ delete_sheet: {
2760
+ name: "delete_sheet",
2761
+ title: "Delete sheet",
2762
+ description: "Use this to soft-delete one writable exercise sheet after checking updated_at and exact destructive confirmation.",
2763
+ inputSchema: deleteSheetInputSchema,
2764
+ outputSchema: deleteSheetOutputSchema,
2765
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
2766
+ requiredPermission: "write",
2767
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2768
+ },
2769
+ create_sheet: {
2770
+ name: "create_sheet",
2771
+ title: "Create sheet",
2772
+ description: "Use this to create one exercise sheet in the selected ChalkSurf organization.",
2773
+ inputSchema: createSheetInputSchema,
2774
+ outputSchema: createSheetOutputSchema,
2775
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2776
+ requiredPermission: "write",
2777
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2778
+ },
1776
2779
  update_sheet: {
1777
2780
  name: "update_sheet",
1778
2781
  title: "Update sheet",
@@ -1783,6 +2786,16 @@ var chalksurfMcpToolCapabilities = {
1783
2786
  requiredPermission: "write",
1784
2787
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
1785
2788
  },
2789
+ set_sheet_visibility: {
2790
+ name: "set_sheet_visibility",
2791
+ title: "Set sheet visibility",
2792
+ description: "Use this to make one writable exercise sheet public or private after checking updated_at and visibility policy.",
2793
+ inputSchema: setSheetVisibilityInputSchema,
2794
+ outputSchema: setSheetVisibilityOutputSchema,
2795
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2796
+ requiredPermission: "write",
2797
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2798
+ },
1786
2799
  append_exercises_to_sheet: {
1787
2800
  name: "append_exercises_to_sheet",
1788
2801
  title: "Append exercises to sheet",
@@ -1803,6 +2816,36 @@ var chalksurfMcpToolCapabilities = {
1803
2816
  requiredPermission: "read",
1804
2817
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
1805
2818
  },
2819
+ send_user_feedback: {
2820
+ name: "send_user_feedback",
2821
+ title: "Send user feedback",
2822
+ description: "Use this only after the user explicitly asks you to send feedback or agrees to send a bug report or feature request.",
2823
+ inputSchema: sendUserFeedbackInputSchema,
2824
+ outputSchema: sendUserFeedbackOutputSchema,
2825
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2826
+ requiredPermission: "read",
2827
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
2828
+ },
2829
+ send_agent_feedback: {
2830
+ name: "send_agent_feedback",
2831
+ title: "Send agent feedback",
2832
+ description: "Use this when you observe a ChalkSurf CLI, MCP, API, or documentation inconsistency while using agent tools.",
2833
+ inputSchema: sendAgentFeedbackInputSchema,
2834
+ outputSchema: sendAgentFeedbackOutputSchema,
2835
+ annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
2836
+ requiredPermission: "read",
2837
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
2838
+ },
2839
+ delete_folder: {
2840
+ name: "delete_folder",
2841
+ title: "Delete folder",
2842
+ description: "Use this to delete one empty exercise sheet folder after exact destructive confirmation.",
2843
+ inputSchema: deleteFolderInputSchema,
2844
+ outputSchema: deleteFolderOutputSchema,
2845
+ annotations: { readOnlyHint: false, destructiveHint: true, idempotentHint: false, openWorldHint: false },
2846
+ requiredPermission: "write",
2847
+ security: { type: "oauth2", scopes: [chalksurfMcpScopes.write] }
2848
+ },
1806
2849
  create_folder: {
1807
2850
  name: "create_folder",
1808
2851
  title: "Create folder",
@@ -1883,14 +2926,582 @@ var chalksurfMcpToolCapabilities = {
1883
2926
  requiredPermission: "read",
1884
2927
  security: { type: "oauth2", scopes: [chalksurfMcpScopes.read] }
1885
2928
  }
1886
- };
2929
+ };
2930
+
2931
+ // ../shared/src/export-layout/preview-layout-settings.ts
2932
+ import { z as z4 } from "zod";
2933
+ var worksheetPreviewLayoutSettingsVersion = 1;
2934
+ var worksheetWorkspaceFillModes = ["empty", "lines", "grid"];
2935
+ var worksheetPreviewLayoutSettingsLimits = {
2936
+ fontSizePt: {
2937
+ min: 8,
2938
+ max: 18,
2939
+ default: 12
2940
+ },
2941
+ figureWidthInCm: {
2942
+ min: 1,
2943
+ max: 16,
2944
+ default: 6
2945
+ },
2946
+ workspaceHeightInCm: {
2947
+ min: 1,
2948
+ max: 12,
2949
+ default: 4
2950
+ }
2951
+ };
2952
+ var defaultWorksheetPreviewLayoutSettings = {
2953
+ version: worksheetPreviewLayoutSettingsVersion,
2954
+ fontSizePt: worksheetPreviewLayoutSettingsLimits.fontSizePt.default,
2955
+ figureOverridesByBlockId: {},
2956
+ workspaceOverridesByExerciseId: {}
2957
+ };
2958
+ var finiteNumberSchema = z4.number().finite();
2959
+ var worksheetPreviewLayoutSettingsSchema = z4.object({
2960
+ version: z4.literal(worksheetPreviewLayoutSettingsVersion),
2961
+ fontSizePt: finiteNumberSchema.optional(),
2962
+ figureOverridesByBlockId: z4.record(
2963
+ z4.string().min(1),
2964
+ z4.object({
2965
+ widthInCm: finiteNumberSchema.optional(),
2966
+ placement: z4.unknown().optional()
2967
+ })
2968
+ ).optional(),
2969
+ workspaceOverridesByExerciseId: z4.record(
2970
+ z4.string().min(1),
2971
+ z4.object({
2972
+ heightInCm: finiteNumberSchema.optional(),
2973
+ fillMode: z4.unknown().optional()
2974
+ })
2975
+ ).optional()
2976
+ });
2977
+
2978
+ // ../shared/src/export-layout/types.ts
2979
+ import { z as z5 } from "zod";
2980
+ var worksheetLayoutVersion = 1;
2981
+ var defaultWorksheetPageSettings = {
2982
+ size: "A4",
2983
+ widthMm: 210,
2984
+ heightMm: 297,
2985
+ marginMm: {
2986
+ top: 16,
2987
+ right: 18,
2988
+ bottom: 16,
2989
+ left: 18
2990
+ }
2991
+ };
2992
+ var worksheetLayoutBlockTypes = [
2993
+ "sheet-title",
2994
+ "sheet-description",
2995
+ "exercise",
2996
+ "exercise-text",
2997
+ "figure",
2998
+ "workspace",
2999
+ "answer",
3000
+ "detailed-solution"
3001
+ ];
3002
+ var baseWorksheetLayoutBlockSchema = z5.object({
3003
+ id: z5.string().min(1),
3004
+ type: z5.enum(worksheetLayoutBlockTypes),
3005
+ exerciseId: z5.string().min(1).optional()
3006
+ });
3007
+ var worksheetLayoutBlockSchema = z5.lazy(
3008
+ () => z5.discriminatedUnion("type", [
3009
+ baseWorksheetLayoutBlockSchema.extend({
3010
+ type: z5.literal("sheet-title"),
3011
+ text: z5.string()
3012
+ }),
3013
+ baseWorksheetLayoutBlockSchema.extend({
3014
+ type: z5.literal("sheet-description"),
3015
+ text: z5.string()
3016
+ }),
3017
+ baseWorksheetLayoutBlockSchema.extend({
3018
+ type: z5.literal("exercise-text"),
3019
+ exerciseId: z5.string().min(1),
3020
+ text: z5.string()
3021
+ }),
3022
+ baseWorksheetLayoutBlockSchema.extend({
3023
+ type: z5.literal("answer"),
3024
+ exerciseId: z5.string().min(1),
3025
+ text: z5.string()
3026
+ }),
3027
+ baseWorksheetLayoutBlockSchema.extend({
3028
+ type: z5.literal("detailed-solution"),
3029
+ exerciseId: z5.string().min(1),
3030
+ text: z5.string()
3031
+ }),
3032
+ baseWorksheetLayoutBlockSchema.extend({
3033
+ type: z5.literal("exercise"),
3034
+ exerciseId: z5.string().min(1),
3035
+ exerciseNumber: z5.number().int().positive(),
3036
+ scorePoints: z5.number().nullable(),
3037
+ children: z5.array(worksheetLayoutBlockSchema)
3038
+ }),
3039
+ baseWorksheetLayoutBlockSchema.extend({
3040
+ type: z5.literal("figure"),
3041
+ exerciseId: z5.string().min(1),
3042
+ figure: z5.object({
3043
+ type: z5.enum(["text", "solution"]),
3044
+ url: z5.string(),
3045
+ widthInCm: z5.number().positive()
3046
+ }),
3047
+ figureNumber: z5.number().int().positive()
3048
+ }),
3049
+ baseWorksheetLayoutBlockSchema.extend({
3050
+ type: z5.literal("workspace"),
3051
+ exerciseId: z5.string().min(1),
3052
+ heightInCm: z5.number().nonnegative(),
3053
+ fillMode: z5.enum(worksheetWorkspaceFillModes)
3054
+ })
3055
+ ])
3056
+ );
3057
+ var worksheetLayoutDocumentSchema = z5.object({
3058
+ version: z5.literal(worksheetLayoutVersion),
3059
+ title: z5.string(),
3060
+ description: z5.string().nullable(),
3061
+ language: z5.enum(translationLanguages),
3062
+ blocks: z5.array(worksheetLayoutBlockSchema)
3063
+ });
3064
+ var worksheetRenderDiagnosticCodes = [
3065
+ "unclosed_latex_delimiter",
3066
+ "katex_render_error",
3067
+ "missing_katex_renderer",
3068
+ "image_load_error",
3069
+ "html_render_error",
3070
+ "layout_measurement_error",
3071
+ "page_overflow"
3072
+ ];
3073
+ var worksheetPageSegmentSchema = z5.discriminatedUnion("type", [
3074
+ z5.object({
3075
+ type: z5.literal("standalone"),
3076
+ unitId: z5.string().min(1),
3077
+ blockId: z5.string().min(1),
3078
+ heightPx: z5.number().finite().nonnegative()
3079
+ }),
3080
+ z5.object({
3081
+ type: z5.literal("exercise"),
3082
+ unitId: z5.string().min(1),
3083
+ blockId: z5.string().min(1),
3084
+ exerciseId: z5.string().min(1),
3085
+ includeHeading: z5.boolean(),
3086
+ childUnitIds: z5.array(z5.string().min(1)),
3087
+ heightPx: z5.number().finite().nonnegative(),
3088
+ isContinuation: z5.boolean(),
3089
+ overflow: z5.boolean()
3090
+ })
3091
+ ]);
3092
+ var worksheetPaginationPlanSchema = z5.object({
3093
+ pages: z5.array(
3094
+ z5.object({
3095
+ pageNumber: z5.number().int().positive(),
3096
+ segments: z5.array(worksheetPageSegmentSchema),
3097
+ usedHeightPx: z5.number().finite().nonnegative()
3098
+ })
3099
+ ),
3100
+ diagnostics: z5.array(
3101
+ z5.object({
3102
+ code: z5.enum(worksheetRenderDiagnosticCodes),
3103
+ severity: z5.enum(["error", "warning"]),
3104
+ message: z5.string(),
3105
+ blockId: z5.string().optional(),
3106
+ exerciseId: z5.string().optional(),
3107
+ snippet: z5.string().optional()
3108
+ })
3109
+ ),
3110
+ metrics: z5.object({
3111
+ pageCount: z5.number().int().positive(),
3112
+ measuredUnitCount: z5.number().int().nonnegative(),
3113
+ overflowCount: z5.number().int().nonnegative()
3114
+ })
3115
+ });
3116
+
3117
+ // ../shared/src/export-layout/document-css.ts
3118
+ var { heightMm, marginMm, widthMm } = defaultWorksheetPageSettings;
3119
+ var worksheetDocumentCss = `
3120
+ @page {
3121
+ size: ${widthMm}mm ${heightMm}mm;
3122
+ margin: 0;
3123
+ }
3124
+
3125
+ .cs-worksheet {
3126
+ box-sizing: border-box;
3127
+ color: #111;
3128
+ font-family: "STIX Two Text", "Latin Modern Roman", "Libertinus Serif", Cambria, Georgia, serif;
3129
+ font-size: 12pt;
3130
+ line-height: 1.45;
3131
+ }
3132
+
3133
+ .cs-worksheet *,
3134
+ .cs-worksheet *::before,
3135
+ .cs-worksheet *::after {
3136
+ box-sizing: border-box;
3137
+ }
3138
+
3139
+ .cs-worksheet .katex {
3140
+ padding: 0;
3141
+ }
3142
+
3143
+ .cs-worksheet--continuous {
3144
+ width: ${widthMm}mm;
3145
+ padding: ${marginMm.top}mm ${marginMm.right}mm ${marginMm.bottom}mm ${marginMm.left}mm;
3146
+ background: #fff;
3147
+ }
3148
+
3149
+ .cs-worksheet--paged {
3150
+ display: flex;
3151
+ flex-direction: column;
3152
+ gap: 16px;
3153
+ }
3154
+
3155
+ .cs-worksheet__page {
3156
+ width: ${widthMm}mm;
3157
+ min-height: ${heightMm}mm;
3158
+ margin-left: auto;
3159
+ margin-right: auto;
3160
+ padding: ${marginMm.top}mm ${marginMm.right}mm ${marginMm.bottom}mm ${marginMm.left}mm;
3161
+ background: #fff;
3162
+ box-shadow: 0 4px 18px rgba(0, 0, 0, 0.18);
3163
+ }
3164
+
3165
+ .cs-worksheet__title {
3166
+ margin: 0 0 40px;
3167
+ font-size: 20pt;
3168
+ font-weight: 700;
3169
+ line-height: 1.2;
3170
+ text-align: center;
3171
+ }
3172
+
3173
+ .cs-worksheet__exercise-list {
3174
+ margin: 0;
3175
+ padding: 0;
3176
+ list-style: none;
3177
+ }
3178
+
3179
+ .cs-worksheet__exercise {
3180
+ margin-bottom: 32px;
3181
+ break-inside: avoid;
3182
+ }
3183
+
3184
+ .cs-worksheet__exercise:last-child {
3185
+ margin-bottom: 0;
3186
+ }
3187
+
3188
+ .cs-worksheet__exercise-heading {
3189
+ display: flex;
3190
+ justify-content: space-between;
3191
+ align-items: baseline;
3192
+ gap: 16px;
3193
+ margin-bottom: 8px;
3194
+ }
3195
+
3196
+ .cs-worksheet__exercise-title {
3197
+ margin: 0;
3198
+ font-size: 13pt;
3199
+ font-weight: 700;
3200
+ line-height: 1.3;
3201
+ }
3202
+
3203
+ .cs-worksheet__exercise-score {
3204
+ font-size: 10pt;
3205
+ white-space: nowrap;
3206
+ }
3207
+
3208
+ .cs-worksheet__exercise-text,
3209
+ .cs-worksheet__subsection-content {
3210
+ overflow-wrap: anywhere;
3211
+ }
3212
+
3213
+ .cs-worksheet__exercise-text::after,
3214
+ .cs-worksheet__subsection-content::after {
3215
+ content: "";
3216
+ display: block;
3217
+ clear: both;
3218
+ }
3219
+
3220
+ .cs-worksheet__math--display {
3221
+ display: block;
3222
+ margin-top: 8px;
3223
+ margin-bottom: 8px;
3224
+ text-align: center;
3225
+ }
3226
+
3227
+ .cs-worksheet__figure {
3228
+ margin: 16px 0;
3229
+ text-align: center;
3230
+ break-inside: avoid;
3231
+ position: relative;
3232
+ outline-offset: 2px;
3233
+ }
3234
+
3235
+ .cs-worksheet__figure--left {
3236
+ text-align: left;
3237
+ }
3238
+
3239
+ .cs-worksheet__figure--center {
3240
+ text-align: center;
3241
+ }
3242
+
3243
+ .cs-worksheet__figure--right {
3244
+ text-align: right;
3245
+ }
3246
+
3247
+ .cs-worksheet__figure--float-left {
3248
+ float: left;
3249
+ max-width: 55%;
3250
+ margin: 0 12px 8px 0;
3251
+ text-align: left;
3252
+ }
3253
+
3254
+ .cs-worksheet__figure--float-right {
3255
+ float: right;
3256
+ max-width: 55%;
3257
+ margin: 0 0 8px 12px;
3258
+ text-align: right;
3259
+ }
3260
+
3261
+ .cs-worksheet__figure img {
3262
+ height: auto;
3263
+ }
3264
+
3265
+ .cs-worksheet__figure-row {
3266
+ display: flex;
3267
+ flex-wrap: nowrap;
3268
+ align-items: flex-start;
3269
+ margin-top: 16px;
3270
+ margin-bottom: 16px;
3271
+ break-inside: avoid;
3272
+ clear: both;
3273
+ width: 100%;
3274
+ }
3275
+
3276
+ .cs-worksheet__figure-row-spacer {
3277
+ flex: 1 1 auto;
3278
+ min-width: 0;
3279
+ }
3280
+
3281
+ .cs-worksheet__figure-row-slot {
3282
+ display: flex;
3283
+ flex: 0 0 auto;
3284
+ align-items: flex-start;
3285
+ gap: 8mm;
3286
+ min-width: 0;
3287
+ }
3288
+
3289
+ .cs-worksheet__figure-row-slot--left {
3290
+ justify-content: flex-start;
3291
+ }
3292
+
3293
+ .cs-worksheet__figure-row-slot--center {
3294
+ justify-content: center;
3295
+ }
3296
+
3297
+ .cs-worksheet__figure-row-slot--right {
3298
+ justify-content: flex-end;
3299
+ }
3300
+
3301
+ .cs-worksheet__figure-row .cs-worksheet__figure {
3302
+ margin-top: 0;
3303
+ margin-bottom: 0;
3304
+ flex: 0 1 auto;
3305
+ }
3306
+
3307
+ .cs-worksheet__workspace {
3308
+ margin-top: 12px;
3309
+ break-inside: avoid;
3310
+ background-color: #fff;
3311
+ -webkit-print-color-adjust: exact;
3312
+ print-color-adjust: exact;
3313
+ outline-offset: 2px;
3314
+ clear: both;
3315
+ }
3316
+
3317
+ .cs-worksheet__workspace--lines {
3318
+ background-image: linear-gradient(
3319
+ to bottom,
3320
+ #c9d4dc 0,
3321
+ #c9d4dc 0.2mm,
3322
+ transparent 0.2mm
3323
+ );
3324
+ background-size: 100% 7mm;
3325
+ background-repeat: repeat;
3326
+ }
3327
+
3328
+ .cs-worksheet__workspace--grid {
3329
+ background-image:
3330
+ linear-gradient(
3331
+ to right,
3332
+ #d3dce3 0,
3333
+ #d3dce3 0.2mm,
3334
+ transparent 0.2mm
3335
+ ),
3336
+ linear-gradient(
3337
+ to bottom,
3338
+ #d3dce3 0,
3339
+ #d3dce3 0.2mm,
3340
+ transparent 0.2mm
3341
+ );
3342
+ background-size: 5mm 5mm;
3343
+ background-repeat: repeat;
3344
+ }
3345
+
3346
+ .cs-worksheet__subsection {
3347
+ margin-top: 16px;
3348
+ break-inside: avoid;
3349
+ clear: both;
3350
+ }
3351
+
3352
+ .cs-worksheet__subsection-title {
3353
+ margin: 0 0 4px;
3354
+ font-size: 11pt;
3355
+ font-weight: 700;
3356
+ }
3357
+
3358
+ @media print {
3359
+ .cs-worksheet--paged {
3360
+ display: block;
3361
+ gap: 0;
3362
+ }
3363
+
3364
+ .cs-worksheet__page {
3365
+ margin: 0;
3366
+ box-shadow: none;
3367
+ break-after: page;
3368
+ page-break-after: always;
3369
+ }
3370
+
3371
+ .cs-worksheet__page:last-child {
3372
+ break-after: auto;
3373
+ page-break-after: auto;
3374
+ }
3375
+ }
3376
+ `.trim();
3377
+ var worksheetHtmlDocumentShellCss = `
3378
+ html,
3379
+ body {
3380
+ margin: 0;
3381
+ padding: 0;
3382
+ }
3383
+ `.trim();
3384
+
3385
+ // ../shared/src/export-layout/html-pdf-export.ts
3386
+ import { z as z6 } from "zod";
3387
+ var worksheetHtmlPdfExportPayloadVersion = 1;
3388
+ var worksheetHtmlPdfExportPayloadSchema = z6.object({
3389
+ version: z6.literal(worksheetHtmlPdfExportPayloadVersion),
3390
+ layoutSettings: worksheetPreviewLayoutSettingsSchema,
3391
+ paginationPlan: worksheetPaginationPlanSchema
3392
+ });
3393
+ var scorePointsSchema = z6.number().min(0, "Score must be greater than or equal to 0").max(99999.9, "Score must be less than or equal to 99999.9").refine((value) => Number.isInteger(value * 10), "Score can have at most 1 decimal place");
3394
+ var worksheetExportTemplateInputShape = {
3395
+ language: z6.enum(translationLanguages),
3396
+ templateId: z6.enum(exportTemplateIds).default("exercises"),
3397
+ parameters: z6.record(z6.string(), z6.unknown()).default({}),
3398
+ layoutSettings: worksheetPreviewLayoutSettingsSchema.optional()
3399
+ };
3400
+ var worksheetPersistedExportSourceInputSchema = z6.object({
3401
+ source: z6.enum(["saved-sheet", "public-sheet"]).default("saved-sheet"),
3402
+ id: z6.uuid(),
3403
+ ...worksheetExportTemplateInputShape
3404
+ });
3405
+ var worksheetLocalExportExerciseInputSchema = z6.object({
3406
+ id: z6.uuid("Invalid UUID"),
3407
+ scorePoints: scorePointsSchema.nullable()
3408
+ });
3409
+ var worksheetLocalExportSourceInputSchema = z6.object({
3410
+ source: z6.literal("local-sheet"),
3411
+ title: z6.string().trim().min(1, "Title is required"),
3412
+ scoringEnabled: z6.boolean().default(false),
3413
+ exercises: z6.array(worksheetLocalExportExerciseInputSchema).max(100).default([]),
3414
+ ...worksheetExportTemplateInputShape
3415
+ });
3416
+ var worksheetExportSourceInputSchema = z6.union([
3417
+ worksheetPersistedExportSourceInputSchema,
3418
+ worksheetLocalExportSourceInputSchema
3419
+ ]);
3420
+ var worksheetHtmlPdfExportInputSchema = z6.union([
3421
+ worksheetPersistedExportSourceInputSchema.extend({
3422
+ htmlExport: worksheetHtmlPdfExportPayloadSchema
3423
+ }),
3424
+ worksheetLocalExportSourceInputSchema.extend({
3425
+ htmlExport: worksheetHtmlPdfExportPayloadSchema
3426
+ })
3427
+ ]);
3428
+
3429
+ // ../../node_modules/entities/dist/esm/decode-codepoint.js
3430
+ var _a;
3431
+ var fromCodePoint = (
3432
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition, n/no-unsupported-features/es-builtins
3433
+ (_a = String.fromCodePoint) !== null && _a !== void 0 ? _a : function(codePoint) {
3434
+ let output = "";
3435
+ if (codePoint > 65535) {
3436
+ codePoint -= 65536;
3437
+ output += String.fromCharCode(codePoint >>> 10 & 1023 | 55296);
3438
+ codePoint = 56320 | codePoint & 1023;
3439
+ }
3440
+ output += String.fromCharCode(codePoint);
3441
+ return output;
3442
+ }
3443
+ );
1887
3444
 
1888
- // ../shared/src/helpers/latex/exercise-translation-latex.ts
1889
- var hintField = "hint";
1890
- var isLatexWholeField = (field) => {
1891
- return field !== hintField;
1892
- };
1893
- var exerciseTranslationLatexWholeFields = exerciseTranslationFields.filter(isLatexWholeField);
3445
+ // ../../node_modules/entities/dist/esm/decode.js
3446
+ var CharCodes;
3447
+ (function(CharCodes2) {
3448
+ CharCodes2[CharCodes2["NUM"] = 35] = "NUM";
3449
+ CharCodes2[CharCodes2["SEMI"] = 59] = "SEMI";
3450
+ CharCodes2[CharCodes2["EQUALS"] = 61] = "EQUALS";
3451
+ CharCodes2[CharCodes2["ZERO"] = 48] = "ZERO";
3452
+ CharCodes2[CharCodes2["NINE"] = 57] = "NINE";
3453
+ CharCodes2[CharCodes2["LOWER_A"] = 97] = "LOWER_A";
3454
+ CharCodes2[CharCodes2["LOWER_F"] = 102] = "LOWER_F";
3455
+ CharCodes2[CharCodes2["LOWER_X"] = 120] = "LOWER_X";
3456
+ CharCodes2[CharCodes2["LOWER_Z"] = 122] = "LOWER_Z";
3457
+ CharCodes2[CharCodes2["UPPER_A"] = 65] = "UPPER_A";
3458
+ CharCodes2[CharCodes2["UPPER_F"] = 70] = "UPPER_F";
3459
+ CharCodes2[CharCodes2["UPPER_Z"] = 90] = "UPPER_Z";
3460
+ })(CharCodes || (CharCodes = {}));
3461
+ var BinTrieFlags;
3462
+ (function(BinTrieFlags2) {
3463
+ BinTrieFlags2[BinTrieFlags2["VALUE_LENGTH"] = 49152] = "VALUE_LENGTH";
3464
+ BinTrieFlags2[BinTrieFlags2["BRANCH_LENGTH"] = 16256] = "BRANCH_LENGTH";
3465
+ BinTrieFlags2[BinTrieFlags2["JUMP_TABLE"] = 127] = "JUMP_TABLE";
3466
+ })(BinTrieFlags || (BinTrieFlags = {}));
3467
+ var EntityDecoderState;
3468
+ (function(EntityDecoderState2) {
3469
+ EntityDecoderState2[EntityDecoderState2["EntityStart"] = 0] = "EntityStart";
3470
+ EntityDecoderState2[EntityDecoderState2["NumericStart"] = 1] = "NumericStart";
3471
+ EntityDecoderState2[EntityDecoderState2["NumericDecimal"] = 2] = "NumericDecimal";
3472
+ EntityDecoderState2[EntityDecoderState2["NumericHex"] = 3] = "NumericHex";
3473
+ EntityDecoderState2[EntityDecoderState2["NamedEntity"] = 4] = "NamedEntity";
3474
+ })(EntityDecoderState || (EntityDecoderState = {}));
3475
+ var DecodingMode;
3476
+ (function(DecodingMode2) {
3477
+ DecodingMode2[DecodingMode2["Legacy"] = 0] = "Legacy";
3478
+ DecodingMode2[DecodingMode2["Strict"] = 1] = "Strict";
3479
+ DecodingMode2[DecodingMode2["Attribute"] = 2] = "Attribute";
3480
+ })(DecodingMode || (DecodingMode = {}));
3481
+
3482
+ // ../../node_modules/entities/dist/esm/escape.js
3483
+ var getCodePoint = (
3484
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
3485
+ String.prototype.codePointAt == null ? (c, index) => (c.charCodeAt(index) & 64512) === 55296 ? (c.charCodeAt(index) - 55296) * 1024 + c.charCodeAt(index + 1) - 56320 + 65536 : c.charCodeAt(index) : (
3486
+ // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
3487
+ (input, index) => input.codePointAt(index)
3488
+ )
3489
+ );
3490
+
3491
+ // ../../node_modules/entities/dist/esm/index.js
3492
+ var EntityLevel;
3493
+ (function(EntityLevel2) {
3494
+ EntityLevel2[EntityLevel2["XML"] = 0] = "XML";
3495
+ EntityLevel2[EntityLevel2["HTML"] = 1] = "HTML";
3496
+ })(EntityLevel || (EntityLevel = {}));
3497
+ var EncodingMode;
3498
+ (function(EncodingMode2) {
3499
+ EncodingMode2[EncodingMode2["UTF8"] = 0] = "UTF8";
3500
+ EncodingMode2[EncodingMode2["ASCII"] = 1] = "ASCII";
3501
+ EncodingMode2[EncodingMode2["Extensive"] = 2] = "Extensive";
3502
+ EncodingMode2[EncodingMode2["Attribute"] = 3] = "Attribute";
3503
+ EncodingMode2[EncodingMode2["Text"] = 4] = "Text";
3504
+ })(EncodingMode || (EncodingMode = {}));
1894
3505
 
1895
3506
  // ../shared/src/helpers/latex/latex-helpers.ts
1896
3507
  var latexDelimiters = [
@@ -1903,185 +3514,241 @@ var sortedLatexDelimiters = [...latexDelimiters].sort((leftDelimiter, rightDelim
1903
3514
  return rightDelimiter.left.length - leftDelimiter.left.length;
1904
3515
  });
1905
3516
 
3517
+ // ../shared/src/export-layout/render-html.ts
3518
+ var worksheetContentWidthInCm = (defaultWorksheetPageSettings.widthMm - defaultWorksheetPageSettings.marginMm.left - defaultWorksheetPageSettings.marginMm.right) / 10;
3519
+
3520
+ // ../shared/src/helpers/exercise-labels.ts
3521
+ var exerciseLabels = labels_default;
3522
+ var flattenExerciseLabels = (labelNodes = exerciseLabels) => {
3523
+ const seenIds = /* @__PURE__ */ new Set();
3524
+ const flattenedLabels = [];
3525
+ const visit = ({
3526
+ depth,
3527
+ node,
3528
+ parentId,
3529
+ pathIds,
3530
+ pathNames
3531
+ }) => {
3532
+ if (seenIds.has(node.id)) {
3533
+ throw new Error(`Duplicate exercise label id: ${node.id}`);
3534
+ }
3535
+ seenIds.add(node.id);
3536
+ const childIds = node.children?.map((child) => child.id) ?? [];
3537
+ const nextPathIds = [...pathIds, node.id];
3538
+ const nextPathNames = [...pathNames, node.name];
3539
+ flattenedLabels.push({
3540
+ id: node.id,
3541
+ name: node.name,
3542
+ parentId,
3543
+ depth,
3544
+ pathIds: nextPathIds,
3545
+ pathNames: nextPathNames,
3546
+ displayPath: nextPathNames.join(" / "),
3547
+ childIds
3548
+ });
3549
+ node.children?.forEach((child) => {
3550
+ visit({
3551
+ depth: depth + 1,
3552
+ node: child,
3553
+ parentId: node.id,
3554
+ pathIds: nextPathIds,
3555
+ pathNames: nextPathNames
3556
+ });
3557
+ });
3558
+ };
3559
+ labelNodes.forEach((node) => {
3560
+ visit({ depth: 0, node, parentId: null, pathIds: [], pathNames: [] });
3561
+ });
3562
+ return flattenedLabels;
3563
+ };
3564
+ var canonicalExerciseLabelIds = new Set(flattenExerciseLabels().map((label) => label.id));
3565
+
3566
+ // ../shared/src/helpers/latex/exercise-translation-latex.ts
3567
+ var hintField = "hint";
3568
+ var isLatexWholeField = (field) => {
3569
+ return field !== hintField;
3570
+ };
3571
+ var exerciseTranslationLatexWholeFields = exerciseTranslationFields.filter(isLatexWholeField);
3572
+
1906
3573
  // ../shared/src/schemas/model-output-schemas.ts
1907
- import z4 from "zod";
1908
- var importFigureCandidateIdsSchema = z4.array(z4.string()).optional();
1909
- var exerciseTranslationOutputSchema = z4.object({
1910
- translations: z4.object({
1911
- exercise_text: z4.string().trim().min(1).nullable(),
1912
- description: z4.string().trim().min(1).nullable(),
1913
- hint: z4.string().trim().min(1).nullable(),
1914
- answer: z4.string().trim().min(1).nullable(),
1915
- scaffold: z4.string().trim().min(1).nullable(),
1916
- detailed_solution: z4.string().trim().min(1).nullable()
3574
+ import z7 from "zod";
3575
+ var importFigureCandidateIdsSchema = z7.array(z7.string()).optional();
3576
+ var exerciseTranslationOutputSchema = z7.object({
3577
+ translations: z7.object({
3578
+ exercise_text: z7.string().trim().min(1).nullable(),
3579
+ description: z7.string().trim().min(1).nullable(),
3580
+ hint: z7.string().trim().min(1).nullable(),
3581
+ answer: z7.string().trim().min(1).nullable(),
3582
+ scaffold: z7.string().trim().min(1).nullable(),
3583
+ detailed_solution: z7.string().trim().min(1).nullable()
1917
3584
  })
1918
3585
  });
1919
- var sheetTranslationFieldSchema = z4.string().trim().min(1);
1920
- var exerciseSheetTranslationOutputSchema = z4.object({
1921
- translations: z4.object(
3586
+ var sheetTranslationFieldSchema = z7.string().trim().min(1);
3587
+ var exerciseSheetTranslationOutputSchema = z7.object({
3588
+ translations: z7.object(
1922
3589
  Object.fromEntries(
1923
3590
  exerciseSheetTranslationFields.map((field) => [field, sheetTranslationFieldSchema.nullable()])
1924
3591
  )
1925
3592
  ).strict()
1926
3593
  });
1927
- var generatedTranslationFieldSchema = z4.string().trim().min(1);
1928
- var generatedTranslationFieldsSchema = z4.object(
3594
+ var generatedTranslationFieldSchema = z7.string().trim().min(1);
3595
+ var generatedTranslationFieldsSchema = z7.object(
1929
3596
  Object.fromEntries(
1930
3597
  exerciseTranslationFields.map((field) => [field, generatedTranslationFieldSchema.nullable()])
1931
3598
  )
1932
3599
  ).strict();
1933
- var exerciseSolutionImportOutputSchema = z4.object({
1934
- language: z4.enum(translationLanguages),
1935
- hints: z4.array(z4.string()).nullable(),
1936
- answer: z4.string().nullable(),
1937
- scaffold: z4.string().nullable(),
1938
- detailedSolution: z4.string().nullable(),
1939
- notes: z4.string().nullable(),
3600
+ var exerciseSolutionImportOutputSchema = z7.object({
3601
+ language: z7.enum(translationLanguages),
3602
+ hints: z7.array(z7.string()).nullable(),
3603
+ answer: z7.string().nullable(),
3604
+ scaffold: z7.string().nullable(),
3605
+ detailedSolution: z7.string().nullable(),
3606
+ notes: z7.string().nullable(),
1940
3607
  solutionFigureCandidateIds: importFigureCandidateIdsSchema
1941
3608
  });
1942
- var generatedSolutionFieldsSchema = z4.object({
1943
- hints: z4.array(z4.string().trim().min(1)).min(1).nullable(),
1944
- answer: z4.string().trim().min(1).nullable(),
1945
- scaffold: z4.string().trim().min(1).nullable(),
1946
- detailedSolution: z4.string().trim().min(1).nullable()
3609
+ var generatedSolutionFieldsSchema = z7.object({
3610
+ hints: z7.array(z7.string().trim().min(1)).min(1).nullable(),
3611
+ answer: z7.string().trim().min(1).nullable(),
3612
+ scaffold: z7.string().trim().min(1).nullable(),
3613
+ detailedSolution: z7.string().trim().min(1).nullable()
1947
3614
  }).strict();
1948
- var sheetImportExerciseOutputSchema = z4.object({
1949
- text: z4.string(),
1950
- detailedSolution: z4.string().nullable(),
1951
- hints: z4.array(z4.string()).nullable(),
1952
- scaffold: z4.string().nullable(),
1953
- answer: z4.string().nullable(),
1954
- source: z4.string().nullable(),
1955
- notes: z4.string().nullable(),
3615
+ var sheetImportExerciseOutputSchema = z7.object({
3616
+ text: z7.string(),
3617
+ detailedSolution: z7.string().nullable(),
3618
+ hints: z7.array(z7.string()).nullable(),
3619
+ scaffold: z7.string().nullable(),
3620
+ answer: z7.string().nullable(),
3621
+ source: z7.string().nullable(),
3622
+ notes: z7.string().nullable(),
1956
3623
  textFigureCandidateIds: importFigureCandidateIdsSchema,
1957
3624
  solutionFigureCandidateIds: importFigureCandidateIdsSchema
1958
3625
  }).strict();
1959
- var sheetImportOutputSchema = z4.object({
1960
- isExerciseSheet: z4.boolean(),
1961
- title: z4.string(),
1962
- description: z4.string().nullable(),
1963
- language: z4.enum(translationLanguages),
1964
- exercises: z4.array(sheetImportExerciseOutputSchema)
3626
+ var sheetImportOutputSchema = z7.object({
3627
+ isExerciseSheet: z7.boolean(),
3628
+ title: z7.string(),
3629
+ description: z7.string().nullable(),
3630
+ language: z7.enum(translationLanguages),
3631
+ exercises: z7.array(sheetImportExerciseOutputSchema)
1965
3632
  }).strict();
1966
- var exerciseImportOutputSchema = z4.object({
1967
- exercises: z4.array(
1968
- z4.object({
1969
- language: z4.enum(translationLanguages),
1970
- text: z4.string(),
1971
- detailedSolution: z4.string().nullable(),
1972
- hints: z4.array(z4.string()).nullable(),
1973
- scaffold: z4.string().nullable(),
1974
- answer: z4.string().nullable(),
1975
- source: z4.string().nullable(),
1976
- notes: z4.string().nullable(),
3633
+ var exerciseImportOutputSchema = z7.object({
3634
+ exercises: z7.array(
3635
+ z7.object({
3636
+ language: z7.enum(translationLanguages),
3637
+ text: z7.string(),
3638
+ detailedSolution: z7.string().nullable(),
3639
+ hints: z7.array(z7.string()).nullable(),
3640
+ scaffold: z7.string().nullable(),
3641
+ answer: z7.string().nullable(),
3642
+ source: z7.string().nullable(),
3643
+ notes: z7.string().nullable(),
1977
3644
  textFigureCandidateIds: importFigureCandidateIdsSchema,
1978
3645
  solutionFigureCandidateIds: importFigureCandidateIdsSchema
1979
3646
  })
1980
3647
  )
1981
3648
  });
1982
- var komalPdfExerciseOutputSchema = z4.object({
1983
- exercise_text_latex: z4.string().describe("The parsed exercise text with LaTeX formulas delimited by $ signs"),
1984
- language: z4.enum(translationLanguages).describe("The language of the exercise"),
1985
- subject: z4.enum(exerciseSubjects).describe("The subject of the exercise")
3649
+ var komalPdfExerciseOutputSchema = z7.object({
3650
+ exercise_text_latex: z7.string().describe("The parsed exercise text with LaTeX formulas delimited by $ signs"),
3651
+ language: z7.enum(translationLanguages).describe("The language of the exercise"),
3652
+ subject: z7.enum(exerciseSubjects).describe("The subject of the exercise")
1986
3653
  });
1987
3654
 
1988
3655
  // ../shared/src/schemas/pgmq.ts
1989
- import { z as z5 } from "zod";
1990
- var importFileSchema = z5.object({
1991
- fileName: z5.string(),
1992
- fileType: z5.string(),
1993
- storageFilePath: z5.string()
3656
+ import { z as z8 } from "zod";
3657
+ var importFileSchema = z8.object({
3658
+ fileName: z8.string(),
3659
+ fileType: z8.string(),
3660
+ storageFilePath: z8.string()
1994
3661
  });
1995
- var declaredSheetImportComponentSchema = z5.object({
3662
+ var declaredSheetImportComponentSchema = z8.object({
1996
3663
  componentId: sheetImportComponentIdSchema,
1997
- description: z5.string().trim().min(1),
1998
- folderId: z5.string().nullable(),
1999
- titleOverride: z5.string().trim().min(1).nullable().optional(),
3664
+ description: z8.string().trim().min(1),
3665
+ folderId: z8.string().nullable(),
3666
+ titleOverride: z8.string().trim().min(1).nullable().optional(),
2000
3667
  translateToLanguages: sheetImportTranslationLanguageListSchema.optional()
2001
3668
  }).strict();
2002
- var exerciseSheetImportQueueMessageSchema = z5.object({
2003
- userId: z5.string(),
2004
- organizationId: z5.uuid(),
2005
- files: z5.array(importFileSchema),
2006
- jobId: z5.string(),
2007
- folderId: z5.string().nullable(),
2008
- docxGotenbergConversionEnabled: z5.boolean().optional(),
2009
- titleOverride: z5.string().nullable().optional(),
2010
- translateToLanguages: z5.array(z5.enum(translationLanguages)).refine((languages) => new Set(languages).size === languages.length, {
3669
+ var exerciseSheetImportQueueMessageSchema = z8.object({
3670
+ userId: z8.string(),
3671
+ organizationId: z8.uuid(),
3672
+ files: z8.array(importFileSchema),
3673
+ jobId: z8.string(),
3674
+ folderId: z8.string().nullable(),
3675
+ docxGotenbergConversionEnabled: z8.boolean().optional(),
3676
+ titleOverride: z8.string().nullable().optional(),
3677
+ translateToLanguages: z8.array(z8.enum(translationLanguages)).refine((languages) => new Set(languages).size === languages.length, {
2011
3678
  message: "translateToLanguages must be unique"
2012
3679
  }).optional(),
2013
- declaredComponents: z5.array(declaredSheetImportComponentSchema).min(1).optional()
2014
- });
2015
- var exerciseSolutionImportQueueMessageSchema = z5.object({
2016
- userId: z5.string(),
2017
- organizationId: z5.uuid(),
2018
- exerciseId: z5.uuid(),
2019
- files: z5.array(importFileSchema),
2020
- jobId: z5.string(),
2021
- docxGotenbergConversionEnabled: z5.boolean().optional()
2022
- });
2023
- var exerciseSheetSolutionImportQueueMessageSchema = z5.object({
2024
- userId: z5.string(),
2025
- organizationId: z5.uuid(),
2026
- exerciseSheetId: z5.uuid(),
2027
- files: z5.array(importFileSchema),
2028
- jobId: z5.string(),
2029
- docxGotenbergConversionEnabled: z5.boolean().optional()
2030
- });
2031
- var exerciseSolutionGenerationQueueMessageSchema = z5.object({
2032
- userId: z5.uuid(),
2033
- organizationId: z5.uuid(),
2034
- exerciseId: z5.uuid(),
2035
- exerciseSheetId: z5.uuid().optional(),
2036
- batchId: z5.uuid().optional(),
2037
- jobId: z5.uuid()
2038
- });
2039
- var exerciseTranslationGenerationQueueMessageSchema = z5.object({
2040
- userId: z5.uuid(),
2041
- organizationId: z5.uuid(),
2042
- exerciseId: z5.uuid(),
2043
- jobId: z5.uuid(),
2044
- languages: z5.array(z5.enum(translationLanguages)).min(1)
3680
+ declaredComponents: z8.array(declaredSheetImportComponentSchema).min(1).optional()
3681
+ });
3682
+ var exerciseSolutionImportQueueMessageSchema = z8.object({
3683
+ userId: z8.string(),
3684
+ organizationId: z8.uuid(),
3685
+ exerciseId: z8.uuid(),
3686
+ files: z8.array(importFileSchema),
3687
+ jobId: z8.string(),
3688
+ docxGotenbergConversionEnabled: z8.boolean().optional()
3689
+ });
3690
+ var exerciseSheetSolutionImportQueueMessageSchema = z8.object({
3691
+ userId: z8.string(),
3692
+ organizationId: z8.uuid(),
3693
+ exerciseSheetId: z8.uuid(),
3694
+ files: z8.array(importFileSchema),
3695
+ jobId: z8.string(),
3696
+ docxGotenbergConversionEnabled: z8.boolean().optional()
3697
+ });
3698
+ var exerciseSolutionGenerationQueueMessageSchema = z8.object({
3699
+ userId: z8.uuid(),
3700
+ organizationId: z8.uuid(),
3701
+ exerciseId: z8.uuid(),
3702
+ exerciseSheetId: z8.uuid().optional(),
3703
+ batchId: z8.uuid().optional(),
3704
+ jobId: z8.uuid()
3705
+ });
3706
+ var exerciseTranslationGenerationQueueMessageSchema = z8.object({
3707
+ userId: z8.uuid(),
3708
+ organizationId: z8.uuid(),
3709
+ exerciseId: z8.uuid(),
3710
+ jobId: z8.uuid(),
3711
+ languages: z8.array(z8.enum(translationLanguages)).min(1)
2045
3712
  }).refine((value) => new Set(value.languages).size === value.languages.length, {
2046
3713
  message: "languages must be unique"
2047
3714
  });
2048
- var exerciseSheetTranslationGenerationQueueMessageSchema = z5.object({
2049
- userId: z5.uuid(),
2050
- organizationId: z5.uuid(),
2051
- exerciseSheetId: z5.uuid(),
2052
- jobId: z5.uuid(),
2053
- language: z5.enum(translationLanguages),
2054
- sourceLanguage: z5.enum(translationLanguages).optional()
2055
- });
2056
- var exerciseImportQueueMessageSchema = z5.object({
2057
- source: z5.literal("ui"),
2058
- userId: z5.uuid(),
2059
- organizationId: z5.uuid(),
2060
- files: z5.array(importFileSchema),
2061
- exerciseSheetId: z5.uuid().nullable().optional(),
2062
- jobId: z5.string(),
2063
- docxGotenbergConversionEnabled: z5.boolean().optional(),
2064
- translateToLanguages: z5.array(z5.enum(translationLanguages)).refine((languages) => new Set(languages).size === languages.length, {
3715
+ var exerciseSheetTranslationGenerationQueueMessageSchema = z8.object({
3716
+ userId: z8.uuid(),
3717
+ organizationId: z8.uuid(),
3718
+ exerciseSheetId: z8.uuid(),
3719
+ jobId: z8.uuid(),
3720
+ language: z8.enum(translationLanguages),
3721
+ sourceLanguage: z8.enum(translationLanguages).optional()
3722
+ });
3723
+ var exerciseImportQueueMessageSchema = z8.object({
3724
+ source: z8.literal("ui"),
3725
+ userId: z8.uuid(),
3726
+ organizationId: z8.uuid(),
3727
+ files: z8.array(importFileSchema),
3728
+ exerciseSheetId: z8.uuid().nullable().optional(),
3729
+ jobId: z8.string(),
3730
+ docxGotenbergConversionEnabled: z8.boolean().optional(),
3731
+ translateToLanguages: z8.array(z8.enum(translationLanguages)).refine((languages) => new Set(languages).size === languages.length, {
2065
3732
  message: "translateToLanguages must be unique"
2066
3733
  }).optional()
2067
3734
  });
2068
- var exerciseEmbeddingRecalculationQueueMessageSchema = z5.object({
2069
- exerciseId: z5.uuid(),
2070
- force: z5.boolean().optional()
3735
+ var exerciseEmbeddingRecalculationQueueMessageSchema = z8.object({
3736
+ exerciseId: z8.uuid(),
3737
+ force: z8.boolean().optional()
2071
3738
  });
2072
- var externalNotificationQueueMessageSchema = z5.discriminatedUnion("type", [
2073
- z5.object({
2074
- type: z5.literal("new_user_signup"),
2075
- userId: z5.uuid(),
2076
- email: z5.email().nullable(),
2077
- occurredAt: z5.iso.datetime({ offset: true })
3739
+ var externalNotificationQueueMessageSchema = z8.discriminatedUnion("type", [
3740
+ z8.object({
3741
+ type: z8.literal("new_user_signup"),
3742
+ userId: z8.uuid(),
3743
+ email: z8.email().nullable(),
3744
+ occurredAt: z8.iso.datetime({ offset: true })
2078
3745
  })
2079
3746
  ]);
2080
3747
 
2081
3748
  // ../shared/src/templates/export-template-definitions.ts
2082
- import { z as z6 } from "zod";
3749
+ import { z as z9 } from "zod";
2083
3750
  var showScoresParameterSchema = {
2084
- showScores: z6.boolean().default(true)
3751
+ showScores: z9.boolean().default(true)
2085
3752
  };
2086
3753
  var showScoresParameterUi = {
2087
3754
  showScores: {
@@ -2089,11 +3756,11 @@ var showScoresParameterUi = {
2089
3756
  shouldDisplay: ({ scoringEnabled }) => scoringEnabled
2090
3757
  }
2091
3758
  };
2092
- var baseExportTemplateParametersSchema = z6.object(showScoresParameterSchema).strict();
3759
+ var baseExportTemplateParametersSchema = z9.object(showScoresParameterSchema).strict();
2093
3760
  var workspaceHeightParameterConfig = {
2094
- defaultValue: 4,
2095
- min: 0,
2096
- max: 12,
3761
+ defaultValue: worksheetPreviewLayoutSettingsLimits.workspaceHeightInCm.default,
3762
+ min: worksheetPreviewLayoutSettingsLimits.workspaceHeightInCm.min,
3763
+ max: worksheetPreviewLayoutSettingsLimits.workspaceHeightInCm.max,
2097
3764
  step: 0.5
2098
3765
  };
2099
3766
  var exportTemplateDefinitions = {
@@ -2104,9 +3771,10 @@ var exportTemplateDefinitions = {
2104
3771
  },
2105
3772
  "exercises-with-workspace": {
2106
3773
  id: "exercises-with-workspace",
2107
- parametersSchema: z6.object({
3774
+ parametersSchema: z9.object({
2108
3775
  ...showScoresParameterSchema,
2109
- workspaceHeightInCm: z6.number().min(workspaceHeightParameterConfig.min).max(workspaceHeightParameterConfig.max).default(workspaceHeightParameterConfig.defaultValue)
3776
+ workspaceHeightInCm: z9.number().min(workspaceHeightParameterConfig.min).max(workspaceHeightParameterConfig.max).default(workspaceHeightParameterConfig.defaultValue),
3777
+ workspaceFillMode: z9.enum(worksheetWorkspaceFillModes).default("grid")
2110
3778
  }).strict(),
2111
3779
  parameterUi: {
2112
3780
  ...showScoresParameterUi,
@@ -2116,6 +3784,11 @@ var exportTemplateDefinitions = {
2116
3784
  max: workspaceHeightParameterConfig.max,
2117
3785
  step: workspaceHeightParameterConfig.step,
2118
3786
  unit: "cm"
3787
+ },
3788
+ workspaceFillMode: {
3789
+ control: "select",
3790
+ options: [...worksheetWorkspaceFillModes],
3791
+ shouldDisplay: ({ previewRendererMode }) => previewRendererMode === "html"
2119
3792
  }
2120
3793
  }
2121
3794
  },
@@ -2157,6 +3830,20 @@ var parseUpdateExerciseAgentInput = (input) => {
2157
3830
  }
2158
3831
  return parsedInput.data;
2159
3832
  };
3833
+ var parseCreateExerciseAgentInput = (input) => {
3834
+ const parsedInput = createExerciseAgentInputSchema.safeParse(input);
3835
+ if (!parsedInput.success) {
3836
+ throw new CliCommandError(`Invalid exercise create input: ${formatZodIssues(parsedInput.error.issues)}`, 2);
3837
+ }
3838
+ return parsedInput.data;
3839
+ };
3840
+ var parseCreateSheetAgentInput = (input) => {
3841
+ const parsedInput = createSheetAgentInputSchema.safeParse(input);
3842
+ if (!parsedInput.success) {
3843
+ throw new CliCommandError(`Invalid sheet create input: ${formatZodIssues(parsedInput.error.issues)}`, 2);
3844
+ }
3845
+ return parsedInput.data;
3846
+ };
2160
3847
  var parseUpdateSheetAgentInput = (input) => {
2161
3848
  const parsedInput = updateSheetAgentInputSchema.safeParse(input);
2162
3849
  if (!parsedInput.success) {
@@ -2459,7 +4146,7 @@ var formatCliImportTranslationJobs = (translationJobs) => {
2459
4146
  // src/lib/manifest.ts
2460
4147
  import { readFile as readFile2, stat as stat2 } from "node:fs/promises";
2461
4148
  import { resolve as resolve2 } from "node:path";
2462
- import { z as z7 } from "zod";
4149
+ import { z as z10 } from "zod";
2463
4150
 
2464
4151
  // src/lib/translation-languages.ts
2465
4152
  var translationLanguages2 = ["english", "hungarian", "german", "french", "spanish", "italian"];
@@ -2489,7 +4176,7 @@ var normalizeOptionalString4 = (value) => {
2489
4176
  const normalizedValue = value.trim();
2490
4177
  return normalizedValue.length > 0 ? normalizedValue : void 0;
2491
4178
  };
2492
- var translationLanguageListSchema = z7.array(z7.enum(translationLanguages2)).min(1, { message: "translateTo must include at least one language." }).refine((languages) => new Set(languages).size === languages.length, {
4179
+ var translationLanguageListSchema = z10.array(z10.enum(translationLanguages2)).min(1, { message: "translateTo must include at least one language." }).refine((languages) => new Set(languages).size === languages.length, {
2493
4180
  message: "translateTo languages must be unique."
2494
4181
  });
2495
4182
  var sheetImportComponentIdPattern2 = /^[a-zA-Z0-9_-]{1,80}$/;
@@ -3272,6 +4959,46 @@ var throwSilentExitCode = (exitCode) => {
3272
4959
  throw new CliCommandError("", exitCode, false);
3273
4960
  };
3274
4961
 
4962
+ // src/commands/exercise-labels.ts
4963
+ var formatExerciseLabelsOutput = ({ labels }) => {
4964
+ if (labels.length === 0) {
4965
+ return "No exercise labels returned.";
4966
+ }
4967
+ return [
4968
+ `${labels.length} exercise label${labels.length === 1 ? "" : "s"} returned.`,
4969
+ ...labels.map((label) => `${" ".repeat(label.depth)}${label.id} ${label.displayPath}`)
4970
+ ].join("\n");
4971
+ };
4972
+ var createExerciseLabelsCommand = (context) => ({
4973
+ command: "labels",
4974
+ describe: "List canonical exercise labels supported by ChalkSurf",
4975
+ builder: (labelsYargs) => labelsYargs.example("chalksurf exercise labels --json", "List valid exercise labels for agent workflows"),
4976
+ handler: async (argv) => {
4977
+ const { apiClient, organizationId } = await createResolvedApiClient({
4978
+ context,
4979
+ baseUrlFlagValue: argv.baseUrl,
4980
+ organizationFlagValue: argv.organization,
4981
+ profileName: argv.profile
4982
+ });
4983
+ let result;
4984
+ try {
4985
+ result = await apiClient.agentListExerciseLabels();
4986
+ } catch (error) {
4987
+ throw mapApiErrorToCliError(error);
4988
+ }
4989
+ context.output.print(
4990
+ {
4991
+ organizationId: organizationId ?? null,
4992
+ labels: result.labels
4993
+ },
4994
+ (output) => formatExerciseLabelsOutput({ labels: output.labels }),
4995
+ {
4996
+ command: "exercise labels"
4997
+ }
4998
+ );
4999
+ }
5000
+ });
5001
+
3275
5002
  // src/commands/exercise.ts
3276
5003
  var exerciseStatusOptions2 = ["verified", "unverified", "invalid"];
3277
5004
  var noSearchableTermsWarningMessage = "Search terms were too common and were ignored.";
@@ -3314,9 +5041,27 @@ var formatExerciseDetailsOutput = ({ exercise }) => {
3314
5041
  var formatCopyExerciseOutput = ({ receipt }) => {
3315
5042
  return formatAgentWriteReceiptOutput({ receipt });
3316
5043
  };
5044
+ var formatCreateExerciseOutput = ({ receipt }) => {
5045
+ return formatAgentWriteReceiptOutput({ receipt });
5046
+ };
5047
+ var formatDeleteExerciseOutput = ({ receipt }) => {
5048
+ return formatAgentWriteReceiptOutput({ receipt });
5049
+ };
3317
5050
  var formatUpdateExerciseOutput = ({ receipt }) => {
3318
5051
  return formatAgentWriteReceiptOutput({ receipt });
3319
5052
  };
5053
+ var formatSetExerciseVisibilityOutput = ({ receipt }) => {
5054
+ return formatAgentWriteReceiptOutput({ receipt });
5055
+ };
5056
+ var resolveVisibilityFlag = ({ privateFlag, publicFlag }) => {
5057
+ if (publicFlag && privateFlag) {
5058
+ throw new CliCommandError("--public and --private cannot be used together.", 2);
5059
+ }
5060
+ if (!publicFlag && !privateFlag) {
5061
+ throw new CliCommandError("Either --public or --private is required.", 2);
5062
+ }
5063
+ return Boolean(publicFlag);
5064
+ };
3320
5065
  var formatExerciseUsageOutput = ({ usage }) => {
3321
5066
  const sheetCount = usage.sheets.length;
3322
5067
  const otherSheetCount = usage.otherOrganizationSheetCount;
@@ -3386,7 +5131,7 @@ var resolveRequestedUuid = ({
3386
5131
  }
3387
5132
  return void 0;
3388
5133
  }
3389
- const parsedValue = z8.uuid().safeParse(resolvedValue);
5134
+ const parsedValue = z11.uuid().safeParse(resolvedValue);
3390
5135
  if (!parsedValue.success) {
3391
5136
  throw new CliCommandError(`${label} must be a valid UUID.`, 2);
3392
5137
  }
@@ -3470,7 +5215,7 @@ var formatWaitedImportOutput = (job) => {
3470
5215
  return `${job.jobId} ${job.status ?? "pending"}`;
3471
5216
  };
3472
5217
  var registerExerciseCommands = (exerciseYargs, context) => {
3473
- return exerciseYargs.command(
5218
+ return exerciseYargs.command(createExerciseLabelsCommand(context)).command(
3474
5219
  "search",
3475
5220
  "Search exercises visible to the selected organization",
3476
5221
  (searchYargs) => searchYargs.option("text", {
@@ -3519,7 +5264,7 @@ var registerExerciseCommands = (exerciseYargs, context) => {
3519
5264
  'chalksurf exercise search --text "binomial theorem" --language english --ownership own --json',
3520
5265
  "Verify imported exercises in the selected organization"
3521
5266
  ).example(
3522
- "chalksurf --profile prod-codex exercise search --label geometry.triangles --status unverified --json",
5267
+ "chalksurf --profile prod-codex exercise search --label geometry.triangle --status unverified --json",
3523
5268
  "Find agent-created exercises that still need review"
3524
5269
  ),
3525
5270
  async (argv) => {
@@ -3735,6 +5480,107 @@ var registerExerciseCommands = (exerciseYargs, context) => {
3735
5480
  }
3736
5481
  );
3737
5482
  }
5483
+ ).command(
5484
+ "create",
5485
+ "Create an exercise from an agent JSON payload",
5486
+ (createYargs) => createYargs.option("input-json", {
5487
+ type: "string",
5488
+ demandOption: true,
5489
+ describe: "JSON object matching the agent exercise create contract"
5490
+ }).example(
5491
+ `chalksurf exercise create --input-json '{"translations":{"english":{"exercise_text":"Find $x$."}},"labels":["algebra.equations"]}' --json`,
5492
+ "Create an exercise for an agent workflow"
5493
+ ),
5494
+ async (argv) => {
5495
+ const input = parseCreateExerciseAgentInput(
5496
+ parseJsonObjectFlag({ label: "--input-json", value: argv.inputJson })
5497
+ );
5498
+ const { apiClient, organizationId } = await createResolvedApiClient({
5499
+ context,
5500
+ baseUrlFlagValue: argv.baseUrl,
5501
+ organizationFlagValue: argv.organization,
5502
+ profileName: argv.profile
5503
+ });
5504
+ let result;
5505
+ try {
5506
+ result = await apiClient.agentCreateExercise(input);
5507
+ } catch (error) {
5508
+ throw mapApiErrorToCliError(error);
5509
+ }
5510
+ context.output.print(
5511
+ {
5512
+ request: {
5513
+ ...input,
5514
+ organizationId: organizationId ?? null
5515
+ },
5516
+ receipt: result.receipt
5517
+ },
5518
+ (output) => formatCreateExerciseOutput({ receipt: output.receipt }),
5519
+ {
5520
+ command: "exercise create"
5521
+ }
5522
+ );
5523
+ }
5524
+ ).command(
5525
+ "delete [exerciseId]",
5526
+ "Delete an unused exercise after confirmation",
5527
+ (deleteYargs) => deleteYargs.positional("exerciseId", {
5528
+ type: "string",
5529
+ describe: "Exercise ID to delete"
5530
+ }).option("expected-updated-at", {
5531
+ type: "string",
5532
+ demandOption: true,
5533
+ describe: "Expected current exercise updated_at ISO timestamp"
5534
+ }).option("confirm-resource-id", {
5535
+ type: "string",
5536
+ demandOption: true,
5537
+ describe: "Must exactly match the exercise ID being deleted"
5538
+ }).example(
5539
+ "chalksurf exercise delete 00000000-0000-4000-8000-000000000001 --expected-updated-at 2026-01-01T00:00:00.000Z --confirm-resource-id 00000000-0000-4000-8000-000000000001 --json",
5540
+ "Delete an unused exercise with destructive confirmation"
5541
+ ),
5542
+ async (argv) => {
5543
+ const id = resolveRequestedUuid({
5544
+ fallbackValue: argv.exerciseId,
5545
+ label: "exerciseId",
5546
+ required: true
5547
+ });
5548
+ const confirmResourceId = resolveRequestedUuid({
5549
+ flagValue: argv.confirmResourceId,
5550
+ label: "--confirm-resource-id",
5551
+ required: true
5552
+ });
5553
+ const input = {
5554
+ id,
5555
+ expectedUpdatedAt: argv.expectedUpdatedAt,
5556
+ confirmResourceId
5557
+ };
5558
+ const { apiClient, organizationId } = await createResolvedApiClient({
5559
+ context,
5560
+ baseUrlFlagValue: argv.baseUrl,
5561
+ organizationFlagValue: argv.organization,
5562
+ profileName: argv.profile
5563
+ });
5564
+ let result;
5565
+ try {
5566
+ result = await apiClient.agentDeleteExercise(input);
5567
+ } catch (error) {
5568
+ throw mapApiErrorToCliError(error);
5569
+ }
5570
+ context.output.print(
5571
+ {
5572
+ request: {
5573
+ ...input,
5574
+ organizationId: organizationId ?? null
5575
+ },
5576
+ receipt: result.receipt
5577
+ },
5578
+ (output) => formatDeleteExerciseOutput({ receipt: output.receipt }),
5579
+ {
5580
+ command: "exercise delete"
5581
+ }
5582
+ );
5583
+ }
3738
5584
  ).command(
3739
5585
  "update [exerciseId]",
3740
5586
  "Apply a field-level patch to an exercise",
@@ -3804,6 +5650,75 @@ var registerExerciseCommands = (exerciseYargs, context) => {
3804
5650
  }
3805
5651
  );
3806
5652
  }
5653
+ ).command(
5654
+ "set-visibility [exerciseId]",
5655
+ "Set exercise visibility after checking the current updated_at value",
5656
+ (visibilityYargs) => visibilityYargs.positional("exerciseId", {
5657
+ type: "string",
5658
+ describe: "Exercise ID to update"
5659
+ }).option("expected-updated-at", {
5660
+ type: "string",
5661
+ demandOption: true,
5662
+ describe: "Expected current exercise updated_at ISO timestamp"
5663
+ }).option("public", {
5664
+ type: "boolean",
5665
+ describe: "Make the exercise public"
5666
+ }).option("private", {
5667
+ type: "boolean",
5668
+ describe: "Make the exercise private"
5669
+ }).option("confirm-make-public-resource-id", {
5670
+ type: "string",
5671
+ describe: "Required when using --public; must exactly match the exercise ID"
5672
+ }).example(
5673
+ "chalksurf exercise set-visibility 00000000-0000-4000-8000-000000000001 --public --expected-updated-at 2026-01-01T00:00:00.000Z --confirm-make-public-resource-id 00000000-0000-4000-8000-000000000001 --json",
5674
+ "Make an exercise public with confirmation"
5675
+ ),
5676
+ async (argv) => {
5677
+ const id = resolveRequestedUuid({
5678
+ fallbackValue: argv.exerciseId,
5679
+ label: "exerciseId",
5680
+ required: true
5681
+ });
5682
+ const isPublic = resolveVisibilityFlag({
5683
+ privateFlag: argv.private,
5684
+ publicFlag: argv.public
5685
+ });
5686
+ const confirmMakePublicResourceId = resolveRequestedUuid({
5687
+ flagValue: argv.confirmMakePublicResourceId,
5688
+ label: "--confirm-make-public-resource-id"
5689
+ });
5690
+ const input = {
5691
+ id,
5692
+ expectedUpdatedAt: argv.expectedUpdatedAt,
5693
+ isPublic,
5694
+ ...confirmMakePublicResourceId === void 0 ? {} : { confirmMakePublicResourceId }
5695
+ };
5696
+ const { apiClient, organizationId } = await createResolvedApiClient({
5697
+ context,
5698
+ baseUrlFlagValue: argv.baseUrl,
5699
+ organizationFlagValue: argv.organization,
5700
+ profileName: argv.profile
5701
+ });
5702
+ let result;
5703
+ try {
5704
+ result = await apiClient.agentSetExerciseVisibility(input);
5705
+ } catch (error) {
5706
+ throw mapApiErrorToCliError(error);
5707
+ }
5708
+ context.output.print(
5709
+ {
5710
+ request: {
5711
+ ...input,
5712
+ organizationId: organizationId ?? null
5713
+ },
5714
+ receipt: result.receipt
5715
+ },
5716
+ (output) => formatSetExerciseVisibilityOutput({ receipt: output.receipt }),
5717
+ {
5718
+ command: "exercise set-visibility"
5719
+ }
5720
+ );
5721
+ }
3807
5722
  ).command(
3808
5723
  "validate-latex",
3809
5724
  "Validate LaTeX snippets before updating exercise or sheet content",
@@ -4208,7 +6123,121 @@ var registerExerciseCommands = (exerciseYargs, context) => {
4208
6123
  await cleanupResolvedSources(resolvedSources);
4209
6124
  }
4210
6125
  }
4211
- ).demandCommand(1).strict();
6126
+ ).demandCommand(1).strict();
6127
+ };
6128
+
6129
+ // src/commands/feedback.ts
6130
+ var parseOptionalContextJson = (value) => {
6131
+ return value === void 0 ? void 0 : parseJsonObjectFlag({ label: "--context-json", value });
6132
+ };
6133
+ var requireMessage = (value) => {
6134
+ const message = value?.trim();
6135
+ if (!message) {
6136
+ throw new CliCommandError("--message is required.", 2);
6137
+ }
6138
+ return message;
6139
+ };
6140
+ var formatFeedbackOutput = ({ receipt }) => `Submitted ${receipt.eventType} feedback event ${receipt.eventId}.`;
6141
+ var registerFeedbackCommands = (feedbackYargs, context) => {
6142
+ return feedbackYargs.command(
6143
+ "user",
6144
+ "Send user-consented feedback to ChalkSurf",
6145
+ (userYargs) => userYargs.option("message", {
6146
+ type: "string",
6147
+ demandOption: true,
6148
+ describe: "Feedback text the user agreed to send"
6149
+ }).option("user-consent", {
6150
+ type: "boolean",
6151
+ default: false,
6152
+ describe: "Confirm the user explicitly consented to sending this feedback"
6153
+ }).option("category", {
6154
+ type: "string",
6155
+ choices: ["bug_report", "feature_request", "frustration", "blocked_request", "other"],
6156
+ describe: "Feedback category"
6157
+ }).option("context-json", {
6158
+ type: "string",
6159
+ describe: "Optional JSON object with reproduction details or request context"
6160
+ }).example(
6161
+ 'chalksurf feedback user --message "Import failed for my sheet" --user-consent --json',
6162
+ "Send user-consented feedback"
6163
+ ),
6164
+ async (argv) => {
6165
+ if (!argv.userConsent) {
6166
+ throw new CliCommandError("--user-consent is required before sending user feedback.", 2);
6167
+ }
6168
+ const input = {
6169
+ message: requireMessage(argv.message),
6170
+ userConsent: true,
6171
+ ...argv.category ? { category: argv.category } : {},
6172
+ ...argv.contextJson === void 0 ? {} : { context: parseOptionalContextJson(argv.contextJson) }
6173
+ };
6174
+ const { apiClient, organizationId } = await createResolvedApiClient({
6175
+ context,
6176
+ baseUrlFlagValue: argv.baseUrl,
6177
+ organizationFlagValue: argv.organization,
6178
+ profileName: argv.profile
6179
+ });
6180
+ let result;
6181
+ try {
6182
+ result = await apiClient.agentSendUserFeedback(input);
6183
+ } catch (error) {
6184
+ throw mapApiErrorToCliError(error);
6185
+ }
6186
+ context.output.print(
6187
+ {
6188
+ organizationId: organizationId ?? null,
6189
+ receipt: result.receipt
6190
+ },
6191
+ (output) => formatFeedbackOutput({ receipt: output.receipt }),
6192
+ { command: "feedback user" }
6193
+ );
6194
+ }
6195
+ ).command(
6196
+ "agent",
6197
+ "Send agent-observed CLI, MCP, API, or documentation feedback to ChalkSurf",
6198
+ (agentYargs) => agentYargs.option("message", {
6199
+ type: "string",
6200
+ demandOption: true,
6201
+ describe: "Feedback text describing the agent-observed issue"
6202
+ }).option("category", {
6203
+ type: "string",
6204
+ choices: ["api_inconsistency", "documentation_issue", "missing_capability", "unexpected_behavior", "other"],
6205
+ describe: "Feedback category"
6206
+ }).option("context-json", {
6207
+ type: "string",
6208
+ describe: "Optional JSON object with command, tool, or documentation context"
6209
+ }).example(
6210
+ 'chalksurf feedback agent --message "MCP tool output differed from docs" --category documentation_issue --json',
6211
+ "Send agent-observed feedback"
6212
+ ),
6213
+ async (argv) => {
6214
+ const input = {
6215
+ message: requireMessage(argv.message),
6216
+ ...argv.category ? { category: argv.category } : {},
6217
+ ...argv.contextJson === void 0 ? {} : { context: parseOptionalContextJson(argv.contextJson) }
6218
+ };
6219
+ const { apiClient, organizationId } = await createResolvedApiClient({
6220
+ context,
6221
+ baseUrlFlagValue: argv.baseUrl,
6222
+ organizationFlagValue: argv.organization,
6223
+ profileName: argv.profile
6224
+ });
6225
+ let result;
6226
+ try {
6227
+ result = await apiClient.agentSendAgentFeedback(input);
6228
+ } catch (error) {
6229
+ throw mapApiErrorToCliError(error);
6230
+ }
6231
+ context.output.print(
6232
+ {
6233
+ organizationId: organizationId ?? null,
6234
+ receipt: result.receipt
6235
+ },
6236
+ (output) => formatFeedbackOutput({ receipt: output.receipt }),
6237
+ { command: "feedback agent" }
6238
+ );
6239
+ }
6240
+ ).demandCommand(1);
4212
6241
  };
4213
6242
 
4214
6243
  // src/commands/job.ts
@@ -4631,7 +6660,7 @@ var registerProfileCommands = (profileYargs, context) => {
4631
6660
  };
4632
6661
 
4633
6662
  // src/commands/sheet.ts
4634
- import { z as z9 } from "zod";
6663
+ import { z as z12 } from "zod";
4635
6664
  var readinessIssueTypeLabels = {
4636
6665
  missing_translation: "missing translations",
4637
6666
  missing_solution: "missing solutions",
@@ -4755,7 +6784,7 @@ var resolveRequestedUuid2 = ({
4755
6784
  }
4756
6785
  return void 0;
4757
6786
  }
4758
- const parsedValue = z9.uuid().safeParse(resolvedValue);
6787
+ const parsedValue = z12.uuid().safeParse(resolvedValue);
4759
6788
  if (!parsedValue.success) {
4760
6789
  throw new CliCommandError(`${label} must be a valid UUID.`, 2);
4761
6790
  }
@@ -4766,7 +6795,7 @@ var resolveRequestedUuidList = ({ label, values }) => {
4766
6795
  throw new CliCommandError(`${label} is required at least once.`, 2);
4767
6796
  }
4768
6797
  return values.map((value, index) => {
4769
- const parsedValue = z9.uuid().safeParse(value.trim());
6798
+ const parsedValue = z12.uuid().safeParse(value.trim());
4770
6799
  if (!parsedValue.success) {
4771
6800
  throw new CliCommandError(`${label}[${index}] must be a valid UUID.`, 2);
4772
6801
  }
@@ -5102,6 +7131,33 @@ var formatSheetDetailsOutput = ({ sheet }) => {
5102
7131
  `readiness: ${formatSheetReadinessSummary(sheet.readinessSummary)}`
5103
7132
  ].join("\n");
5104
7133
  };
7134
+ var formatSheetVersionListOutput = ({ versions }) => {
7135
+ if (versions.length === 0) {
7136
+ return "No sheet versions found.";
7137
+ }
7138
+ return [
7139
+ `${versions.length} sheet version${versions.length === 1 ? "" : "s"} returned.`,
7140
+ ...versions.map(
7141
+ (version) => [
7142
+ version.id,
7143
+ `v${version.versionNumber}`,
7144
+ version.type,
7145
+ version.createdAt,
7146
+ version.createdByName ? `by ${version.createdByName}` : null,
7147
+ version.sourceVersionId ? `source: ${version.sourceVersionId}` : null
7148
+ ].filter(Boolean).join(" ")
7149
+ )
7150
+ ].join("\n");
7151
+ };
7152
+ var formatSheetVersionDetailsOutput = ({ version }) => {
7153
+ return [
7154
+ `Sheet version ${version.id}`,
7155
+ `sheet: ${version.exerciseSheetId}`,
7156
+ `version: ${version.versionNumber}`,
7157
+ `type: ${version.type}`,
7158
+ `exercises: ${version.exercises.length}`
7159
+ ].join("\n");
7160
+ };
5105
7161
  var formatSheetIssuesOutput = ({ issues, readinessSummary }) => {
5106
7162
  if (issues.length === 0) {
5107
7163
  return `No sheet issues found. ${formatSheetReadinessSummary(readinessSummary)}`;
@@ -5126,9 +7182,18 @@ var formatSheetIssuesOutput = ({ issues, readinessSummary }) => {
5126
7182
  var formatCopySheetOutput = ({ receipt }) => {
5127
7183
  return formatAgentWriteReceiptOutput({ receipt });
5128
7184
  };
7185
+ var formatCreateSheetOutput = ({ receipt }) => {
7186
+ return formatAgentWriteReceiptOutput({ receipt });
7187
+ };
7188
+ var formatDeleteSheetOutput = ({ receipt }) => {
7189
+ return formatAgentWriteReceiptOutput({ receipt });
7190
+ };
5129
7191
  var formatUpdateSheetOutput = ({ receipt }) => {
5130
7192
  return formatAgentWriteReceiptOutput({ receipt });
5131
7193
  };
7194
+ var formatSetSheetVisibilityOutput = ({ receipt }) => {
7195
+ return formatAgentWriteReceiptOutput({ receipt });
7196
+ };
5132
7197
  var formatAppendExercisesToSheetOutput = ({ receipt }) => {
5133
7198
  return formatAgentWriteReceiptOutput({ receipt });
5134
7199
  };
@@ -5144,9 +7209,21 @@ var formatFolderListOutput = ({ folders }) => {
5144
7209
  var formatCreateFolderOutput = ({ receipt }) => {
5145
7210
  return formatAgentWriteReceiptOutput({ receipt });
5146
7211
  };
7212
+ var formatDeleteFolderOutput = ({ receipt }) => {
7213
+ return formatAgentWriteReceiptOutput({ receipt });
7214
+ };
5147
7215
  var formatRenameFolderOutput = ({ receipt }) => {
5148
7216
  return formatAgentWriteReceiptOutput({ receipt });
5149
7217
  };
7218
+ var resolveVisibilityFlag2 = ({ privateFlag, publicFlag }) => {
7219
+ if (publicFlag && privateFlag) {
7220
+ throw new CliCommandError("--public and --private cannot be used together.", 2);
7221
+ }
7222
+ if (!publicFlag && !privateFlag) {
7223
+ throw new CliCommandError("Either --public or --private is required.", 2);
7224
+ }
7225
+ return Boolean(publicFlag);
7226
+ };
5150
7227
  var registerSheetCommands = (sheetYargs, context) => {
5151
7228
  return sheetYargs.command(
5152
7229
  "search",
@@ -5279,6 +7356,99 @@ var registerSheetCommands = (sheetYargs, context) => {
5279
7356
  }
5280
7357
  );
5281
7358
  }
7359
+ ).command(
7360
+ "versions [exerciseSheetId]",
7361
+ "List version history for an exercise sheet owned by the selected organization",
7362
+ (versionsYargs) => versionsYargs.positional("exerciseSheetId", {
7363
+ type: "string",
7364
+ describe: "Exercise sheet ID to inspect"
7365
+ }).example(
7366
+ "chalksurf sheet versions 00000000-0000-4000-8000-000000000001 --json",
7367
+ "List restorable sheet versions for an agent audit"
7368
+ ),
7369
+ async (argv) => {
7370
+ const id = resolveRequestedUuid2({
7371
+ fallbackValue: argv.exerciseSheetId,
7372
+ label: "exerciseSheetId",
7373
+ required: true
7374
+ });
7375
+ const { apiClient, organizationId } = await createResolvedApiClient({
7376
+ context,
7377
+ baseUrlFlagValue: argv.baseUrl,
7378
+ organizationFlagValue: argv.organization,
7379
+ profileName: argv.profile
7380
+ });
7381
+ let result;
7382
+ try {
7383
+ result = await apiClient.agentListSheetVersions(id);
7384
+ } catch (error) {
7385
+ throw mapApiErrorToCliError(error);
7386
+ }
7387
+ context.output.print(
7388
+ {
7389
+ request: {
7390
+ id,
7391
+ organizationId: organizationId ?? null
7392
+ },
7393
+ versions: result.versions
7394
+ },
7395
+ (output) => formatSheetVersionListOutput({ versions: output.versions }),
7396
+ {
7397
+ command: "sheet versions"
7398
+ }
7399
+ );
7400
+ }
7401
+ ).command(
7402
+ "version [exerciseSheetId] [versionId]",
7403
+ "Get one exercise sheet version snapshot",
7404
+ (versionYargs) => versionYargs.positional("exerciseSheetId", {
7405
+ type: "string",
7406
+ describe: "Exercise sheet ID to inspect"
7407
+ }).positional("versionId", {
7408
+ type: "string",
7409
+ describe: "Sheet version ID to fetch"
7410
+ }).example(
7411
+ "chalksurf sheet version 00000000-0000-4000-8000-000000000001 00000000-0000-4000-8000-000000000002 --json",
7412
+ "Fetch one sheet version snapshot for an agent audit"
7413
+ ),
7414
+ async (argv) => {
7415
+ const exerciseSheetId = resolveRequestedUuid2({
7416
+ fallbackValue: argv.exerciseSheetId,
7417
+ label: "exerciseSheetId",
7418
+ required: true
7419
+ });
7420
+ const versionId = resolveRequestedUuid2({
7421
+ fallbackValue: argv.versionId,
7422
+ label: "versionId",
7423
+ required: true
7424
+ });
7425
+ const { apiClient, organizationId } = await createResolvedApiClient({
7426
+ context,
7427
+ baseUrlFlagValue: argv.baseUrl,
7428
+ organizationFlagValue: argv.organization,
7429
+ profileName: argv.profile
7430
+ });
7431
+ let result;
7432
+ try {
7433
+ result = await apiClient.agentGetSheetVersion(exerciseSheetId, versionId);
7434
+ } catch (error) {
7435
+ throw mapApiErrorToCliError(error);
7436
+ }
7437
+ context.output.print(
7438
+ {
7439
+ request: {
7440
+ exerciseSheetId,
7441
+ versionId,
7442
+ organizationId: organizationId ?? null
7443
+ },
7444
+ version: result.version
7445
+ },
7446
+ (output) => formatSheetVersionDetailsOutput({ version: output.version }),
7447
+ {
7448
+ command: "sheet version"
7449
+ }
7450
+ );
7451
+ }
5282
7452
  ).command(
5283
7453
  "issues [exerciseSheetId]",
5284
7454
  "List actionable issues for an exercise sheet",
@@ -5404,6 +7574,58 @@ var registerSheetCommands = (sheetYargs, context) => {
5404
7574
  }
5405
7575
  );
5406
7576
  }
7577
+ ).command(
7578
+ "delete [folderId]",
7579
+ "Delete an empty folder after confirmation",
7580
+ (deleteYargs) => deleteYargs.positional("folderId", {
7581
+ type: "string",
7582
+ describe: "Folder ID to delete"
7583
+ }).option("confirm-resource-id", {
7584
+ type: "string",
7585
+ demandOption: true,
7586
+ describe: "Must exactly match the folder ID being deleted"
7587
+ }).example(
7588
+ "chalksurf sheet folder delete 00000000-0000-4000-8000-000000000001 --confirm-resource-id 00000000-0000-4000-8000-000000000001 --json",
7589
+ "Delete an empty folder with destructive confirmation"
7590
+ ),
7591
+ async (argv) => {
7592
+ const id = resolveRequestedUuid2({
7593
+ fallbackValue: argv.folderId,
7594
+ label: "folderId",
7595
+ required: true
7596
+ });
7597
+ const confirmResourceId = resolveRequestedUuid2({
7598
+ flagValue: argv.confirmResourceId,
7599
+ label: "--confirm-resource-id",
7600
+ required: true
7601
+ });
7602
+ const input = { id, confirmResourceId };
7603
+ const { apiClient, organizationId } = await createResolvedApiClient({
7604
+ context,
7605
+ baseUrlFlagValue: argv.baseUrl,
7606
+ organizationFlagValue: argv.organization,
7607
+ profileName: argv.profile
7608
+ });
7609
+ let result;
7610
+ try {
7611
+ result = await apiClient.agentDeleteFolder(input);
7612
+ } catch (error) {
7613
+ throw mapApiErrorToCliError(error);
7614
+ }
7615
+ context.output.print(
7616
+ {
7617
+ request: {
7618
+ ...input,
7619
+ organizationId: organizationId ?? null
7620
+ },
7621
+ receipt: result.receipt
7622
+ },
7623
+ (output) => formatDeleteFolderOutput({ receipt: output.receipt }),
7624
+ {
7625
+ command: "sheet folder delete"
7626
+ }
7627
+ );
7628
+ }
5407
7629
  ).command(
5408
7630
  "rename [folderId] [name]",
5409
7631
  "Rename a folder in the selected organization",
@@ -5454,6 +7676,176 @@ var registerSheetCommands = (sheetYargs, context) => {
5454
7676
  ).demandCommand(1),
5455
7677
  () => {
5456
7678
  }
7679
+ ).command(
7680
+ "create",
7681
+ "Create an exercise sheet from an agent JSON payload",
7682
+ (createYargs) => createYargs.option("input-json", {
7683
+ type: "string",
7684
+ demandOption: true,
7685
+ describe: "JSON object matching the agent sheet create contract"
7686
+ }).example(
7687
+ `chalksurf sheet create --input-json '{"name":"Practice","language":"english","exerciseIds":["00000000-0000-4000-8000-000000000001"]}' --json`,
7688
+ "Create a sheet for an agent workflow"
7689
+ ),
7690
+ async (argv) => {
7691
+ const input = parseCreateSheetAgentInput(
7692
+ parseJsonObjectFlag({ label: "--input-json", value: argv.inputJson })
7693
+ );
7694
+ const { apiClient, organizationId } = await createResolvedApiClient({
7695
+ context,
7696
+ baseUrlFlagValue: argv.baseUrl,
7697
+ organizationFlagValue: argv.organization,
7698
+ profileName: argv.profile
7699
+ });
7700
+ let result;
7701
+ try {
7702
+ result = await apiClient.agentCreateSheet(input);
7703
+ } catch (error) {
7704
+ throw mapApiErrorToCliError(error);
7705
+ }
7706
+ context.output.print(
7707
+ {
7708
+ request: {
7709
+ ...input,
7710
+ organizationId: organizationId ?? null
7711
+ },
7712
+ receipt: result.receipt
7713
+ },
7714
+ (output) => formatCreateSheetOutput({ receipt: output.receipt }),
7715
+ {
7716
+ command: "sheet create"
7717
+ }
7718
+ );
7719
+ }
7720
+ ).command(
7721
+ "delete [exerciseSheetId]",
7722
+ "Delete an exercise sheet after confirmation",
7723
+ (deleteYargs) => deleteYargs.positional("exerciseSheetId", {
7724
+ type: "string",
7725
+ describe: "Exercise sheet ID to delete"
7726
+ }).option("expected-updated-at", {
7727
+ type: "string",
7728
+ demandOption: true,
7729
+ describe: "Expected current sheet updated_at ISO timestamp"
7730
+ }).option("confirm-resource-id", {
7731
+ type: "string",
7732
+ demandOption: true,
7733
+ describe: "Must exactly match the sheet ID being deleted"
7734
+ }).example(
7735
+ "chalksurf sheet delete 00000000-0000-4000-8000-000000000001 --expected-updated-at 2026-01-01T00:00:00.000Z --confirm-resource-id 00000000-0000-4000-8000-000000000001 --json",
7736
+ "Delete a sheet with destructive confirmation"
7737
+ ),
7738
+ async (argv) => {
7739
+ const id = resolveRequestedUuid2({
7740
+ fallbackValue: argv.exerciseSheetId,
7741
+ label: "exerciseSheetId",
7742
+ required: true
7743
+ });
7744
+ const confirmResourceId = resolveRequestedUuid2({
7745
+ flagValue: argv.confirmResourceId,
7746
+ label: "--confirm-resource-id",
7747
+ required: true
7748
+ });
7749
+ const input = {
7750
+ id,
7751
+ expectedUpdatedAt: argv.expectedUpdatedAt,
7752
+ confirmResourceId
7753
+ };
7754
+ const { apiClient, organizationId } = await createResolvedApiClient({
7755
+ context,
7756
+ baseUrlFlagValue: argv.baseUrl,
7757
+ organizationFlagValue: argv.organization,
7758
+ profileName: argv.profile
7759
+ });
7760
+ let result;
7761
+ try {
7762
+ result = await apiClient.agentDeleteSheet(input);
7763
+ } catch (error) {
7764
+ throw mapApiErrorToCliError(error);
7765
+ }
7766
+ context.output.print(
7767
+ {
7768
+ request: {
7769
+ ...input,
7770
+ organizationId: organizationId ?? null
7771
+ },
7772
+ receipt: result.receipt
7773
+ },
7774
+ (output) => formatDeleteSheetOutput({ receipt: output.receipt }),
7775
+ {
7776
+ command: "sheet delete"
7777
+ }
7778
+ );
7779
+ }
7780
+ ).command(
7781
+ "set-visibility [exerciseSheetId]",
7782
+ "Set sheet visibility after checking the current updated_at value",
7783
+ (visibilityYargs) => visibilityYargs.positional("exerciseSheetId", {
7784
+ type: "string",
7785
+ describe: "Exercise sheet ID to update"
7786
+ }).option("expected-updated-at", {
7787
+ type: "string",
7788
+ demandOption: true,
7789
+ describe: "Expected current sheet updated_at ISO timestamp"
7790
+ }).option("public", {
7791
+ type: "boolean",
7792
+ describe: "Make the sheet public"
7793
+ }).option("private", {
7794
+ type: "boolean",
7795
+ describe: "Make the sheet private"
7796
+ }).option("confirm-make-public-resource-id", {
7797
+ type: "string",
7798
+ describe: "Required when using --public; must exactly match the sheet ID"
7799
+ }).example(
7800
+ "chalksurf sheet set-visibility 00000000-0000-4000-8000-000000000001 --public --expected-updated-at 2026-01-01T00:00:00.000Z --confirm-make-public-resource-id 00000000-0000-4000-8000-000000000001 --json",
7801
+ "Make a sheet public with confirmation"
7802
+ ),
7803
+ async (argv) => {
7804
+ const id = resolveRequestedUuid2({
7805
+ fallbackValue: argv.exerciseSheetId,
7806
+ label: "exerciseSheetId",
7807
+ required: true
7808
+ });
7809
+ const isPublic = resolveVisibilityFlag2({
7810
+ privateFlag: argv.private,
7811
+ publicFlag: argv.public
7812
+ });
7813
+ const confirmMakePublicResourceId = resolveRequestedUuid2({
7814
+ flagValue: argv.confirmMakePublicResourceId,
7815
+ label: "--confirm-make-public-resource-id"
7816
+ });
7817
+ const input = {
7818
+ id,
7819
+ expectedUpdatedAt: argv.expectedUpdatedAt,
7820
+ isPublic,
7821
+ ...confirmMakePublicResourceId === void 0 ? {} : { confirmMakePublicResourceId }
7822
+ };
7823
+ const { apiClient, organizationId } = await createResolvedApiClient({
7824
+ context,
7825
+ baseUrlFlagValue: argv.baseUrl,
7826
+ organizationFlagValue: argv.organization,
7827
+ profileName: argv.profile
7828
+ });
7829
+ let result;
7830
+ try {
7831
+ result = await apiClient.agentSetSheetVisibility(input);
7832
+ } catch (error) {
7833
+ throw mapApiErrorToCliError(error);
7834
+ }
7835
+ context.output.print(
7836
+ {
7837
+ request: {
7838
+ ...input,
7839
+ organizationId: organizationId ?? null
7840
+ },
7841
+ receipt: result.receipt
7842
+ },
7843
+ (output) => formatSetSheetVisibilityOutput({ receipt: output.receipt }),
7844
+ {
7845
+ command: "sheet set-visibility"
7846
+ }
7847
+ );
7848
+ }
5457
7849
  ).command(
5458
7850
  "copy [exerciseSheetId] [name]",
5459
7851
  "Copy a visible exercise sheet into the selected organization",
@@ -6215,6 +8607,12 @@ var createCli = ({
6215
8607
  (exerciseYargs) => registerExerciseCommands(exerciseYargs, commandContext),
6216
8608
  () => {
6217
8609
  }
8610
+ ).command(
8611
+ "feedback <subcommand>",
8612
+ "Feedback commands",
8613
+ (feedbackYargs) => registerFeedbackCommands(feedbackYargs, commandContext),
8614
+ () => {
8615
+ }
6218
8616
  ).command(
6219
8617
  "sheet <subcommand>",
6220
8618
  "Exercise sheet commands",
@@ -6250,7 +8648,7 @@ var parseCliWithCapturedOutput = async ({
6250
8648
  var hasFlag = (argv, flags) => {
6251
8649
  return argv.some((argument) => flags.includes(argument));
6252
8650
  };
6253
- var topLevelCommands = /* @__PURE__ */ new Set(["auth", "org", "profile", "exercise", "sheet", "job"]);
8651
+ var topLevelCommands = /* @__PURE__ */ new Set(["auth", "org", "profile", "exercise", "feedback", "sheet", "job"]);
6254
8652
  var hasTopLevelCommand = (argv) => {
6255
8653
  return argv.some((argument) => topLevelCommands.has(argument));
6256
8654
  };