@design.estate/dees-catalog 11.0.0 → 11.2.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.
Files changed (22) hide show
  1. package/dist_bundle/bundle.js +114 -17
  2. package/dist_bundle/bundle.js.map +1 -1
  3. package/dist_ts_web/00_commitinfo_data.js +1 -1
  4. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.js +46 -1
  5. package/dist_ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.js +19 -2
  6. package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.demo.js +9 -7
  7. package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.js +14 -5
  8. package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.js +19 -1
  9. package/dist_ts_web/elements/00group-harness/harness.helpers.js +4 -2
  10. package/dist_ts_web/elements/00group-harness/interfaces.d.ts +4 -0
  11. package/dist_ts_web/elements/00group-harness/toolregistry.js +10 -6
  12. package/package.json +1 -1
  13. package/readme.md +4 -4
  14. package/ts_web/00_commitinfo_data.ts +1 -1
  15. package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.ts +45 -0
  16. package/ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.ts +18 -1
  17. package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.demo.ts +8 -6
  18. package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.ts +15 -4
  19. package/ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.ts +18 -0
  20. package/ts_web/elements/00group-harness/harness.helpers.ts +3 -1
  21. package/ts_web/elements/00group-harness/interfaces.ts +4 -0
  22. package/ts_web/elements/00group-harness/toolregistry.ts +9 -5
@@ -40,13 +40,13 @@ const stages: Record<TDemoStage, { state: NonNullable<IHarnessSessionMeta['state
40
40
  };
41
41
 
42
42
  const demoSessions = (): IDemoSession[] => [
43
- { title: 'Fix sitemap cache key', harness: { id: 'codex', name: 'Codex' }, stage: 'approval' as const },
44
- { title: 'Investigate model rate limits', harness: { id: 'opencode', name: 'OpenCode' }, stage: 'working' as const },
45
- { title: 'Refactor workbench layout', harness: { id: 'flexharness', name: 'FlexHarness' }, stage: 'feedback' as const },
46
- { title: 'Add adaptive code diffs', harness: { id: 'codex', name: 'Codex' }, stage: 'finished' as const },
47
- { title: 'Prepare the catalog release', harness: { id: 'opencode', name: 'OpenCode' }, stage: 'error' as const },
43
+ { title: 'Fix sitemap cache key', harness: { id: 'codex', name: 'Codex' }, projectLabel: 'storefront', stage: 'approval' as const },
44
+ { title: 'Investigate model rate limits', harness: { id: 'opencode', name: 'OpenCode' }, projectLabel: 'gateway', stage: 'working' as const },
45
+ { title: 'Refactor workbench layout', harness: { id: 'flexharness', name: 'FlexHarness' }, projectLabel: 'storefront', stage: 'feedback' as const },
46
+ { title: 'Add adaptive code diffs', harness: { id: 'codex', name: 'Codex' }, projectLabel: 'catalog', stage: 'finished' as const },
47
+ { title: 'Prepare the catalog release', harness: { id: 'opencode', name: 'OpenCode' }, projectLabel: 'catalog', stage: 'error' as const },
48
48
  { title: 'Improve agent onboarding', harness: { id: 'flexharness', name: 'FlexHarness' }, stage: 'idle' as const },
49
- { title: 'Draft the migration guide', harness: { id: 'codex', name: 'Codex' }, stage: 'starting' as const },
49
+ { title: 'Draft the migration guide', harness: { id: 'codex', name: 'Codex' }, projectLabel: 'gateway', stage: 'starting' as const },
50
50
  ].map((session, index) => ({
51
51
  ...session,
52
52
  id: `session-${index}`,
@@ -97,6 +97,7 @@ const demoResources: IHarnessResourceMeta[] = [
97
97
  title: 'Build shell',
98
98
  icon: 'lucide:Terminal',
99
99
  preview: 'pnpm run build',
100
+ projectLabel: 'storefront',
100
101
  updatedAt: Date.now() - 90_000,
101
102
  state: 'ready',
102
103
  },
@@ -106,6 +107,7 @@ const demoResources: IHarnessResourceMeta[] = [
106
107
  title: 'Release notes',
107
108
  icon: 'lucide:FileText',
108
109
  preview: 'Catalog migration notes',
110
+ projectLabel: 'catalog',
109
111
  updatedAt: Date.now() - 180_000,
110
112
  },
111
113
  {
@@ -528,7 +528,8 @@ export class DeesHarnessSessionList extends DeesElement {
528
528
  line-height: 14px;
529
529
  }
530
530
 
531
- .harnessName {
531
+ .harnessName,
532
+ .projectName {
532
533
  min-width: 0;
533
534
  overflow: hidden;
534
535
  text-overflow: ellipsis;
@@ -1064,7 +1065,8 @@ export class DeesHarnessSessionList extends DeesElement {
1064
1065
  }
1065
1066
 
1066
1067
  private resourceMatchesSearch(resourceArg: IHarnessResourceMeta, queryArg: string): boolean {
1067
- return [resourceArg.id, resourceArg.kind, resourceArg.title, resourceArg.preview]
1068
+ return [resourceArg.id, resourceArg.kind, resourceArg.title, resourceArg.preview,
1069
+ resourceArg.projectLabel]
1068
1070
  .filter(Boolean)
1069
1071
  .join(' ')
1070
1072
  .toLowerCase()
@@ -1073,7 +1075,8 @@ export class DeesHarnessSessionList extends DeesElement {
1073
1075
 
1074
1076
  private sessionMatchesSearch(sessionArg: IHarnessSessionMeta, queryArg: string): boolean {
1075
1077
  return [sessionArg.title, sessionArg.preview, sessionArg.id, sessionArg.harness?.id,
1076
- sessionArg.harness?.name, this.sessionStatusLabel(sessionArg), this.sessionStateLabel(sessionArg.state ?? 'normal')]
1078
+ sessionArg.harness?.name, sessionArg.projectLabel,
1079
+ this.sessionStatusLabel(sessionArg), this.sessionStateLabel(sessionArg.state ?? 'normal')]
1077
1080
  .filter(Boolean)
1078
1081
  .join(' ')
1079
1082
  .toLowerCase()
@@ -1509,6 +1512,7 @@ export class DeesHarnessSessionList extends DeesElement {
1509
1512
  const detailsId = `session-details-${session.id}`;
1510
1513
  const dropIndex = index < 0 ? 0 : index;
1511
1514
  const title = session.title || session.id;
1515
+ const projectLabel = session.projectLabel?.trim() ?? '';
1512
1516
  return html`
1513
1517
  <article
1514
1518
  class="item state-${state} ${active ? 'active' : ''} ${expanded ? 'expanded' : ''} ${
@@ -1577,6 +1581,10 @@ export class DeesHarnessSessionList extends DeesElement {
1577
1581
  <span class="harnessName" title=${session.harness.name}>${session.harness.name}</span>
1578
1582
  <span aria-hidden="true">·</span>
1579
1583
  ` : ''}
1584
+ ${projectLabel ? html`
1585
+ <span class="projectName" title=${projectLabel}>${projectLabel}</span>
1586
+ <span aria-hidden="true">·</span>
1587
+ ` : ''}
1580
1588
  <span class="itemTime">${harnessFormatRelativeTime(session.updatedAt ?? session.createdAt)}</span>
1581
1589
  </span>
1582
1590
  </span>
@@ -1634,6 +1642,7 @@ export class DeesHarnessSessionList extends DeesElement {
1634
1642
  const contextOpen = resourceArg.id === this.resourceContextResourceId;
1635
1643
  const attachedTitle = attachedTarget ? this.itemTitleFor(attachedTarget) : '';
1636
1644
  const title = resourceArg.title || resourceArg.id;
1645
+ const projectLabel = resourceArg.projectLabel?.trim() ?? '';
1637
1646
  const dropIndex = indexArg < 0 ? 0 : indexArg;
1638
1647
  return html`
1639
1648
  <article
@@ -1695,7 +1704,9 @@ export class DeesHarnessSessionList extends DeesElement {
1695
1704
  <span class="resourceTitle">${title}</span>
1696
1705
  ${resourceArg.preview ? html`<span class="resourcePreview">${resourceArg.preview}</span>` : ''}
1697
1706
  <span class="resourceMeta">
1698
- ${resourceArg.kind}${resourceArg.state ? ` · ${resourceArg.state}` : ''}${
1707
+ ${resourceArg.kind}${projectLabel ? ` · ${projectLabel}` : ''}${
1708
+ resourceArg.state ? ` · ${resourceArg.state}` : ''
1709
+ }${
1699
1710
  resourceArg.updatedAt || resourceArg.createdAt
1700
1711
  ? ` · ${harnessFormatRelativeTime(resourceArg.updatedAt ?? resourceArg.createdAt)}`
1701
1712
  : ''
@@ -131,7 +131,21 @@ export class DeesHarnessToolCard extends DeesElement {
131
131
  :host {
132
132
  display: block;
133
133
  container-type: inline-size;
134
+ margin-inline: auto;
135
+ max-width: 100%;
134
136
  font-family: var(--dees-font-family);
137
+ transition: max-width var(--dees-transition-default) var(--dees-ease-standard);
138
+ }
139
+
140
+ /*
141
+ * A collapsed card may be held to a narrower measure than its row. The host — not the inner
142
+ * surface — carries the constraint so the card's own inline-size container keeps measuring
143
+ * what is actually rendered. The width comes from the context the card sits in: a transcript
144
+ * row that holds this card alone sets it, a multi-card grid cell leaves it unset, and a
145
+ * direct host falls back to the full row.
146
+ */
147
+ :host([data-collapsed]) {
148
+ max-width: var(--dees-harness-collapsed-tool-width, 100%);
135
149
  }
136
150
 
137
151
  .harness-card.subtaskPreviewCard {
@@ -1006,6 +1020,10 @@ export class DeesHarnessToolCard extends DeesElement {
1006
1020
 
1007
1021
  public updated(changedProperties: Map<PropertyKey, unknown>): void {
1008
1022
  super.updated(changedProperties);
1023
+ // Mirrors the rendered disclosure state onto the host so the width rule can follow it. Set
1024
+ // during the update that produced the render, so a card that mounts collapsed reaches its
1025
+ // first style resolution already constrained and never animates on mount.
1026
+ this.toggleAttribute('data-collapsed', !this.isOpen);
1009
1027
  if (!this.isConnected) return;
1010
1028
  this.terminalScrollHydrationFrame ??= requestAnimationFrame(() => {
1011
1029
  this.terminalScrollHydrationFrame = null;
@@ -369,7 +369,9 @@ export const harnessTerminalResultSummary = (callArg: IHarnessToolCall): string
369
369
  const combined = `${stdout}${stdout && stderr ? '\n' : ''}${stderr}`;
370
370
  const lineCount = combined ? harnessStripAnsi(combined).split('\n').filter((line) => line.trim()).length : 0;
371
371
  if (lineCount > 0) parts.push(`${lineCount} ${lineCount === 1 ? 'line' : 'lines'}`);
372
- else if (exitCode !== undefined) parts.push('no output');
372
+ // Without an exit code there is nothing else to report, so a silent command still says so
373
+ // rather than collapsing to a bare command line. No exit code is ever invented here.
374
+ else parts.push('no output');
373
375
  const lastLine = harnessLastMeaningfulLine(stderr) || harnessLastMeaningfulLine(stdout);
374
376
  const prefix = parts.join(' · ');
375
377
  if (!lastLine) return prefix;
@@ -355,6 +355,8 @@ export interface IHarnessSessionMeta {
355
355
  statusLabel?: string;
356
356
  /** Harness running this session, e.g. Codex, OpenCode or FlexHarness. */
357
357
  harness?: IHarnessAgentIdentity;
358
+ /** Host-owned project or workspace this session belongs to, shown on the identity line. */
359
+ projectLabel?: string;
358
360
  /** Pulse the normal/working indicator. Defaults to state === 'working'; never pulses attention/error/finished. */
359
361
  working?: boolean;
360
362
  /** Set false for pinned, non-sortable entries such as terminals. Defaults to true. */
@@ -390,6 +392,8 @@ export interface IHarnessResourceMeta<TState extends string = string> {
390
392
  preview?: string;
391
393
  createdAt?: number;
392
394
  updatedAt?: number;
395
+ /** Host-owned project or workspace this resource belongs to, shown on the metadata line. */
396
+ projectLabel?: string;
393
397
  /** Optional host-defined display state. */
394
398
  state?: TState;
395
399
  /** Set false for pinned, non-sortable entries. Defaults to true. */
@@ -115,12 +115,16 @@ const defaultDescriptors: IHarnessToolDescriptor[] = [
115
115
  defaultExpanded: true,
116
116
  layout: 'full-row',
117
117
  /*
118
- * Only a command that can be PROVEN to have succeeded collapses. An absent exit code is not
119
- * evidence of success: a producer that reports a failed command as completed and encodes the
120
- * failure in its output would otherwise have that failure hidden behind a one-line summary.
121
- * Such a card stays open, and the producer reporting an exit code is the real fix.
118
+ * A finished command collapses unless it reports a failure. A missing exit code is not a
119
+ * failure — most harnesses never send one — so requiring proof of success kept nearly every
120
+ * terminal card open and left whole transcripts expanded. A non-zero exit keeps its output on
121
+ * screen; an error or a stopped command never reaches this rule, because the card keeps those
122
+ * open on status alone. The user's own expand or collapse still wins over all of it.
122
123
  */
123
- collapseWhenFinished: (call) => harnessTerminalOutcome(call).exitCode === 0,
124
+ collapseWhenFinished: (call) => {
125
+ const { exitCode } = harnessTerminalOutcome(call);
126
+ return exitCode === undefined || exitCode === 0;
127
+ },
124
128
  summary: harnessTerminalResultSummary,
125
129
  },
126
130
  {