@design.estate/dees-catalog 6.1.0 → 6.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.
Files changed (50) hide show
  1. package/dist_bundle/bundle.js +3161 -1498
  2. package/dist_ts_web/00_commitinfo_data.js +1 -1
  3. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.d.ts +5 -1
  4. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.js +484 -8
  5. package/dist_ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.js +33 -2
  6. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.d.ts +6 -4
  7. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.demo.js +7 -1
  8. package/dist_ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.js +67 -6
  9. package/dist_ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.d.ts +3 -1
  10. package/dist_ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.js +24 -4
  11. package/dist_ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.d.ts +26 -0
  12. package/dist_ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.js +398 -94
  13. package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.d.ts +32 -0
  14. package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.demo.d.ts +1 -0
  15. package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.demo.js +31 -0
  16. package/dist_ts_web/elements/00group-harness/dees-harness-overflow-text.js +297 -0
  17. package/dist_ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.js +1 -9
  18. package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.d.ts +10 -1
  19. package/dist_ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.js +181 -2
  20. package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.d.ts +17 -1
  21. package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.js +476 -36
  22. package/dist_ts_web/elements/00group-harness/dees-harness-tool-card/renderers.js +23 -20
  23. package/dist_ts_web/elements/00group-harness/harness.helpers.d.ts +5 -1
  24. package/dist_ts_web/elements/00group-harness/harness.helpers.js +66 -1
  25. package/dist_ts_web/elements/00group-harness/index.d.ts +1 -0
  26. package/dist_ts_web/elements/00group-harness/index.js +2 -1
  27. package/dist_ts_web/elements/00group-harness/interfaces.d.ts +39 -2
  28. package/dist_ts_web/elements/00group-harness/toolregistry.d.ts +4 -0
  29. package/dist_ts_web/elements/00group-harness/toolregistry.js +8 -1
  30. package/package.json +2 -2
  31. package/readme.hints.md +16 -1
  32. package/readme.md +48 -11
  33. package/readme.playbook.md +8 -4
  34. package/ts_web/00_commitinfo_data.ts +1 -1
  35. package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.demo.ts +490 -7
  36. package/ts_web/elements/00group-harness/dees-harness-chat/dees-harness-chat.ts +22 -0
  37. package/ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.demo.ts +6 -0
  38. package/ts_web/elements/00group-harness/dees-harness-composer/dees-harness-composer.ts +64 -5
  39. package/ts_web/elements/00group-harness/dees-harness-message/dees-harness-message.ts +24 -3
  40. package/ts_web/elements/00group-harness/dees-harness-message-list/dees-harness-message-list.ts +397 -84
  41. package/ts_web/elements/00group-harness/dees-harness-overflow-text.demo.ts +31 -0
  42. package/ts_web/elements/00group-harness/dees-harness-overflow-text.ts +236 -0
  43. package/ts_web/elements/00group-harness/dees-harness-session-list/dees-harness-session-list.ts +0 -8
  44. package/ts_web/elements/00group-harness/dees-harness-session-sidebar/dees-harness-session-sidebar.ts +193 -1
  45. package/ts_web/elements/00group-harness/dees-harness-tool-card/dees-harness-tool-card.ts +480 -34
  46. package/ts_web/elements/00group-harness/dees-harness-tool-card/renderers.ts +24 -21
  47. package/ts_web/elements/00group-harness/harness.helpers.ts +68 -1
  48. package/ts_web/elements/00group-harness/index.ts +1 -0
  49. package/ts_web/elements/00group-harness/interfaces.ts +46 -2
  50. package/ts_web/elements/00group-harness/toolregistry.ts +12 -0
@@ -256,33 +256,36 @@ const renderSearch = (call: IHarnessToolCall, helpers: IHarnessToolRenderHelpers
256
256
  `;
257
257
  };
258
258
 
259
- const renderSubtask = (call: IHarnessToolCall, helpers: IHarnessToolRenderHelpers): TemplateResult => {
259
+ const renderSubtask = (call: IHarnessToolCall): TemplateResult => {
260
260
  const input = inputRecord(call);
261
261
  const prompt = String(input.prompt ?? input.description ?? '');
262
+ const projectedResult = call.subtask?.previewState === 'ready'
263
+ && call.subtask.status.type !== 'busy'
264
+ ? [...call.subtask.messages].reverse().find(
265
+ (message) => message.role === 'assistant' && Boolean(message.text),
266
+ )?.text ?? ''
267
+ : '';
268
+ const result = outputText(call) || projectedResult;
269
+ const terminal = call.subtask
270
+ ? call.subtask.status.type !== 'busy'
271
+ : call.status === 'completed' || call.status === 'error';
262
272
  return html`
263
- ${call.childSessionId
273
+ ${prompt
264
274
  ? html`
265
- <button
266
- class="harness-subtask-open"
267
- type="button"
268
- @click=${(event: Event) => {
269
- (event.currentTarget as HTMLElement).dispatchEvent(
270
- new CustomEvent('harness-subtask-open', {
271
- detail: { sessionId: call.childSessionId, call },
272
- bubbles: true,
273
- composed: true,
274
- }),
275
- );
276
- }}
277
- >
278
- ${call.status === 'completed' || call.status === 'error'
279
- ? 'Open subagent chat'
280
- : 'Follow subagent live'}
281
- </button>
275
+ <section class="harness-subtask-detail harness-subtask-detail-brief">
276
+ <div class="harness-subtask-detail-label">Agent Brief</div>
277
+ <div class="harness-subtask-detail-text">${prompt}</div>
278
+ </section>
279
+ `
280
+ : ''}
281
+ ${result || terminal
282
+ ? html`
283
+ <section class="harness-subtask-detail harness-subtask-detail-result">
284
+ <div class="harness-subtask-detail-label">Result</div>
285
+ <div class="harness-subtask-detail-text">${result || 'No result was returned.'}</div>
286
+ </section>
282
287
  `
283
288
  : ''}
284
- ${prompt ? helpers.monoBlock(prompt) : ''}
285
- ${outputText(call) ? helpers.monoBlock(outputText(call)) : ''}
286
289
  `;
287
290
  };
288
291
 
@@ -3,7 +3,13 @@
3
3
  * detection, attachment constraints, and defensive value summarization.
4
4
  * No DOM access; safe to import from anywhere including tests.
5
5
  */
6
- import type { IHarnessTodoItem } from './interfaces.js';
6
+ import type {
7
+ IHarnessMessage,
8
+ IHarnessTodoItem,
9
+ IHarnessToolCall,
10
+ THarnessMessageStreamDelta,
11
+ THarnessToolStatus,
12
+ } from './interfaces.js';
7
13
 
8
14
  export const harnessMaxAttachmentBytes = 10 * 1024 * 1024;
9
15
  export const harnessMaxTotalAttachmentBytes = 30 * 1024 * 1024;
@@ -89,6 +95,17 @@ export const harnessIsRecord = (value: unknown): value is Record<string, unknown
89
95
  return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
90
96
  };
91
97
 
98
+ /** Uses the child projection as the status authority for subagent calls. */
99
+ export const harnessEffectiveToolStatus = (callArg: IHarnessToolCall): THarnessToolStatus => {
100
+ if (callArg.subtask) {
101
+ if (callArg.subtask.status.type === 'busy') return 'running';
102
+ if (callArg.subtask.status.type === 'error') return 'error';
103
+ return 'completed';
104
+ }
105
+ if (callArg.isError || callArg.status === 'error') return 'error';
106
+ return callArg.status;
107
+ };
108
+
92
109
  export const harnessFormatBytes = (bytes: unknown): string => {
93
110
  const value = typeof bytes === 'number' && Number.isFinite(bytes) ? bytes : 0;
94
111
  if (value < 1024) return `${value} B`;
@@ -153,6 +170,56 @@ export const harnessAttachmentKindFor = (mediaType: string): 'image' | 'text' |
153
170
  return 'binary';
154
171
  };
155
172
 
173
+ /** Mutates one normalized message when no rendered message element owns it. */
174
+ export const harnessApplyMessageDelta = (
175
+ messages: IHarnessMessage[],
176
+ delta: THarnessMessageStreamDelta,
177
+ ): IHarnessMessage | undefined => {
178
+ const message = messages.find((candidate) => candidate.id === delta.messageId);
179
+ if (!message) return undefined;
180
+ switch (delta.type) {
181
+ case 'text':
182
+ message.text += delta.delta;
183
+ message.streaming = true;
184
+ break;
185
+ case 'reasoning-start':
186
+ message.reasoning ??= [];
187
+ if (!message.reasoning.some((part) => part.id === delta.partId)) {
188
+ message.reasoning.push({
189
+ id: delta.partId,
190
+ text: '',
191
+ startedAt: delta.startedAt ?? Date.now(),
192
+ });
193
+ }
194
+ break;
195
+ case 'reasoning': {
196
+ message.reasoning ??= [];
197
+ const part = message.reasoning.find((candidate) => candidate.id === delta.partId);
198
+ if (part) part.text += delta.delta;
199
+ else message.reasoning.push({ id: delta.partId, text: delta.delta, startedAt: Date.now() });
200
+ break;
201
+ }
202
+ case 'reasoning-end': {
203
+ const part = message.reasoning?.find((candidate) => candidate.id === delta.partId);
204
+ if (part && !part.endedAt) part.endedAt = delta.endedAt ?? Date.now();
205
+ break;
206
+ }
207
+ case 'tool-update':
208
+ message.toolCall = {
209
+ ...(message.toolCall ?? { id: delta.tool.id, name: '', status: 'pending' }),
210
+ ...delta.tool,
211
+ };
212
+ break;
213
+ case 'message-end':
214
+ message.streaming = false;
215
+ if (delta.usage) message.usage = delta.usage;
216
+ if (delta.error) message.error = delta.error;
217
+ message.updatedAt = Date.now();
218
+ break;
219
+ }
220
+ return message;
221
+ };
222
+
156
223
  export const harnessFileToBase64 = (file: File): Promise<string> =>
157
224
  new Promise<string>((resolve, reject) => {
158
225
  const reader = new FileReader();
@@ -7,6 +7,7 @@ export * from './harness.helpers.js';
7
7
  export { HarnessMarkdown, markdownStyles } from './harness.markdown.js';
8
8
  export { harnessCardStyles, harnessPillStyles, harnessMonoStyles } from './harness.styles.js';
9
9
  export * from './harness.demodata.js';
10
+ export * from './dees-harness-overflow-text.js';
10
11
 
11
12
  export * from './dees-harness-chat/index.js';
12
13
  export * from './dees-harness-composer/index.js';
@@ -182,6 +182,8 @@ export interface IHarnessToolCall {
182
182
  mcp?: IHarnessMcpMeta;
183
183
  /** Session spawned by this call (subagent/task tools); enables drill-in. */
184
184
  childSessionId?: string;
185
+ /** Bounded live preview of the spawned session. Consumers own hydration. */
186
+ subtask?: IHarnessSubtaskStream;
185
187
  /** model the spawned session runs on, e.g. "anthropic/claude-opus-5" */
186
188
  model?: string;
187
189
  /** epoch ms */
@@ -189,6 +191,29 @@ export interface IHarnessToolCall {
189
191
  finishedAt?: number;
190
192
  }
191
193
 
194
+ interface IHarnessSubtaskStreamBase {
195
+ sessionId: string;
196
+ status: IHarnessStatus;
197
+ }
198
+
199
+ export type IHarnessSubtaskStream =
200
+ | (IHarnessSubtaskStreamBase & {
201
+ previewState: 'loading';
202
+ notice?: string;
203
+ })
204
+ | (IHarnessSubtaskStreamBase & {
205
+ previewState: 'ready';
206
+ messages: IHarnessMessage[];
207
+ permissions?: IHarnessPermissionRequest[];
208
+ questions?: IHarnessQuestionRequest[];
209
+ truncated?: boolean;
210
+ notice?: string;
211
+ })
212
+ | (IHarnessSubtaskStreamBase & {
213
+ previewState: 'unavailable';
214
+ notice: string;
215
+ });
216
+
192
217
  /** Detail of `harness-subtask-open`, fired when a subagent card is drilled into. */
193
218
  export interface IHarnessSubtaskOpenDetail {
194
219
  sessionId: string;
@@ -268,7 +293,7 @@ export interface IHarnessSessionMeta {
268
293
  icon?: string;
269
294
  /** Visual card state. Defaults to `normal`. */
270
295
  state?: THarnessSessionCardState;
271
- /** Independent activity signal used for idle-to-working auto-expansion. */
296
+ /** Independent activity signal for hosts that track work separately from the visual state. */
272
297
  working?: boolean;
273
298
  /** Set false for pinned, non-sortable entries such as terminals. Defaults to true. */
274
299
  draggable?: boolean;
@@ -325,9 +350,19 @@ export interface IHarnessStatus {
325
350
 
326
351
  // ---------------------------------------------------------------- composer
327
352
 
353
+ export interface IHarnessComposerOption {
354
+ label: string;
355
+ value: string;
356
+ }
357
+
358
+ export interface IHarnessAccountChangeDetail {
359
+ account: string;
360
+ }
361
+
328
362
  export interface IHarnessComposerSendDetail {
329
363
  text: string;
330
364
  attachments: IHarnessAttachment[];
365
+ account?: string;
331
366
  model?: string;
332
367
  reasoningEffort?: string;
333
368
  }
@@ -340,10 +375,19 @@ export interface IHarnessComposerSendDetail {
340
375
  * re-assignment is idempotent) and re-render only the affected message
341
376
  * element.
342
377
  */
343
- export type THarnessStreamDelta =
378
+ export type THarnessMessageStreamDelta =
344
379
  | { type: 'text'; messageId: string; delta: string }
345
380
  | { type: 'reasoning-start'; messageId: string; partId: string; startedAt?: number }
346
381
  | { type: 'reasoning'; messageId: string; partId: string; delta: string }
347
382
  | { type: 'reasoning-end'; messageId: string; partId: string; endedAt?: number }
348
383
  | { type: 'tool-update'; messageId: string; tool: Partial<IHarnessToolCall> & { id: string } }
349
384
  | { type: 'message-end'; messageId: string; usage?: IHarnessUsage; error?: string };
385
+
386
+ /**
387
+ * A delta without `parentMessageId` addresses the outer transcript. Setting
388
+ * it routes the same update into one subtask transcript; inline recursion is
389
+ * intentionally limited to one level.
390
+ */
391
+ export type THarnessStreamDelta = THarnessMessageStreamDelta & {
392
+ parentMessageId?: string;
393
+ };
@@ -22,6 +22,8 @@ export interface IHarnessToolRenderHelpers {
22
22
  image(dataBase64: string, mimeType: string, alt?: string): TemplateResult;
23
23
  }
24
24
 
25
+ export type THarnessToolLayout = 'compact' | 'full-row' | 'subtask';
26
+
25
27
  export interface IHarnessToolDescriptor {
26
28
  /** stable kind id, e.g. 'terminal', 'file-read', 'mcp', 'unknown' */
27
29
  kind: string;
@@ -40,6 +42,8 @@ export interface IHarnessToolDescriptor {
40
42
  */
41
43
  renderBody?: (call: IHarnessToolCall, helpers: IHarnessToolRenderHelpers) => TemplateResult;
42
44
  defaultExpanded?: boolean | ((call: IHarnessToolCall) => boolean);
45
+ /** Transcript grid packing; omitted descriptors use the compact layout. */
46
+ layout?: THarnessToolLayout;
43
47
  /** styles the card with a destructive accent regardless of status */
44
48
  destructive?: boolean;
45
49
  }
@@ -81,6 +85,7 @@ const defaultDescriptors: IHarnessToolDescriptor[] = [
81
85
  return command ? `${command}${cwd ? ` — in ${cwd}` : ''}` : harnessSummaryLine(call.input);
82
86
  },
83
87
  defaultExpanded: true,
88
+ layout: 'full-row',
84
89
  },
85
90
  {
86
91
  kind: 'file-read',
@@ -111,6 +116,7 @@ const defaultDescriptors: IHarnessToolDescriptor[] = [
111
116
  return harnessSummaryLine(call.input);
112
117
  },
113
118
  defaultExpanded: true,
119
+ layout: 'full-row',
114
120
  },
115
121
  {
116
122
  kind: 'file-delete',
@@ -179,6 +185,8 @@ const defaultDescriptors: IHarnessToolDescriptor[] = [
179
185
  || harnessSummaryLine(call.input);
180
186
  return call.model ? `${description} — ${call.model}` : description;
181
187
  },
188
+ defaultExpanded: (call) => call.subtask?.status.type === 'busy',
189
+ layout: 'subtask',
182
190
  },
183
191
  {
184
192
  kind: 'question',
@@ -282,6 +290,10 @@ export class DeesHarnessToolRegistry {
282
290
  return this.resolve({ id: '', name, status: 'completed' }).kind;
283
291
  }
284
292
 
293
+ public resolveLayout(call: IHarnessToolCall): THarnessToolLayout {
294
+ return this.resolve(call).layout ?? 'compact';
295
+ }
296
+
285
297
  /** Isolated copy for demos, tests, or per-pane toolsets. */
286
298
  public fork(): DeesHarnessToolRegistry {
287
299
  return new DeesHarnessToolRegistry(this.descriptors.map((descriptor) => ({ ...descriptor })));