@aparte/core 0.4.0-alpha.0 → 0.6.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 (35) hide show
  1. package/README.md +5 -2
  2. package/dist/client/aparte-client.d.ts +7 -1
  3. package/dist/client/aparte-client.d.ts.map +1 -1
  4. package/dist/components/bubble/aparte-chat-bubble.d.ts +15 -2
  5. package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -1
  6. package/dist/components/composer/aparte-composer-attachments.d.ts +3 -2
  7. package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -1
  8. package/dist/components/viewport/aparte-chat-viewport.d.ts +4 -2
  9. package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -1
  10. package/dist/config/aparte-config.d.ts +54 -5
  11. package/dist/config/aparte-config.d.ts.map +1 -1
  12. package/dist/config/index.d.ts +1 -1
  13. package/dist/config/index.d.ts.map +1 -1
  14. package/dist/custom-elements.json +4501 -4310
  15. package/dist/host/aparte-chat-host.d.ts +11 -0
  16. package/dist/host/aparte-chat-host.d.ts.map +1 -1
  17. package/dist/{index-BBg6dsYx.js → index-Dn7TH14G.js} +137 -59
  18. package/dist/index-Dn7TH14G.js.map +1 -0
  19. package/dist/index.css +15 -2
  20. package/dist/index.d.ts +1 -1
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +106 -48
  23. package/dist/index.js.map +1 -1
  24. package/dist/index.node.d.ts +1 -1
  25. package/dist/index.node.d.ts.map +1 -1
  26. package/dist/index.node.js +34 -32
  27. package/dist/index.node.js.map +1 -1
  28. package/dist/renderers/index.d.ts +1 -1
  29. package/dist/renderers/index.d.ts.map +1 -1
  30. package/dist/renderers/segment-renderers.d.ts +23 -0
  31. package/dist/renderers/segment-renderers.d.ts.map +1 -1
  32. package/dist/types/models.d.ts +56 -9
  33. package/dist/types/models.d.ts.map +1 -1
  34. package/package.json +1 -1
  35. package/dist/index-BBg6dsYx.js.map +0 -1
@@ -79,6 +79,17 @@ export declare class AparteChatHost {
79
79
  /** Abort handle for an in-flight {@link streamTokens} loop. */
80
80
  private _streamAbort?;
81
81
  /** Segment chunks written to the bubble, awaiting one coalesced state sync. */
82
+ /**
83
+ * Buffered segment text, per segment id, as `base + text` — an **absolute**
84
+ * target, never a delta.
85
+ *
86
+ * Why absolute: the immediate paint (`appendToSegment` below) writes through the
87
+ * viewport into the very segment object the framework list holds — they are the
88
+ * same object, handed to both by `addSegment`. A delta added at flush time would
89
+ * therefore land on content that already contains it, and every chunk came out
90
+ * doubled. `base` is captured before the paint, so whoever mutates the shared
91
+ * object in between cannot change the result.
92
+ */
82
93
  private readonly _segmentBuffer;
83
94
  /** {@link streamTokens} text written to the bubble, awaiting the same sync. */
84
95
  private _tokenBuffer;
@@ -1 +1 @@
1
- {"version":3,"file":"aparte-chat-host.d.ts","sourceRoot":"","sources":["../../src/host/aparte-chat-host.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"aparte-chat-host.d.ts","sourceRoot":"","sources":["../../src/host/aparte-chat-host.ts"],"names":[],"mappings":"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"}
@@ -939,6 +939,18 @@ const defaultSanitizer = (html) => {
939
939
  sanitizeChildren(doc.body, container, doc);
940
940
  return container.innerHTML;
941
941
  };
942
+ const DEFAULT_BUBBLE_ACTIONS = {
943
+ copy: true,
944
+ retry: false,
945
+ edit: false,
946
+ feedback: false,
947
+ info: false
948
+ };
949
+ const DEFAULT_HOST_HANDLERS = {
950
+ attachmentPreview: false,
951
+ terminalRun: false,
952
+ artifactRedownload: false
953
+ };
942
954
  class AparteConfigClass {
943
955
  _markdownProvider;
944
956
  _streamingMarkdownProvider;
@@ -978,8 +990,11 @@ class AparteConfigClass {
978
990
  // Tool Registry
979
991
  _tools = /* @__PURE__ */ new Map();
980
992
  _toolRenderers = /* @__PURE__ */ new Map();
981
- // Bubble Actions
982
- _bubbleActionsConfig = { copy: true, retry: true, edit: true, feedback: false };
993
+ // Host handlers — what the app declares it can actually complete.
994
+ _hostHandlers = { ...DEFAULT_HOST_HANDLERS };
995
+ // Bubble Actions — DEFAULT_BUBBLE_ACTIONS is the single source of truth
996
+ // (init here, restored by reset(), and the fallback in getBubbleActions()).
997
+ _bubbleActionsConfig = { ...DEFAULT_BUBBLE_ACTIONS };
983
998
  // ─────────────────────────────────────────────────────────────────────────
984
999
  // Provider Setters (Dependency Injection)
985
1000
  // ─────────────────────────────────────────────────────────────────────────
@@ -1021,12 +1036,13 @@ class AparteConfigClass {
1021
1036
  }
1022
1037
  /**
1023
1038
  * Configure which action buttons appear in message bubbles.
1024
- * Unset keys keep their defaults (copy=true, retry=true, edit=true, feedback=false).
1039
+ * Unset keys keep their defaults see {@link DEFAULT_BUBBLE_ACTIONS}: `copy`
1040
+ * only, because every other button needs a host to honor it.
1025
1041
  *
1026
1042
  * @example
1027
- * AparteConfig.setBubbleActions({ feedback: true }) // enable feedback, keep rest
1028
- * AparteConfig.setBubbleActions({ retry: false }) // disable retry only
1029
- * AparteConfig.setBubbleActions({ copy: false, retry: false, edit: false }) // hide all
1043
+ * AparteConfig.setBubbleActions({ retry: true, edit: true }) // you run AparteClient
1044
+ * AparteConfig.setBubbleActions({ feedback: true }) // you listen for aparte-feedback
1045
+ * AparteConfig.setBubbleActions({ copy: false }) // hide everything
1030
1046
  * // Explicit per-role ordered sets (replace the flag defaults for that role):
1031
1047
  * AparteConfig.setBubbleActions({ user: ['edit', 'copy'], assistant: ['copy', 'thumbUp', 'thumbDown', 'retry'] })
1032
1048
  */
@@ -1034,13 +1050,33 @@ class AparteConfigClass {
1034
1050
  this._bubbleActionsConfig = { ...this._bubbleActionsConfig, ...config };
1035
1051
  this._notify();
1036
1052
  }
1053
+ /**
1054
+ * Declare which host-dependent affordances your app handles. Core renders the
1055
+ * trigger only for the ones you claim — see {@link AparteHostHandlersConfig}.
1056
+ *
1057
+ * @example
1058
+ * AparteConfig.setHostHandlers({ attachmentPreview: true, terminalRun: true });
1059
+ */
1060
+ setHostHandlers(config) {
1061
+ this._hostHandlers = { ...this._hostHandlers, ...config };
1062
+ this._notify();
1063
+ }
1064
+ /** Returns the resolved host-handler declarations (undeclared = false). */
1065
+ getHostHandlers() {
1066
+ return {
1067
+ attachmentPreview: this._hostHandlers.attachmentPreview ?? DEFAULT_HOST_HANDLERS.attachmentPreview,
1068
+ terminalRun: this._hostHandlers.terminalRun ?? DEFAULT_HOST_HANDLERS.terminalRun,
1069
+ artifactRedownload: this._hostHandlers.artifactRedownload ?? DEFAULT_HOST_HANDLERS.artifactRedownload
1070
+ };
1071
+ }
1037
1072
  /** Returns the resolved bubble actions config (flag defaults applied; per-role sets passed through). */
1038
1073
  getBubbleActions() {
1039
1074
  return {
1040
- copy: this._bubbleActionsConfig.copy ?? true,
1041
- retry: this._bubbleActionsConfig.retry ?? true,
1042
- edit: this._bubbleActionsConfig.edit ?? true,
1043
- feedback: this._bubbleActionsConfig.feedback ?? false,
1075
+ copy: this._bubbleActionsConfig.copy ?? DEFAULT_BUBBLE_ACTIONS.copy,
1076
+ retry: this._bubbleActionsConfig.retry ?? DEFAULT_BUBBLE_ACTIONS.retry,
1077
+ edit: this._bubbleActionsConfig.edit ?? DEFAULT_BUBBLE_ACTIONS.edit,
1078
+ feedback: this._bubbleActionsConfig.feedback ?? DEFAULT_BUBBLE_ACTIONS.feedback,
1079
+ info: this._bubbleActionsConfig.info ?? DEFAULT_BUBBLE_ACTIONS.info,
1044
1080
  user: this._bubbleActionsConfig.user,
1045
1081
  assistant: this._bubbleActionsConfig.assistant
1046
1082
  };
@@ -1681,7 +1717,8 @@ class AparteConfigClass {
1681
1717
  this._modelConfig = {};
1682
1718
  this._requireModelSelection = false;
1683
1719
  this._modelPreferenceProvider = void 0;
1684
- this._bubbleActionsConfig = { copy: true, retry: true, edit: true, feedback: false };
1720
+ this._bubbleActionsConfig = { ...DEFAULT_BUBBLE_ACTIONS };
1721
+ this._hostHandlers = { ...DEFAULT_HOST_HANDLERS };
1685
1722
  this._notify();
1686
1723
  }
1687
1724
  // ─────────────────────────────────────────────────────────────────────────
@@ -1818,10 +1855,23 @@ function findClosingFence(s) {
1818
1855
  }
1819
1856
  const renderers = /* @__PURE__ */ new Map();
1820
1857
  let styleElement = null;
1858
+ let defaultsInstalled = false;
1859
+ let defaultsDeclined = false;
1821
1860
  function registerSegmentRenderer(renderer) {
1822
1861
  renderers.set(renderer.type, renderer);
1823
1862
  injectRendererStyles();
1824
1863
  }
1864
+ function declineDefaultRenderers() {
1865
+ defaultsDeclined = true;
1866
+ }
1867
+ function installDefaultRenderersOnce() {
1868
+ if (defaultsInstalled || defaultsDeclined) return;
1869
+ defaultsInstalled = true;
1870
+ for (const renderer of DEFAULT_RENDERERS) {
1871
+ if (!renderers.has(renderer.type)) renderers.set(renderer.type, renderer);
1872
+ }
1873
+ injectRendererStyles();
1874
+ }
1825
1875
  function unregisterSegmentRenderer(type) {
1826
1876
  renderers.delete(type);
1827
1877
  }
@@ -1953,7 +2003,7 @@ const terminalRenderer = {
1953
2003
  </div>
1954
2004
  <code class="terminal-command">${escapeHtml(segment.command || "")}</code>
1955
2005
  <div class="terminal-actions">
1956
- ${segment.isRunning ? `<span class="terminal-running"><span class="spinner"></span>${contextConfig().t("running")}</span>` : `<button class="terminal-run-btn" data-action="run" aria-label="${contextConfig().t("run")}" title="${contextConfig().t("run")}">${contextConfig().t("run")}</button>`}
2006
+ ${segment.isRunning ? `<span class="terminal-running"><span class="spinner"></span>${contextConfig().t("running")}</span>` : contextConfig().getHostHandlers().terminalRun ? `<button class="terminal-run-btn" data-action="run" aria-label="${contextConfig().t("run")}" title="${contextConfig().t("run")}">${contextConfig().t("run")}</button>` : ""}
1957
2007
  <button class="terminal-copy-btn" data-action="copy" aria-label="${contextConfig().t("copy")}" title="${contextConfig().t("copy")}">
1958
2008
  ${contextConfig().getIcon("copy")}
1959
2009
  </button>
@@ -2211,16 +2261,8 @@ const pipelineWaitingRenderer = {
2211
2261
  `
2212
2262
  };
2213
2263
  function registerDefaultRenderers() {
2214
- registerSegmentRenderer(textRenderer);
2215
- registerSegmentRenderer(thinkingRenderer);
2216
- registerSegmentRenderer(codeRenderer);
2217
- registerSegmentRenderer(terminalRenderer);
2218
- registerSegmentRenderer(errorRenderer);
2219
- registerSegmentRenderer(progressRenderer);
2220
- registerSegmentRenderer(fileTreeRenderer);
2221
- registerSegmentRenderer(toolCallRenderer);
2222
- registerSegmentRenderer(artifactRenderer);
2223
- registerSegmentRenderer(pipelineWaitingRenderer);
2264
+ defaultsInstalled = true;
2265
+ for (const renderer of DEFAULT_RENDERERS) registerSegmentRenderer(renderer);
2224
2266
  }
2225
2267
  const PREVIEWABLE_KINDS = /* @__PURE__ */ new Set(["react", "html", "svg", "js", "css"]);
2226
2268
  const BINARY_FILE_KINDS = /* @__PURE__ */ new Set(["pdf", "xlsx", "docx"]);
@@ -2705,6 +2747,7 @@ function renderBinaryFileArtifact(segment, kind) {
2705
2747
  const title = segment.title?.trim() || labelForKind(kind);
2706
2748
  const iconLabel = FILE_ICON_LABEL[kind] ?? kind.toUpperCase();
2707
2749
  const isStreaming = !!segment.isStreaming;
2750
+ const canRedownload = contextConfig().getHostHandlers().artifactRedownload;
2708
2751
  const cached = _binaryArtifactCache.get(segment.id);
2709
2752
  if (cached && !isStreaming) {
2710
2753
  const previewBody = cached.previewHtml ? contextConfig().sanitizeHtml(cached.previewHtml) : `<div class="aparte-art-file__preview-empty">Preview not available for ${escapeHtml(kind)} yet</div>`;
@@ -2720,7 +2763,7 @@ function renderBinaryFileArtifact(segment, kind) {
2720
2763
  <div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(formatBytes(cached.bytes))} · ${escapeHtml(kind.toUpperCase())}</div>
2721
2764
  </div>
2722
2765
  <div class="aparte-art-file__actions">
2723
- <button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download">Download</button>
2766
+ ${canRedownload ? '<button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download">Download</button>' : ""}
2724
2767
  </div>
2725
2768
  </div>
2726
2769
  <div class="aparte-art-file__body">
@@ -2746,7 +2789,7 @@ function renderBinaryFileArtifact(segment, kind) {
2746
2789
  <div class="aparte-art-file__meta-sub" data-role="file-sub">${escapeHtml(subText)}</div>
2747
2790
  </div>
2748
2791
  <div class="aparte-art-file__actions">
2749
- <button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download" disabled>Download</button>
2792
+ ${canRedownload ? '<button type="button" class="aparte-art-file__btn aparte-art-file__btn--primary" data-action="download" disabled>Download</button>' : ""}
2750
2793
  </div>
2751
2794
  </div>
2752
2795
  <div class="aparte-art-file__body">
@@ -3078,6 +3121,18 @@ function escapeClosingScriptTag(body) {
3078
3121
  }
3079
3122
  return out;
3080
3123
  }
3124
+ const DEFAULT_RENDERERS = [
3125
+ textRenderer,
3126
+ thinkingRenderer,
3127
+ codeRenderer,
3128
+ terminalRenderer,
3129
+ errorRenderer,
3130
+ progressRenderer,
3131
+ fileTreeRenderer,
3132
+ toolCallRenderer,
3133
+ artifactRenderer,
3134
+ pipelineWaitingRenderer
3135
+ ];
3081
3136
  function populateBubbleFromMessage(bubble, message, siblingInfo) {
3082
3137
  if (message.segments && message.segments.length > 0) {
3083
3138
  const existing = bubble.getSegments?.() ?? [];
@@ -3637,6 +3692,17 @@ class AparteChatHost {
3637
3692
  /** Abort handle for an in-flight {@link streamTokens} loop. */
3638
3693
  _streamAbort;
3639
3694
  /** Segment chunks written to the bubble, awaiting one coalesced state sync. */
3695
+ /**
3696
+ * Buffered segment text, per segment id, as `base + text` — an **absolute**
3697
+ * target, never a delta.
3698
+ *
3699
+ * Why absolute: the immediate paint (`appendToSegment` below) writes through the
3700
+ * viewport into the very segment object the framework list holds — they are the
3701
+ * same object, handed to both by `addSegment`. A delta added at flush time would
3702
+ * therefore land on content that already contains it, and every chunk came out
3703
+ * doubled. `base` is captured before the paint, so whoever mutates the shared
3704
+ * object in between cannot change the result.
3705
+ */
3640
3706
  _segmentBuffer = /* @__PURE__ */ new Map();
3641
3707
  /** {@link streamTokens} text written to the bubble, awaiting the same sync. */
3642
3708
  _tokenBuffer = null;
@@ -3874,8 +3940,15 @@ class AparteChatHost {
3874
3940
  const last = msgs[msgs.length - 1];
3875
3941
  if (!last || !last.segments) return;
3876
3942
  if (this._isOrphan(last.id)) return;
3943
+ let buffered = this._segmentBuffer.get(segmentId);
3944
+ if (!buffered) {
3945
+ const segment = last.segments.find((s) => s.id === segmentId);
3946
+ const base = segment && "content" in segment ? segment.content ?? "" : "";
3947
+ buffered = { base, text: "" };
3948
+ this._segmentBuffer.set(segmentId, buffered);
3949
+ }
3950
+ buffered.text += content;
3877
3951
  this._vp()?.appendToSegment?.(last.id, segmentId, content);
3878
- this._segmentBuffer.set(segmentId, (this._segmentBuffer.get(segmentId) ?? "") + content);
3879
3952
  this._scheduleStreamFlush();
3880
3953
  }
3881
3954
  /** Schedule the coalesced segment-state sync (idempotent within a frame). */
@@ -3920,8 +3993,8 @@ class AparteChatHost {
3920
3993
  const last = msgs[msgs.length - 1];
3921
3994
  if (last?.segments) {
3922
3995
  const segments = last.segments.map((s) => {
3923
- const chunk = pending.get(s.id);
3924
- return chunk !== void 0 && "content" in s ? { ...s, content: s.content + chunk } : s;
3996
+ const buffered = pending.get(s.id);
3997
+ return buffered !== void 0 && "content" in s ? { ...s, content: buffered.base + buffered.text } : s;
3925
3998
  });
3926
3999
  msgs = [...msgs.slice(0, -1), { ...last, segments }];
3927
4000
  changed = true;
@@ -4523,6 +4596,8 @@ class AparteClient {
4523
4596
  this._config = options.config ?? AparteConfig;
4524
4597
  if (this.options.autoRegister) {
4525
4598
  registerDefaultRenderers();
4599
+ } else {
4600
+ declineDefaultRenderers();
4526
4601
  }
4527
4602
  this._setupListeners();
4528
4603
  }
@@ -6399,21 +6474,24 @@ export {
6399
6474
  APARTE_CONVERSATION_SCHEMA_VERSION as A,
6400
6475
  BackendTransport as B,
6401
6476
  ConversationManager as C,
6402
- DEFAULT_ICON_FALLBACKS as D,
6403
- isAwaitingReply as E,
6404
- isFormatAdapter as F,
6405
- isSafeUrl as G,
6406
- parseAparteEventStream as H,
6407
- parseMarkdownToSegments as I,
6408
- populateBubbleFromMessage as J,
6409
- readableToAsyncIterable as K,
6410
- registerDefaultRenderers as L,
6477
+ DEFAULT_BUBBLE_ACTIONS as D,
6478
+ filesToAttachments as E,
6479
+ getSegmentRenderer as F,
6480
+ isAwaitingReply as G,
6481
+ isFormatAdapter as H,
6482
+ isSafeUrl as I,
6483
+ parseAparteEventStream as J,
6484
+ parseMarkdownToSegments as K,
6485
+ populateBubbleFromMessage as L,
6411
6486
  MessageRepository as M,
6412
- registerSegmentRenderer as N,
6413
- requestUserInput as O,
6414
- resolveConfig as P,
6415
- runWithConfig as Q,
6416
- unregisterSegmentRenderer as R,
6487
+ readableToAsyncIterable as N,
6488
+ registerDefaultRenderers as O,
6489
+ registerSegmentRenderer as P,
6490
+ requestUserInput as Q,
6491
+ resolveConfig as R,
6492
+ runWithConfig as S,
6493
+ unregisterSegmentRenderer as T,
6494
+ installDefaultRenderersOnce as U,
6417
6495
  APARTE_HOST_ATTR as a,
6418
6496
  AparteChatHost as b,
6419
6497
  AparteClient as c,
@@ -6423,22 +6501,22 @@ export {
6423
6501
  AparteError as g,
6424
6502
  AparteErrorCode as h,
6425
6503
  AparteStreamParser as i,
6426
- DEFAULT_LOCALE as j,
6427
- DEFAULT_SKELETON_FALLBACKS as k,
6428
- DEFAULT_UI_EVENTS as l,
6429
- DirectTransport as m,
6430
- applyElementProps as n,
6431
- attachConfig as o,
6432
- buildElicitationPanel as p,
6433
- collectRendererStyles as q,
6434
- contentToText as r,
6435
- contextConfig as s,
6436
- createAparteChatHandler as t,
6437
- createStreamAdapter as u,
6438
- defaultSanitizer as v,
6439
- deriveArtifactKind as w,
6440
- detachConfig as x,
6441
- filesToAttachments as y,
6442
- getSegmentRenderer as z
6504
+ DEFAULT_HOST_HANDLERS as j,
6505
+ DEFAULT_ICON_FALLBACKS as k,
6506
+ DEFAULT_LOCALE as l,
6507
+ DEFAULT_SKELETON_FALLBACKS as m,
6508
+ DEFAULT_UI_EVENTS as n,
6509
+ DirectTransport as o,
6510
+ applyElementProps as p,
6511
+ attachConfig as q,
6512
+ buildElicitationPanel as r,
6513
+ collectRendererStyles as s,
6514
+ contentToText as t,
6515
+ contextConfig as u,
6516
+ createAparteChatHandler as v,
6517
+ createStreamAdapter as w,
6518
+ defaultSanitizer as x,
6519
+ deriveArtifactKind as y,
6520
+ detachConfig as z
6443
6521
  };
6444
- //# sourceMappingURL=index-BBg6dsYx.js.map
6522
+ //# sourceMappingURL=index-Dn7TH14G.js.map