@aparte/core 0.9.0 → 0.11.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 (109) hide show
  1. package/dist/client/aparte-client.d.ts +54 -33
  2. package/dist/client/aparte-client.d.ts.map +1 -1
  3. package/dist/client/stream-adapter.d.ts +6 -1
  4. package/dist/client/stream-adapter.d.ts.map +1 -1
  5. package/dist/components/bubble/aparte-chat-bubble.d.ts +49 -7
  6. package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
  7. package/dist/components/chat/aparte-chat.d.ts +8 -4
  8. package/dist/components/chat/aparte-chat.d.ts.map +1 -1
  9. package/dist/components/composer/aparte-composer-action.d.ts +5 -5
  10. package/dist/components/composer/aparte-composer-action.d.ts.map +1 -1
  11. package/dist/components/composer/aparte-composer-add-attachment.d.ts +16 -4
  12. package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -1
  13. package/dist/components/composer/aparte-composer-attachments.d.ts +5 -3
  14. package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -1
  15. package/dist/components/composer/aparte-composer-cancel.d.ts +10 -2
  16. package/dist/components/composer/aparte-composer-cancel.d.ts.map +1 -1
  17. package/dist/components/composer/aparte-composer-input.d.ts +8 -5
  18. package/dist/components/composer/aparte-composer-input.d.ts.map +1 -1
  19. package/dist/components/composer/aparte-composer-send.d.ts +34 -2
  20. package/dist/components/composer/aparte-composer-send.d.ts.map +1 -1
  21. package/dist/components/composer/aparte-composer-toolbar.d.ts +3 -3
  22. package/dist/components/composer/aparte-composer.d.ts +54 -10
  23. package/dist/components/composer/aparte-composer.d.ts.map +1 -1
  24. package/dist/components/conversation-list/aparte-conversation-list.d.ts +19 -12
  25. package/dist/components/conversation-list/aparte-conversation-list.d.ts.map +1 -1
  26. package/dist/components/elicitation/aparte-elicitation.d.ts +22 -0
  27. package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -1
  28. package/dist/components/status/aparte-chat-status.d.ts +9 -0
  29. package/dist/components/status/aparte-chat-status.d.ts.map +1 -1
  30. package/dist/components/viewport/aparte-chat-viewport.d.ts +18 -5
  31. package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
  32. package/dist/config/aparte-config.d.ts +54 -2
  33. package/dist/config/aparte-config.d.ts.map +1 -1
  34. package/dist/config/config-subscribe.d.ts +4 -0
  35. package/dist/config/config-subscribe.d.ts.map +1 -0
  36. package/dist/config/index.d.ts +1 -0
  37. package/dist/config/index.d.ts.map +1 -1
  38. package/dist/config/locale.d.ts +141 -0
  39. package/dist/config/locale.d.ts.map +1 -1
  40. package/dist/config/sanitize.d.ts.map +1 -1
  41. package/dist/custom-elements.json +5905 -4694
  42. package/dist/elicitation/approval-panel.d.ts +42 -0
  43. package/dist/elicitation/approval-panel.d.ts.map +1 -0
  44. package/dist/elicitation/index.d.ts +4 -1
  45. package/dist/elicitation/index.d.ts.map +1 -1
  46. package/dist/elicitation/panel.d.ts +14 -1
  47. package/dist/elicitation/panel.d.ts.map +1 -1
  48. package/dist/elicitation/types.d.ts +116 -9
  49. package/dist/elicitation/types.d.ts.map +1 -1
  50. package/dist/generated/element-attributes.d.ts +173 -0
  51. package/dist/generated/element-attributes.d.ts.map +1 -0
  52. package/dist/host/aparte-chat-host.d.ts +3 -1
  53. package/dist/host/aparte-chat-host.d.ts.map +1 -1
  54. package/dist/index.css +752 -392
  55. package/dist/index.d.ts +5 -4
  56. package/dist/index.d.ts.map +1 -1
  57. package/dist/index.js +538 -290
  58. package/dist/index.js.map +1 -1
  59. package/dist/index.node.d.ts +5 -4
  60. package/dist/index.node.d.ts.map +1 -1
  61. package/dist/index.node.js +62 -57
  62. package/dist/index.node.js.map +1 -1
  63. package/dist/interop/element-props.d.ts +26 -1
  64. package/dist/interop/element-props.d.ts.map +1 -1
  65. package/dist/{index-hQQljwfX.js → is-awaiting-reply-Cb7H3YfN.js} +1159 -972
  66. package/dist/is-awaiting-reply-Cb7H3YfN.js.map +1 -0
  67. package/dist/parsers/aparte-stream-parser.d.ts.map +1 -1
  68. package/dist/primitives/select/aparte-optgroup.d.ts +3 -0
  69. package/dist/primitives/select/aparte-optgroup.d.ts.map +1 -1
  70. package/dist/primitives/select/aparte-option.d.ts +1 -0
  71. package/dist/primitives/select/aparte-option.d.ts.map +1 -1
  72. package/dist/primitives/select/aparte-select.d.ts +22 -18
  73. package/dist/primitives/select/aparte-select.d.ts.map +1 -1
  74. package/dist/renderers/highlight-stream.d.ts +17 -0
  75. package/dist/renderers/highlight-stream.d.ts.map +1 -0
  76. package/dist/renderers/segment-renderers.d.ts.map +1 -1
  77. package/dist/renderers/segments/artifact/binary-file.d.ts.map +1 -1
  78. package/dist/renderers/segments/artifact/card.d.ts.map +1 -1
  79. package/dist/renderers/segments/artifact/shared.d.ts +19 -2
  80. package/dist/renderers/segments/artifact/shared.d.ts.map +1 -1
  81. package/dist/renderers/segments/code.d.ts.map +1 -1
  82. package/dist/renderers/segments/error.d.ts.map +1 -1
  83. package/dist/renderers/segments/pipeline-waiting.d.ts.map +1 -1
  84. package/dist/renderers/segments/thinking.d.ts.map +1 -1
  85. package/dist/renderers/segments/tool-call.d.ts.map +1 -1
  86. package/dist/types/element-attributes.d.ts +42 -0
  87. package/dist/types/element-attributes.d.ts.map +1 -0
  88. package/dist/types/event-map.d.ts +2 -4
  89. package/dist/types/event-map.d.ts.map +1 -1
  90. package/dist/types/events.d.ts +0 -22
  91. package/dist/types/events.d.ts.map +1 -1
  92. package/dist/types/index.d.ts +4 -3
  93. package/dist/types/index.d.ts.map +1 -1
  94. package/dist/types/models.d.ts +1 -6
  95. package/dist/types/models.d.ts.map +1 -1
  96. package/dist/types/segments.d.ts +87 -74
  97. package/dist/types/segments.d.ts.map +1 -1
  98. package/dist/types/tools.d.ts +15 -21
  99. package/dist/types/tools.d.ts.map +1 -1
  100. package/dist/utils/segments.d.ts +83 -5
  101. package/dist/utils/segments.d.ts.map +1 -1
  102. package/package.json +3 -2
  103. package/dist/index-hQQljwfX.js.map +0 -1
  104. package/dist/renderers/segments/file-tree.d.ts +0 -3
  105. package/dist/renderers/segments/file-tree.d.ts.map +0 -1
  106. package/dist/renderers/segments/progress.d.ts +0 -3
  107. package/dist/renderers/segments/progress.d.ts.map +0 -1
  108. package/dist/renderers/segments/terminal.d.ts +0 -3
  109. package/dist/renderers/segments/terminal.d.ts.map +0 -1
@@ -17,41 +17,88 @@ export interface AparteSegmentBase {
17
17
  * insertions and removals.
18
18
  */
19
19
  index?: number;
20
- /** Epoch ms when the segment entered the transcript. */
20
+ /**
21
+ * Extras the producer of the segment knows — token counts, cost, compute
22
+ * device — plus `aparte`, the one sub-object core writes.
23
+ *
24
+ * Everything except `meta.aparte` is yours: fill it with
25
+ * `updateSegment(segmentId, { meta })`, which MERGES rather than replaces.
26
+ * Mirrors `AparteMessage.metadata`.
27
+ */
28
+ meta?: Record<string, unknown> & {
29
+ aparte?: AparteSegmentTiming;
30
+ };
31
+ }
32
+ /**
33
+ * What core measured about a segment. Lives in `meta.aparte`, not on the segment.
34
+ *
35
+ * These two were first-class fields, and moving them is not tidying. **No protocol
36
+ * carries a timestamp on a content block** — verified rather than assumed: Anthropic's
37
+ * blocks have none (and neither does the message), OpenAI's `output_text` part is
38
+ * `{annotations, logprobs, text, type}` with `created_at` on the item above it, and the
39
+ * AI SDK's `UIMessage.parts` have none either. What the AI SDK does have is a metadata
40
+ * bag whose canonical example is literally `{ createdAt, model, totalTokens }` — at the
41
+ * message level. A per-block `id` has industry precedent; per-block time has none.
42
+ *
43
+ * So this is a **local measurement**, and the shape says so. It stays typed — the bag is
44
+ * where it belongs, opacity is not part of the deal — and it is namespaced under
45
+ * `aparte` because `meta` is the consumer's: a flat `startedAt` there would collide
46
+ * with a key of their own.
47
+ *
48
+ * Core reads it through {@link segmentDuration} and {@link isSegmentSettled}; it never
49
+ * renders either number.
50
+ */
51
+ export interface AparteSegmentTiming {
52
+ /** Epoch ms when the segment entered a LIVE transcript. Absent for history. */
21
53
  startedAt?: number;
22
54
  /**
23
55
  * Epoch ms when content last arrived on this segment.
24
56
  *
25
- * It ADVANCES while the segment streams and freezes when the segment settles,
26
- * so `endedAt - startedAt` is a live duration during a turn and a final one
27
- * after it — ask `isSegmentSettled(segment)` which you are looking at. Core
28
- * never renders either.
57
+ * It ADVANCES while the segment streams and freezes when the segment settles, so
58
+ * `endedAt - startedAt` is a live duration during a turn and a final one after it
59
+ * — ask `isSegmentSettled(segment)` which you are looking at.
29
60
  *
30
61
  * Why not simply "when it finished": the two obvious rules are both wrong, and
31
62
  * measurably. Closing at the end of the turn makes a reasoning block span the
32
- * whole answer that followed it (2s of thinking before a 20s reply reads
33
- * "22s"). Closing when the next segment opens is the same error, smaller — a
34
- * gap of ten seconds before the next segment is counted as thinking, while the
35
- * person watching knows nothing happened. The last delta is the only moment
36
- * the segment itself can vouch for.
63
+ * whole answer that followed it (2s of thinking before a 20s reply reads "22s").
64
+ * Closing when the next segment opens is the same error, smaller — a gap of ten
65
+ * seconds before the next segment is counted as thinking, while the person
66
+ * watching knows nothing happened. The last delta is the only moment the segment
67
+ * itself can vouch for.
37
68
  */
38
69
  endedAt?: number;
39
- /**
40
- * Extras only the producer of the segment can know — token counts, cost,
41
- * compute device. Core writes nothing here: fill it from an app with
42
- * `updateSegment(segmentId, { meta })`. Mirrors `AparteMessage.metadata`.
43
- */
44
- meta?: Record<string, unknown>;
45
70
  }
46
71
  /** Text segment - plain text content */
47
72
  export interface AparteTextSegment extends AparteSegmentBase {
48
73
  type: 'text';
49
74
  content: string;
50
75
  }
76
+ /**
77
+ * Field defaults for one segment TYPE, merged when a segment enters a message.
78
+ *
79
+ * A record and not a `Partial<AparteSegment>` on purpose: the type key is a string,
80
+ * a consumer's own segment type is as valid as a built-in one, and its fields cannot
81
+ * be known here. What CANNOT be defaulted is identity — `id`, `type`, `messageId`,
82
+ * `index`, `startedAt`, `endedAt` are refused, because a default `id` would give
83
+ * every segment in a conversation the same one.
84
+ */
85
+ export type AparteSegmentDefaults = Readonly<Record<string, unknown>>;
51
86
  /** Thinking/reasoning segment - collapsible */
52
87
  export interface AparteThinkingSegment extends AparteSegmentBase {
53
88
  type: 'thinking';
54
89
  content: string;
90
+ /**
91
+ * Open the block. **Absent means CLOSED** — a reasoning block is a disclosure,
92
+ * and the reader opens it.
93
+ *
94
+ * It used to be the other way round: absent meant open, and core's own parser
95
+ * emitted `collapsed: false` on every block it produced, so a reasoning block
96
+ * stayed unfolded for the whole conversation and buried the answer under it. No
97
+ * assistant on the market does that — the content is behind a click, streaming
98
+ * or settled.
99
+ *
100
+ * `false` is still how you open one on purpose. Only ABSENT changed meaning.
101
+ */
55
102
  collapsed?: boolean;
56
103
  label?: string;
57
104
  }
@@ -63,56 +110,6 @@ export interface AparteCodeSegment extends AparteSegmentBase {
63
110
  filename?: string;
64
111
  showLineNumbers?: boolean;
65
112
  }
66
- /** Diff segment - before/after code comparison */
67
- export interface AparteDiffSegment extends AparteSegmentBase {
68
- type: 'diff';
69
- filename?: string;
70
- hunks: AparteDiffHunk[];
71
- }
72
- export interface AparteDiffHunk {
73
- oldStart: number;
74
- newStart: number;
75
- lines: AparteDiffLine[];
76
- }
77
- export interface AparteDiffLine {
78
- type: 'add' | 'remove' | 'context';
79
- content: string;
80
- }
81
- /** Terminal/console segment - command execution */
82
- export interface AparteTerminalSegment extends AparteSegmentBase {
83
- type: 'terminal';
84
- command?: string;
85
- output?: string;
86
- exitCode?: number;
87
- isRunning?: boolean;
88
- }
89
- /** File tree segment - directory structure */
90
- export interface AparteFileTreeSegment extends AparteSegmentBase {
91
- type: 'file-tree';
92
- files: AparteFileNode[];
93
- title?: string;
94
- }
95
- export interface AparteFileNode {
96
- name: string;
97
- path: string;
98
- type: 'file' | 'directory';
99
- children?: AparteFileNode[];
100
- status?: 'added' | 'modified' | 'deleted';
101
- }
102
- /** Image segment */
103
- export interface AparteImageSegment extends AparteSegmentBase {
104
- type: 'image';
105
- url: string;
106
- alt?: string;
107
- caption?: string;
108
- }
109
- /** Preview/iframe segment */
110
- export interface ApartePreviewSegment extends AparteSegmentBase {
111
- type: 'preview';
112
- url: string;
113
- title?: string;
114
- height?: number;
115
- }
116
113
  /** Error segment */
117
114
  export interface AparteErrorSegment extends AparteSegmentBase {
118
115
  type: 'error';
@@ -120,13 +117,6 @@ export interface AparteErrorSegment extends AparteSegmentBase {
120
117
  details?: string;
121
118
  stack?: string;
122
119
  }
123
- /** Progress segment - for long operations */
124
- export interface AparteProgressSegment extends AparteSegmentBase {
125
- type: 'progress';
126
- label: string;
127
- percent?: number;
128
- status?: 'pending' | 'running' | 'complete' | 'error';
129
- }
130
120
  /** Tool call segment - rendered while waiting for a tool handler to resolve */
131
121
  export interface AparteToolCallSegment extends AparteSegmentBase {
132
122
  type: 'tool_call';
@@ -187,7 +177,7 @@ export interface ApartePipelineWaitingSegment extends AparteSegmentBase {
187
177
  type: 'pipeline-waiting';
188
178
  }
189
179
  /** All built-in segment types */
190
- export type AparteSegment = AparteTextSegment | AparteThinkingSegment | AparteCodeSegment | AparteDiffSegment | AparteTerminalSegment | AparteFileTreeSegment | AparteImageSegment | ApartePreviewSegment | AparteErrorSegment | AparteProgressSegment | AparteCustomSegment | AparteToolCallSegment | AparteArtifactSegment | ApartePipelineWaitingSegment;
180
+ export type AparteSegment = AparteTextSegment | AparteThinkingSegment | AparteCodeSegment | AparteErrorSegment | AparteCustomSegment | AparteToolCallSegment | AparteArtifactSegment | ApartePipelineWaitingSegment;
191
181
  /** Segment type discriminator values */
192
182
  export type AparteSegmentType = AparteSegment['type'];
193
183
  /**
@@ -230,6 +220,29 @@ export interface AparteSegmentRenderer<T extends AparteSegmentBase = AparteSegme
230
220
  * so the MutationObserver (childList) doesn't fire and scroll stays stable.
231
221
  */
232
222
  update?(element: HTMLElement, segment: T): void;
223
+ /**
224
+ * Optional: re-read the CONFIG-DERIVED text of an already-rendered segment —
225
+ * an icon from the icon provider, a label from the locale.
226
+ *
227
+ * Called when the config changes (a language switch, a new icon set), on every
228
+ * segment already on screen. Bound by the same rule as `update()`: **must not
229
+ * add or remove child nodes** — only attributes and textContent — so the
230
+ * viewport's childList observer stays quiet and scroll does not move.
231
+ *
232
+ * This exists because the obvious alternative does not work. Re-rendering the
233
+ * segments container to pick up a new locale destroys state the DOM owns and the
234
+ * segment data does not: a mounted sandboxed artifact preview, a reasoning block
235
+ * the reader expanded by clicking `<summary>` (which never writes back to
236
+ * `collapsed`), scroll position inside a long terminal, the focus on an
237
+ * Approve/Reject gate, and the buffered lookahead of the incremental Markdown
238
+ * parser mid-stream. It also fires container-wide childList mutations, which is
239
+ * exactly what the rule above forbids.
240
+ *
241
+ * Implement it only if the rendered output contains text or icons that came from
242
+ * the config. A renderer whose chrome is entirely its own data — `progress`,
243
+ * `text` — correctly does not, exactly as it does not implement `update()`.
244
+ */
245
+ relabel?(element: HTMLElement, segment: T): void;
233
246
  /**
234
247
  * Optional: Cleanup when segment is removed
235
248
  * @param element - The DOM element being removed
@@ -1 +1 @@
1
- {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/types/segments.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/types/segments.ts"],"names":[],"mappings":"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"}
@@ -18,30 +18,24 @@ export interface AparteTool {
18
18
  maxTurns?: number;
19
19
  /**
20
20
  * When true, the agent loop pauses before running this tool's handler and
21
- * waits for a human decision (approve / reject) — "human in the loop". The
22
- * UI surfaces Approve/Reject (default renderer, or a custom tool renderer)
23
- * and resolves it by dispatching an `aparte-tool-decision` event. On reject,
24
- * a synthetic "rejected by user" result is injected and the turn stops.
21
+ * waits for a human decision — "human in the loop".
22
+ *
23
+ * The decision is asked AT THE COMPOSER, through the same `requestUserInput`
24
+ * a tool handler calls: every request for the user is answered in one place.
25
+ * The row in the transcript is the anchor, naming which tool is waiting, and
26
+ * holds nothing clickable. An `approvalResolver` on `AparteClientOptions`
27
+ * answers it programmatically instead.
28
+ *
29
+ * On a refusal the rest of the turn is skipped — no later tool call of the
30
+ * same turn runs — and then the model gets a turn to answer it, so it can
31
+ * say what it will do instead. The refusal may carry the user's own words.
32
+ *
33
+ * All three clauses of this comment used to say something else: the default
34
+ * renderer surfaced the buttons, an `aparte-tool-decision` event resolved
35
+ * them, and a refusal ended the turn. None of that is true any more.
25
36
  */
26
37
  needsApproval?: boolean;
27
38
  }
28
- /**
29
- * Detail for `aparte-tool-decision` — the human's verdict on a tool awaiting
30
- * approval. Dispatched by the approval UI (built-in or app-provided) and
31
- * consumed by the agent loop to resume or reject.
32
- */
33
- export interface AparteToolDecisionDetail {
34
- toolCallId: string;
35
- approved: boolean;
36
- /**
37
- * Optional payload from a custom approval surface. When it is a plain object
38
- * and the decision is `approved`, the agent loop merges it onto the tool's
39
- * input before invoking the handler — so a human can edit the arguments
40
- * before the tool runs (correct a path, tighten a query, …). The built-in
41
- * Approve/Reject gate sends no payload, so existing flows are unchanged.
42
- */
43
- payload?: unknown;
44
- }
45
39
  /**
46
40
  * Detail for `aparte-tool-approval-request` — emitted by the loop when a tool
47
41
  * marked `needsApproval` is about to run. Apps may listen to show a richer
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,8GAA8G;IAC9G,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,wBAAwB;IACrC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAA+B;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC5B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,iBAAiB,KAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,MAAM,GAAG,WAAW,CAAC;IACjE,8EAA8E;IAC9E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACvE,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../../src/types/tools.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,2CAA2C;AAC3C,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,8GAA8G;IAC9G,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;;;;;;;;;;;;OAiBG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED;;;;GAIG;AACH,MAAM,WAAW,+BAA+B;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,qDAAqD;AACrD,MAAM,WAAW,cAAc;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC;AAED,oDAAoD;AACpD,MAAM,WAAW,gBAAgB;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAC5B,IAAI,EAAE,cAAc,EACpB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,iBAAiB,KAC1B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,kBAAkB;IAC/B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,MAAM,GAAG,WAAW,CAAC;IACjE,8EAA8E;IAC9E,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACvE,qDAAqD;IACrD,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC;CAC5B"}
@@ -27,7 +27,7 @@
27
27
  * Everything here is pure and DOM-free, so a consumer can test their own wiring in
28
28
  * Node — the introspectability half of the reachability rule.
29
29
  */
30
- import type { AparteSegment } from '../types/index.js';
30
+ import type { AparteSegmentDefaults, AparteSegmentTiming, AparteSegment } from '../types/index.js';
31
31
  /**
32
32
  * Stamp identity and start time on a segment joining `segments` at the tail.
33
33
  *
@@ -38,7 +38,49 @@ import type { AparteSegment } from '../types/index.js';
38
38
  * A value already present is never overwritten, so a segment rehydrated from a
39
39
  * consumer's storage keeps the numbers it was persisted with.
40
40
  */
41
- export declare function stampSegmentOnInsert(segments: readonly AparteSegment[], segment: AparteSegment, messageId: string): AparteSegment;
41
+ export declare function stampSegmentOnInsert(segments: readonly AparteSegment[], segment: AparteSegment, messageId: string, defaults?: AparteSegmentDefaults): AparteSegment;
42
+ /**
43
+ * A segment arriving from STORAGE or a server, rather than starting now.
44
+ *
45
+ * The counterpart of {@link stampSegmentOnInsert}, and the reason it exists: the two
46
+ * are not the same act, and treating them as one made the library invent history.
47
+ * `stampSegmentOnInsert` ran on every arrival path including a reload, so a
48
+ * conversation from three weeks ago came back claiming each of its segments had
49
+ * started this second — while THREE other load paths did not stamp at all, so the same
50
+ * stored conversation produced different numbers depending on the mode and on whether
51
+ * a branch tree had been saved. Not a lie so much as an incoherence.
52
+ *
53
+ * What it writes, and why each:
54
+ *
55
+ * - `messageId` and `index` are **recomputed**, not preserved. They are derivable
56
+ * facts about the array this segment is joining, so a stored value can only
57
+ * contradict it — and no protocol persists either (Anthropic's block `index` exists
58
+ * only in the streaming envelope, as a position).
59
+ * - **no time, ever.** A measurement nobody took is absent, not zero and not now.
60
+ * `segmentDuration` already answers `undefined` for that, so a consumer reading
61
+ * through the helper degrades correctly.
62
+ * - `isStreaming: false`, unconditionally. A persisted stream is dead: restoring one
63
+ * with `isStreaming: true` would render a caret forever, and — through
64
+ * `openSegmentIds`, which reads exactly this flag — would have the next turn-close
65
+ * stamp it a brand-new `endedAt`.
66
+ * - a `tool_call` persisted as `awaiting-approval` becomes `'aborted'`, for the same
67
+ * reason and through a hole the line above cannot reach: `isSegmentSettled` reads
68
+ * STATUS for a tool call, not `isStreaming`, so a restored gate stayed OPEN. The loop
69
+ * that awaited the decision is gone and the promise it would have settled went with
70
+ * the page, so the request is unanswerable — and `'aborted'` rather than `'rejected'`
71
+ * because nobody refused anything. Documented as a consumer's problem in the
72
+ * persistence guide until now ("normalise those statuses on save"), which is a
73
+ * normalisation this function was already the single funnel for.
74
+ */
75
+ export declare function adoptSegment(segments: readonly AparteSegment[], segment: AparteSegment, messageId: string): AparteSegment;
76
+ /**
77
+ * Read core's own measurements off a segment.
78
+ *
79
+ * A function rather than a property access because it is read from six places, and
80
+ * `segment.meta?.aparte` spelled six times is six chances to spell it differently —
81
+ * which is exactly how this repo's recurring bug starts.
82
+ */
83
+ export declare function segmentTiming(segment: Pick<AparteSegment, 'meta'>): AparteSegmentTiming | undefined;
42
84
  /**
43
85
  * Has this segment settled? The trigger for `endedAt`.
44
86
  *
@@ -76,6 +118,21 @@ export declare function isSegmentSettled(segment: AparteSegment): boolean;
76
118
  * counter that ticks while a model reasons is the same number, read earlier.
77
119
  */
78
120
  export declare function stampSegmentOnUpdate(segment: AparteSegment, updates: Partial<AparteSegment>): Partial<AparteSegment>;
121
+ /**
122
+ * Merge an update into a segment without one writer erasing the other's `meta`.
123
+ *
124
+ * `{ ...segment, ...updates }` is wrong now that `meta` has two writers. A consumer's
125
+ * `updateSegment(id, { meta: { cost } })` is presentation, not activity, so it passes
126
+ * through {@link stampSegmentOnUpdate} untouched — and a plain spread would then
127
+ * replace the whole bag and take `meta.aparte` with it. The measurement would vanish
128
+ * the first time an app wrote a token count, which is precisely when it matters.
129
+ *
130
+ * So the bag is merged one level, and `aparte` inside it merged again. Every site that
131
+ * folds an update into a segment goes through here — the viewport, the host and the
132
+ * bubble each had their own spread, which is three chances to fix this twice and miss
133
+ * once.
134
+ */
135
+ export declare function mergeSegmentUpdate(segment: AparteSegment, updates: Partial<AparteSegment>): AparteSegment;
79
136
  /**
80
137
  * How long this segment took, or `undefined` when that is not knowable yet.
81
138
  *
@@ -113,9 +170,7 @@ export declare function segmentDuration(segment: AparteSegment): number | undefi
113
170
  *
114
171
  * Empty once the segment has settled, so a late write cannot move a final end.
115
172
  */
116
- export declare function stampSegmentActivity(segment: AparteSegment): {
117
- endedAt?: number;
118
- };
173
+ export declare function stampSegmentActivity(segment: AparteSegment): Partial<AparteSegment>;
119
174
  /**
120
175
  * The update that forwards a parser-emitted segment's content — carrying the fact
121
176
  * that it CLOSED, when it did.
@@ -162,6 +217,29 @@ export declare function isTerminalStatus(status: string | null | undefined): boo
162
217
  * re-render, a branch switch, a reloaded conversation — cannot move an end.
163
218
  */
164
219
  export declare function openSegmentIds(segments: readonly AparteSegment[]): string[];
220
+ /**
221
+ * Adopt every segment of a message arriving from storage or a server.
222
+ *
223
+ * The message-level counterpart of {@link adoptSegment}, and the reason it exists as a
224
+ * function rather than a loop written four times: there are FOUR entry paths for
225
+ * historical data (`setMessages`, `importTree`, `addMessage`, and the framework host's
226
+ * own list setter) and they disagreed. One stamped and invented a start, one wrote
227
+ * straight to the repository, one did nothing, and the host's `appendMessage` — same
228
+ * name as the viewport's, opposite behaviour — did nothing either. The same stored
229
+ * conversation therefore produced different numbers depending on the mode and on
230
+ * whether a branch tree had been saved.
231
+ *
232
+ * Always returns a NEW object, even for a message with no segments. That looks like a
233
+ * missed optimisation and is the invariant of this whole file: the viewport hands the
234
+ * same object to the repository AND to the framework's list, so sharing one makes the
235
+ * immediate paint and the coalesced write land on the same string twice. Returning the
236
+ * caller's message here doubled every streamed reply — caught by the suite that exists
237
+ * for exactly that bug, within minutes of my writing the shortcut.
238
+ */
239
+ export declare function adoptMessageSegments<T extends {
240
+ id: string;
241
+ segments?: AparteSegment[];
242
+ }>(message: T): T;
165
243
  /**
166
244
  * Close the gap a removal left, in place.
167
245
  *
@@ -1 +1 @@
1
- {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/utils/segments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA6BvD;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAClB,aAAa,CAOf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAGhE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAChC,OAAO,CAAC,aAAa,CAAC,CAaxB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAI1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAEjF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAMnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,EAAE,CAE3E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAMhE"}
1
+ {"version":3,"file":"segments.d.ts","sourceRoot":"","sources":["../../src/utils/segments.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,qBAAqB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AA6BnG;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAChC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,qBAAqB,GACjC,aAAa,CAWf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,YAAY,CACxB,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,OAAO,EAAE,aAAa,EACtB,SAAS,EAAE,MAAM,GAClB,aAAa,CAUf;AASD;;;;;;GAMG;AACH,wBAAgB,aAAa,CACzB,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,CAAC,GACrC,mBAAmB,GAAG,SAAS,CAEjC;AA6CD;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAGhE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAChC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAChC,OAAO,CAAC,aAAa,CAAC,CAgBxB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,GAChC,aAAa,CAef;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,CAI1E;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAEnF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAMnF;AAED;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAE3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,GAAG,MAAM,EAAE,CAE3E;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,aAAa,EAAE,CAAA;CAAE,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CASxG;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAMhE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aparte/core",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "High-performance AI conversation engine - Zero-dependency Web Components",
5
5
  "type": "module",
6
6
  "//sideEffects": "The BROWSER entry defines the custom elements and imports CSS at module scope, so it must never be tree-shaken; the Node entry (`index.node`) and every other module are pure. Listing them explicitly is what lets a bundler drop the rest — the whole package was implicitly side-effectful before, the only one of the 14 without this field.",
@@ -68,6 +68,7 @@
68
68
  "preview": "vite preview",
69
69
  "test": "vitest",
70
70
  "test:run": "vitest run",
71
- "test:coverage": "vitest run --coverage"
71
+ "test:coverage": "vitest run --coverage",
72
+ "gen": "pnpm run analyze && node ../../scripts/gen-element-bindings.mjs packages/core --registry packages/core/src/generated"
72
73
  }
73
74
  }