@abelxiaoxing/cadence 1.2.1 → 1.2.3

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.
@@ -87,7 +87,6 @@ export type ActivitySummary = EvidenceActivitySummary | DiffActivitySummary;
87
87
  export type ActivityTone = "accent" | "success" | "warning" | "muted" | "error";
88
88
 
89
89
  export interface ActivityDisplay {
90
- version: 1;
91
90
  kind: "activityDisplay";
92
91
  requestId: string;
93
92
  role: string;
@@ -188,6 +187,7 @@ export function sanitizeDisplayText(value: unknown, maxLength = 240): string {
188
187
  }
189
188
 
190
189
  const SAFE_WORKFLOW_CODE = /^[a-z0-9](?:[a-z0-9._:-]{0,126}[a-z0-9])?$/iu;
190
+ const SAFE_DESIGN_DETAIL_VALUE = /^[a-z0-9](?:[a-z0-9._:-]{0,126}[a-z0-9])?$/iu;
191
191
  const SAFE_CONTROL_ACTIONS = new Set([
192
192
  "start",
193
193
  "status",
@@ -221,6 +221,82 @@ export function sanitizeFailureReason(value: unknown, maxLength = 240): string {
221
221
  return safe.slice(0, Math.max(0, maxLength));
222
222
  }
223
223
 
224
+ function safeDesignFailure(value: unknown): {
225
+ operation: string;
226
+ code: string;
227
+ diagnostics: Array<Record<string, string>>;
228
+ } | null {
229
+ const failure = asRecord(value);
230
+ if (
231
+ failure?.kind !== "design-control-failure" ||
232
+ typeof failure.operation !== "string" ||
233
+ !SAFE_DESIGN_DETAIL_VALUE.test(failure.operation) ||
234
+ typeof failure.code !== "string" ||
235
+ !SAFE_DESIGN_DETAIL_VALUE.test(failure.code) ||
236
+ !Array.isArray(failure.diagnostics)
237
+ ) {
238
+ return null;
239
+ }
240
+ const diagnostics = failure.diagnostics.flatMap((candidate) => {
241
+ const record = asRecord(candidate);
242
+ if (
243
+ !record ||
244
+ typeof record.code !== "string" ||
245
+ !SAFE_DESIGN_DETAIL_VALUE.test(record.code)
246
+ ) {
247
+ return [];
248
+ }
249
+ return [
250
+ Object.fromEntries(
251
+ Object.entries(record).filter(
252
+ ([, entry]) =>
253
+ typeof entry === "string" && SAFE_DESIGN_DETAIL_VALUE.test(entry),
254
+ ),
255
+ ) as Record<string, string>,
256
+ ];
257
+ });
258
+ return {
259
+ operation: failure.operation,
260
+ code: failure.code,
261
+ diagnostics,
262
+ };
263
+ }
264
+
265
+ function renderDesignFailure(
266
+ failure: ReturnType<typeof safeDesignFailure> & object,
267
+ expanded: boolean,
268
+ theme?: ActivityTheme,
269
+ ): Component {
270
+ const title = styled(
271
+ theme,
272
+ "error",
273
+ `${dispatchLabel("design")} ${failure.operation} failed: ${failure.code}`,
274
+ );
275
+ if (!expanded || failure.diagnostics.length === 0) {
276
+ const suffix =
277
+ failure.diagnostics.length > 0
278
+ ? styled(
279
+ theme,
280
+ "muted",
281
+ ` (${failure.diagnostics.length} diagnostic${failure.diagnostics.length === 1 ? "" : "s"})`,
282
+ )
283
+ : "";
284
+ return new Text(`${title}${suffix}`, 0, 0);
285
+ }
286
+ const lines = failure.diagnostics.map((diagnostic) => {
287
+ const details = Object.entries(diagnostic)
288
+ .filter(([key]) => key !== "code")
289
+ .map(([key, value]) => `${key}=${value}`)
290
+ .join(" · ");
291
+ return ` - ${diagnostic.code}${details ? ` · ${details}` : ""}`;
292
+ });
293
+ return new Text(
294
+ [title, ...lines.map((entry) => styled(theme, "muted", entry))].join("\n"),
295
+ 0,
296
+ 0,
297
+ );
298
+ }
299
+
224
300
  export function formatElapsed(milliseconds: number): string {
225
301
  const value = Math.max(
226
302
  0,
@@ -470,6 +546,7 @@ function workflowStateOf(
470
546
  }
471
547
  const state = result.state;
472
548
  switch (state) {
549
+ case "not-started":
473
550
  case "created":
474
551
  case "ready":
475
552
  case "queued":
@@ -659,7 +736,6 @@ export function projectWorkflowActivity(
659
736
  ? "completion-state-inconsistent"
660
737
  : workflowCode(payload);
661
738
  return {
662
- version: 1,
663
739
  kind: "activityDisplay",
664
740
  requestId: sanitizeDisplayText(
665
741
  runId ?? taskId ?? change ?? command.operationId ?? "pending",
@@ -792,7 +868,6 @@ function displayFromEvent(
792
868
  ): ActivityDisplay {
793
869
  const reason = event.failureReason;
794
870
  return {
795
- version: 1,
796
871
  kind: "activityDisplay",
797
872
  requestId: entry.requestId,
798
873
  role: entry.role,
@@ -989,7 +1064,6 @@ export class ActivityController {
989
1064
  const entry = this.entries.get(toolCallId);
990
1065
  if (!entry) return;
991
1066
  const display: ActivityDisplay = {
992
- version: 1,
993
1067
  kind: "activityDisplay",
994
1068
  requestId: entry.requestId,
995
1069
  role: entry.role,
@@ -1230,7 +1304,6 @@ export function renderActivityResult(
1230
1304
  if (failedRun) {
1231
1305
  const snapshot = identityFromDispatchArgs(asRecord(context?.args)?.request);
1232
1306
  const display: ActivityDisplay = {
1233
- version: 1,
1234
1307
  kind: "activityDisplay",
1235
1308
  requestId: isActivityDisplay(activity)
1236
1309
  ? activity.requestId
@@ -1250,6 +1323,10 @@ export function renderActivityResult(
1250
1323
  return new ActivityInlineComponent(display, theme);
1251
1324
  }
1252
1325
  if (failed) {
1326
+ const designFailure = safeDesignFailure(details?.designFailure);
1327
+ if (args?.action === "design" && designFailure) {
1328
+ return renderDesignFailure(designFailure, options.expanded, theme);
1329
+ }
1253
1330
  return new Text(
1254
1331
  `${dispatchLabel(args?.action ?? args?.command)} failed`,
1255
1332
  0,
@@ -1275,7 +1352,6 @@ function isActivityDisplay(value: unknown): value is ActivityDisplay {
1275
1352
  const record = asRecord(value);
1276
1353
  return (
1277
1354
  record?.kind === "activityDisplay" &&
1278
- record.version === 1 &&
1279
1355
  typeof record.requestId === "string" &&
1280
1356
  typeof record.role === "string" &&
1281
1357
  typeof record.phase === "string" &&