@jini-ai/chat 0.3.10 → 0.5.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 (206) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +152 -6
  3. package/dist/core/ag-ui/entry.d.ts +53 -0
  4. package/dist/core/ag-ui/entry.js +135 -0
  5. package/dist/core/agentic/chat-capabilities.d.ts +1 -1
  6. package/dist/core/agentic/index.d.ts +1 -1
  7. package/dist/core/agentic/index.js +1 -1
  8. package/dist/core/assistant-content.d.ts +6 -2
  9. package/dist/core/assistant-content.js +2 -2
  10. package/dist/core/compact-events.d.ts +3 -1
  11. package/dist/core/compact-events.js +1 -1
  12. package/dist/core/events.d.ts +1 -1
  13. package/dist/core/events.js +1 -1
  14. package/dist/core/index.d.ts +3 -3
  15. package/dist/core/index.js +3 -3
  16. package/dist/core/messages.d.ts +4 -2
  17. package/dist/core/messages.js +2 -2
  18. package/dist/core/partial-json.d.ts +6 -2
  19. package/dist/core/partial-json.js +3 -3
  20. package/dist/core/persistence/index.d.ts +1 -1
  21. package/dist/core/persistence/index.js +1 -1
  22. package/dist/core/persistence/ports.d.ts +2 -123
  23. package/dist/core/persistence/title.d.ts +3 -1
  24. package/dist/core/persistence/title.js +1 -1
  25. package/dist/core/question-form/format.d.ts +16 -7
  26. package/dist/core/question-form/format.js +3 -3
  27. package/dist/core/question-form/normalize.d.ts +7 -2
  28. package/dist/core/question-form/normalize.js +5 -5
  29. package/dist/core/question-form/scan.d.ts +18 -6
  30. package/dist/core/question-form/scan.js +14 -14
  31. package/dist/core/run-activity.d.ts +16 -4
  32. package/dist/core/run-activity.js +11 -11
  33. package/dist/core/run-events/entry.d.ts +121 -0
  34. package/dist/core/run-events/entry.js +290 -0
  35. package/dist/core/todos.d.ts +20 -8
  36. package/dist/core/todos.js +11 -11
  37. package/dist/core/tool-events.d.ts +3 -1
  38. package/dist/core/tool-events.js +1 -1
  39. package/dist/core/tool-output.d.ts +3 -1
  40. package/dist/core/tool-output.js +1 -1
  41. package/dist/core/tools.d.ts +14 -3
  42. package/dist/core/tools.js +3 -3
  43. package/dist/core/transcript.d.ts +13 -5
  44. package/dist/core/transcript.js +5 -5
  45. package/dist/core/util/manifest.d.ts +9 -3
  46. package/dist/core/util/manifest.js +3 -3
  47. package/dist/core/util/markdown-context.d.ts +11 -3
  48. package/dist/core/util/markdown-context.js +3 -3
  49. package/dist/core/util/markup-attributes.d.ts +3 -1
  50. package/dist/core/util/markup-attributes.js +1 -1
  51. package/dist/core/util/parser.d.ts +9 -5
  52. package/dist/core/util/parser.js +13 -13
  53. package/dist/core/util/recover.d.ts +6 -2
  54. package/dist/core/util/recover.js +6 -6
  55. package/dist/core/util/strip.d.ts +19 -5
  56. package/dist/core/util/strip.js +17 -17
  57. package/dist/core/util/validate.d.ts +3 -1
  58. package/dist/core/util/validate.js +1 -1
  59. package/dist/embed-widget/browser/page-actions.d.ts +121 -0
  60. package/dist/embed-widget/browser/page-actions.js +113 -0
  61. package/dist/embed-widget/browser/session-store.d.ts +44 -0
  62. package/dist/embed-widget/browser/session-store.js +103 -0
  63. package/dist/embed-widget/react/embed.d.ts +45 -0
  64. package/dist/embed-widget/react/embed.js +87 -0
  65. package/dist/embed-widget/react/header.d.ts +21 -0
  66. package/dist/embed-widget/react/header.js +18 -0
  67. package/dist/embed-widget/transports/fetch-sse.d.ts +75 -0
  68. package/dist/embed-widget/transports/fetch-sse.js +175 -0
  69. package/dist/react/agent-bridge/frontend-session-bridge.d.ts +15 -3
  70. package/dist/react/agent-bridge/frontend-session-bridge.js +13 -6
  71. package/dist/react/artifact-types.d.ts +3 -3
  72. package/dist/react/artifact-types.js +3 -3
  73. package/dist/react/components/A2uiSurfaceCard.js +34 -13
  74. package/dist/react/components/AttachmentPreviewModal.hooks.d.ts +7 -2
  75. package/dist/react/components/AttachmentPreviewModal.hooks.js +5 -5
  76. package/dist/react/components/AttachmentPreviewModal.js +2 -2
  77. package/dist/react/components/AttachmentTray.d.ts +3 -1
  78. package/dist/react/components/AttachmentTray.js +2 -2
  79. package/dist/react/components/ChatFab.js +1 -1
  80. package/dist/react/components/Composer.js +9 -9
  81. package/dist/react/components/ConversationList.js +1 -1
  82. package/dist/react/components/McpUiSurfaceCard.d.ts +4 -2
  83. package/dist/react/components/McpUiSurfaceCard.js +5 -5
  84. package/dist/react/components/MessageList.js +1 -1
  85. package/dist/react/components/MessageRow.js +9 -9
  86. package/dist/react/components/QuestionForm.js +5 -5
  87. package/dist/react/components/ToolCard.js +9 -9
  88. package/dist/react/components/composer-discovery.d.ts +29 -8
  89. package/dist/react/components/composer-discovery.js +10 -10
  90. package/dist/react/ext-event-renderer-registry.d.ts +15 -5
  91. package/dist/react/ext-event-renderer-registry.js +4 -4
  92. package/dist/react/features/chat-pane/components/AgentRuntimePicker.d.ts +3 -1
  93. package/dist/react/features/chat-pane/components/AgentRuntimePicker.js +3 -3
  94. package/dist/react/features/chat-pane/components/ChatPane.js +43 -43
  95. package/dist/react/features/chat-pane/create-daemon-attachment-uploader.d.ts +4 -1
  96. package/dist/react/features/chat-pane/create-daemon-attachment-uploader.js +5 -35
  97. package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.d.ts +5 -2
  98. package/dist/react/features/chat-pane/create-mcp-ui-tool-caller.js +1 -1
  99. package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.d.ts +38 -10
  100. package/dist/react/features/chat-pane/hooks/useAgentRuntimePicker.hooks.js +15 -15
  101. package/dist/react/features/chat-pane/hooks/useChatPane.hooks.js +31 -31
  102. package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.d.ts +3 -1
  103. package/dist/react/features/chat-pane/hooks/useChatPaneAgentControl.hooks.js +3 -3
  104. package/dist/react/features/chat-pane/hooks/useChatPaneComposerPlaceholder.hooks.d.ts +4 -1
  105. package/dist/react/features/chat-pane/hooks/useChatPaneComposerPlaceholder.hooks.js +1 -1
  106. package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.d.ts +3 -0
  107. package/dist/react/features/chat-pane/hooks/useChatPaneRuntimeInventory.hooks.js +80 -38
  108. package/dist/react/features/chat-pane/hooks/useChatPaneWorkingDirectory.hooks.js +57 -57
  109. package/dist/react/features/chat-pane/rules.d.ts +13 -4
  110. package/dist/react/features/chat-pane/rules.js +5 -5
  111. package/dist/react/features/chat-pane/types.d.ts +1 -1
  112. package/dist/react/hooks/attachment-preview-cache.d.ts +7 -2
  113. package/dist/react/hooks/attachment-preview-cache.js +2 -2
  114. package/dist/react/hooks/composer-draft-cache.d.ts +17 -5
  115. package/dist/react/hooks/composer-draft-cache.js +6 -6
  116. package/dist/react/hooks/useArtifactStream.d.ts +5 -1
  117. package/dist/react/hooks/useArtifactStream.js +3 -3
  118. package/dist/react/hooks/useChatFabDrag.d.ts +9 -4
  119. package/dist/react/hooks/useChatFabDrag.js +4 -4
  120. package/dist/react/hooks/useComposer.js +8 -8
  121. package/dist/react/hooks/useConversation.js +56 -4
  122. package/dist/react/hooks/useExtEventGroups.d.ts +5 -1
  123. package/dist/react/hooks/useExtEventGroups.js +1 -1
  124. package/dist/react/hooks/useLatestOperation.d.ts +8 -3
  125. package/dist/react/hooks/useLatestOperation.js +4 -4
  126. package/dist/react/hooks/usePinnedTodos.d.ts +3 -1
  127. package/dist/react/hooks/usePinnedTodos.js +3 -3
  128. package/dist/react/hooks/useQuestionForms.d.ts +7 -2
  129. package/dist/react/hooks/useQuestionForms.js +7 -7
  130. package/dist/react/hooks/useRunActivity.d.ts +6 -1
  131. package/dist/react/hooks/useRunActivity.js +3 -3
  132. package/dist/react/hooks/useRunStream.d.ts +3 -1
  133. package/dist/react/hooks/useRunStream.js +1 -1
  134. package/dist/react/hooks/useToolTimeline.d.ts +3 -1
  135. package/dist/react/hooks/useToolTimeline.js +3 -3
  136. package/dist/react/index.d.ts +4 -4
  137. package/dist/react/index.js +6 -6
  138. package/dist/react/message-blocks.d.ts +10 -4
  139. package/dist/react/message-blocks.js +2 -2
  140. package/dist/react/styles/reference.css +3 -3
  141. package/dist/react/tool-renderer-registry.d.ts +8 -3
  142. package/dist/react/tool-renderer-registry.js +3 -3
  143. package/dist/react/util/defined-props.d.ts +3 -1
  144. package/dist/react/util/defined-props.js +1 -1
  145. package/dist/server/run-finalizer/entry.d.ts +47 -0
  146. package/dist/server/run-finalizer/entry.js +156 -0
  147. package/dist/server/run-finalizer/ports.d.ts +52 -0
  148. package/dist/store/contracts/index.d.ts +5 -0
  149. package/dist/store/contracts/index.js +5 -0
  150. package/dist/store/errors.d.ts +12 -0
  151. package/dist/store/errors.js +18 -0
  152. package/dist/store/index.d.ts +4 -0
  153. package/dist/store/index.js +2 -0
  154. package/dist/store/legacy/index.d.ts +3 -0
  155. package/dist/store/legacy/index.js +2 -0
  156. package/dist/store/legacy/sqlite/conversations.d.ts +129 -0
  157. package/dist/store/legacy/sqlite/conversations.js +274 -0
  158. package/dist/store/legacy/sqlite/index.d.ts +6 -0
  159. package/dist/store/legacy/sqlite/index.js +5 -0
  160. package/dist/store/legacy/sqlite/messages.d.ts +156 -0
  161. package/dist/store/legacy/sqlite/messages.js +246 -0
  162. package/dist/store/legacy/sqlite/schema.d.ts +3 -0
  163. package/dist/store/legacy/sqlite/schema.js +40 -0
  164. package/dist/store/pglite/index.d.ts +21 -0
  165. package/dist/store/pglite/index.js +17 -0
  166. package/dist/store/ports.d.ts +121 -0
  167. package/dist/store/ports.js +2 -0
  168. package/dist/store/postgres/index.d.ts +21 -0
  169. package/dist/store/postgres/index.js +17 -0
  170. package/dist/store/sql/boundary.d.ts +28 -0
  171. package/dist/store/sql/boundary.js +32 -0
  172. package/dist/store/sql/cursor.d.ts +24 -0
  173. package/dist/store/sql/cursor.js +49 -0
  174. package/dist/store/sql/maintenance.d.ts +9 -0
  175. package/dist/store/sql/maintenance.js +16 -0
  176. package/dist/store/sql/store.d.ts +22 -0
  177. package/dist/store/sql/store.js +340 -0
  178. package/dist/store/sql/tables.d.ts +34 -0
  179. package/dist/store/sql/tables.js +2 -0
  180. package/dist/store/sqlite/index.d.ts +36 -0
  181. package/dist/store/sqlite/index.js +29 -0
  182. package/dist/store/sqlite/schema.d.ts +49 -0
  183. package/dist/store/sqlite/schema.js +80 -0
  184. package/package.json +211 -14
  185. package/dist/react/features/model-picker/components/CredentialStatusBadge.d.ts +0 -7
  186. package/dist/react/features/model-picker/components/CredentialStatusBadge.js +0 -20
  187. package/dist/react/features/model-picker/components/ModelPicker.d.ts +0 -9
  188. package/dist/react/features/model-picker/components/ModelPicker.js +0 -34
  189. package/dist/react/features/model-picker/constants.d.ts +0 -6
  190. package/dist/react/features/model-picker/constants.js +0 -9
  191. package/dist/react/features/model-picker/dependencies.d.ts +0 -11
  192. package/dist/react/features/model-picker/dependencies.js +0 -10
  193. package/dist/react/features/model-picker/hooks/useModelPicker.hooks.d.ts +0 -27
  194. package/dist/react/features/model-picker/hooks/useModelPicker.hooks.js +0 -62
  195. package/dist/react/features/model-picker/index.d.ts +0 -32
  196. package/dist/react/features/model-picker/index.js +0 -29
  197. package/dist/react/features/model-picker/ports.d.ts +0 -11
  198. package/dist/react/features/model-picker/rules.d.ts +0 -26
  199. package/dist/react/features/model-picker/rules.js +0 -84
  200. package/dist/react/features/model-picker/types.d.ts +0 -38
  201. package/dist/react/features/model-picker/types.js +0 -2
  202. package/dist/react/poc-mcp-ui-official/PocMcpUiCard.d.ts +0 -9
  203. package/dist/react/poc-mcp-ui-official/PocMcpUiCard.js +0 -29
  204. package/dist/react/poc-mcp-ui-official/create-poc-resource.d.ts +0 -30
  205. package/dist/react/poc-mcp-ui-official/create-poc-resource.js +0 -44
  206. /package/dist/{react/features/model-picker → server/run-finalizer}/ports.js +0 -0
@@ -5,18 +5,20 @@
5
5
  * the flattened text a host sends to an agent as prior-turn context.
6
6
  *
7
7
  * Adapted from OD's `providers/daemon.ts` transcript section (see
8
- * source-map.md). The OD original also owned SSE/fetch transport
8
+ * archived provenance ledger). The OD original also owned SSE/fetch transport
9
9
  * (`streamViaDaemon`, `DaemonStreamHandlers`) — none of that is ported here;
10
10
  * only the pure string-assembly helpers. It also hard-coded OD's BYOK/
11
11
  * OpenCode agent-family policy and an `agent-browser`-tool-specific
12
12
  * context-warning heuristic; both are OD product policy, not generic
13
13
  * transcript assembly, so they are generalized into caller-supplied hooks
14
- * (or dropped) below — see source-map.md for the full accounting.
14
+ * (or dropped) below — see archived provenance ledger for the full accounting.
15
15
  */
16
16
  import type { ChatMessage } from './messages.js';
17
17
  import type { PersistedArtifactFileRef } from './util/strip.js';
18
18
  /** The most recent `user`-authored message's content, or `''` if there isn't one. */
19
- export declare function latestUserPromptFromHistory(history: ChatMessage[]): string;
19
+ export declare function latestUserPromptFromHistory({ history }: {
20
+ history: ChatMessage[];
21
+ }): string;
20
22
  /**
21
23
  * Strip transcript-echo hazards from a prior assistant turn before it goes
22
24
  * back to the agent as history: an already-answered `<question-form>` /
@@ -36,7 +38,11 @@ export declare function latestUserPromptFromHistory(history: ChatMessage[]): str
36
38
  * @complexity O(n) in `content.length` (a small fixed number of regex
37
39
  * passes) plus {@link summarizeArtifactsForTranscript}'s cost.
38
40
  */
39
- export declare function sanitizePriorAssistantTurn(content: string, persistedArtifactFiles?: ReadonlyArray<PersistedArtifactFileRef>): string;
41
+ export declare function sanitizePriorAssistantTurn({ content }: {
42
+ content: string;
43
+ }, { persistedArtifactFiles }?: {
44
+ persistedArtifactFiles?: (ReadonlyArray<PersistedArtifactFileRef>) | undefined;
45
+ }): string;
40
46
  export interface BuildTranscriptOptions {
41
47
  /**
42
48
  * Scope the transcript to messages from this agent's family onward,
@@ -77,5 +83,7 @@ export interface BuildTranscriptOptions {
77
83
  * scope, one to sanitize/truncate/join each message, one to scan events
78
84
  * for the warning.
79
85
  */
80
- export declare function buildTranscript(history: ChatMessage[], options?: BuildTranscriptOptions): string;
86
+ export declare function buildTranscript({ history }: {
87
+ history: ChatMessage[];
88
+ }, options?: BuildTranscriptOptions): string;
81
89
  //# sourceMappingURL=transcript.d.ts.map
@@ -3,7 +3,7 @@ const DEFAULT_MAX_TRANSCRIPT_MESSAGE_CHARS = 12_000;
3
3
  const DEFAULT_LARGE_TOOL_RESULT_CHARS = 8_000;
4
4
  const DEFAULT_HIGH_INPUT_TOKEN_WARNING_THRESHOLD = 200_000;
5
5
  /** The most recent `user`-authored message's content, or `''` if there isn't one. */
6
- export function latestUserPromptFromHistory(history) {
6
+ export function latestUserPromptFromHistory({ history }) {
7
7
  for (let i = history.length - 1; i >= 0; i -= 1) {
8
8
  const message = history[i];
9
9
  if (message?.role === 'user')
@@ -82,7 +82,7 @@ function scopeHistoryToAgent(history, targetAgentId, isSameAgentFamily) {
82
82
  * @complexity O(n) in `content.length` (a small fixed number of regex
83
83
  * passes) plus {@link summarizeArtifactsForTranscript}'s cost.
84
84
  */
85
- export function sanitizePriorAssistantTurn(content, persistedArtifactFiles = []) {
85
+ export function sanitizePriorAssistantTurn({ content }, { persistedArtifactFiles = [] } = {}) {
86
86
  let sanitized = content.replace(
87
87
  // `\1` backreference keeps the open/close tag names matched so this never
88
88
  // splices across a `<question-form>…</ask-question>` mismatch.
@@ -99,7 +99,7 @@ export function sanitizePriorAssistantTurn(content, persistedArtifactFiles = [])
99
99
  // Replace prior-turn `<artifact>` HTML with a one-line summary for
100
100
  // artifacts CONFIRMED persisted (see summarizeArtifactsForTranscript's own
101
101
  // doc for why an unconfirmed save is left verbatim).
102
- sanitized = summarizeArtifactsForTranscript(sanitized, persistedArtifactFiles);
102
+ sanitized = summarizeArtifactsForTranscript({ content: sanitized, persistedFiles: persistedArtifactFiles });
103
103
  return sanitized;
104
104
  }
105
105
  /**
@@ -113,7 +113,7 @@ export function sanitizePriorAssistantTurn(content, persistedArtifactFiles = [])
113
113
  * scope, one to sanitize/truncate/join each message, one to scan events
114
114
  * for the warning.
115
115
  */
116
- export function buildTranscript(history, options = {}) {
116
+ export function buildTranscript({ history }, options = {}) {
117
117
  const maxMessageChars = options.maxMessageChars ?? DEFAULT_MAX_TRANSCRIPT_MESSAGE_CHARS;
118
118
  const largeToolResultChars = options.largeToolResultChars ?? DEFAULT_LARGE_TOOL_RESULT_CHARS;
119
119
  const highInputTokenWarningThreshold = options.highInputTokenWarningThreshold ?? DEFAULT_HIGH_INPUT_TOKEN_WARNING_THRESHOLD;
@@ -123,7 +123,7 @@ export function buildTranscript(history, options = {}) {
123
123
  const transcript = scopedHistory
124
124
  .map((m) => {
125
125
  const trimmed = m.content.trim();
126
- const sanitized = m.role === 'assistant' ? sanitizePriorAssistantTurn(trimmed, resolvePersistedArtifactFiles(m)) : trimmed;
126
+ const sanitized = m.role === 'assistant' ? sanitizePriorAssistantTurn({ content: trimmed }, { persistedArtifactFiles: resolvePersistedArtifactFiles(m) }) : trimmed;
127
127
  return `## ${m.role}\n${escapeTranscriptRoleDelimiters(truncateForTranscript(sanitized, maxMessageChars))}`;
128
128
  })
129
129
  .join('\n\n');
@@ -6,7 +6,9 @@
6
6
  */
7
7
  import type { ArtifactManifest } from './types.js';
8
8
  /** The manifest sidecar file name convention for a given artifact entry file name. */
9
- export declare function artifactManifestNameFor(entry: string): string;
9
+ export declare function artifactManifestNameFor({ entry }: {
10
+ entry: string;
11
+ }): string;
10
12
  /** Build a fresh, complete manifest for a newly-persisted HTML artifact. */
11
13
  export declare function createHtmlArtifactManifest(input: {
12
14
  entry: string;
@@ -15,7 +17,9 @@ export declare function createHtmlArtifactManifest(input: {
15
17
  sourceSkillId?: string;
16
18
  designSystemId?: string | null;
17
19
  }): ArtifactManifest;
18
- export declare function serializeArtifactManifest(manifest: ArtifactManifest): string;
20
+ export declare function serializeArtifactManifest({ manifest }: {
21
+ manifest: ArtifactManifest;
22
+ }): string;
19
23
  /**
20
24
  * Parse and validate a manifest JSON string, rejecting anything that isn't a
21
25
  * well-formed, currently-supported manifest (wrong version, missing
@@ -25,7 +29,9 @@ export declare function serializeArtifactManifest(manifest: ArtifactManifest): s
25
29
  * @returns The validated manifest, or `null` on any parse/shape failure.
26
30
  * @complexity O(k) in the manifest's own field/array count — no I/O.
27
31
  */
28
- export declare function parseArtifactManifest(raw: string): ArtifactManifest | null;
32
+ export declare function parseArtifactManifest({ raw }: {
33
+ raw: string;
34
+ }): ArtifactManifest | null;
29
35
  /**
30
36
  * Infer a manifest for a legacy artifact file that predates manifest
31
37
  * sidecars, from its entry file name alone (extension → kind → renderer).
@@ -55,7 +55,7 @@ function exportsForKind(kind) {
55
55
  return ['html', 'pdf', 'zip'];
56
56
  }
57
57
  /** The manifest sidecar file name convention for a given artifact entry file name. */
58
- export function artifactManifestNameFor(entry) {
58
+ export function artifactManifestNameFor({ entry }) {
59
59
  return `${entry}.artifact.json`;
60
60
  }
61
61
  /** Build a fresh, complete manifest for a newly-persisted HTML artifact. */
@@ -77,7 +77,7 @@ export function createHtmlArtifactManifest(input) {
77
77
  metadata: input.metadata,
78
78
  };
79
79
  }
80
- export function serializeArtifactManifest(manifest) {
80
+ export function serializeArtifactManifest({ manifest }) {
81
81
  return JSON.stringify(manifest, null, 2);
82
82
  }
83
83
  /**
@@ -89,7 +89,7 @@ export function serializeArtifactManifest(manifest) {
89
89
  * @returns The validated manifest, or `null` on any parse/shape failure.
90
90
  * @complexity O(k) in the manifest's own field/array count — no I/O.
91
91
  */
92
- export function parseArtifactManifest(raw) {
92
+ export function parseArtifactManifest({ raw }) {
93
93
  try {
94
94
  const parsed = JSON.parse(raw);
95
95
  if (parsed?.version !== MANIFEST_VERSION)
@@ -22,7 +22,10 @@ export declare const INLINE_CODE_RE: RegExp;
22
22
  * continuation (e.g. `<artifactual`) is a prefix-shared literal that must
23
23
  * not be treated as a tag.
24
24
  */
25
- export declare function isRealArtifactOpenAt(content: string, idx: number): boolean;
25
+ export declare function isRealArtifactOpenAt({ content, idx }: {
26
+ content: string;
27
+ idx: number;
28
+ }): boolean;
26
29
  export type Range = readonly [number, number];
27
30
  /**
28
31
  * Compute the half-open `[start, end)` ranges of `buffer` that a Markdown
@@ -38,10 +41,15 @@ export type Range = readonly [number, number];
38
41
  * @complexity O(n) in `buffer.length` — one line-by-line scan plus one
39
42
  * backtick scan per accumulated paragraph block.
40
43
  */
41
- export declare function computeSkipRanges(buffer: string): {
44
+ export declare function computeSkipRanges({ buffer }: {
45
+ buffer: string;
46
+ }): {
42
47
  ranges: Range[];
43
48
  unclosedFenceStart: number | null;
44
49
  };
45
50
  /** `true` when position `p` falls inside one of `ranges` (half-open intervals). */
46
- export declare function rangeContains(ranges: ReadonlyArray<Range>, p: number): boolean;
51
+ export declare function rangeContains({ ranges, p }: {
52
+ ranges: ReadonlyArray<Range>;
53
+ p: number;
54
+ }): boolean;
47
55
  //# sourceMappingURL=markdown-context.d.ts.map
@@ -34,7 +34,7 @@ const OL_ITEM_RE = /^\s*\d+\.\s+/;
34
34
  * continuation (e.g. `<artifactual`) is a prefix-shared literal that must
35
35
  * not be treated as a tag.
36
36
  */
37
- export function isRealArtifactOpenAt(content, idx) {
37
+ export function isRealArtifactOpenAt({ content, idx }) {
38
38
  const next = content.charAt(idx + '<artifact'.length);
39
39
  return next !== '' && /\s/.test(next);
40
40
  }
@@ -52,7 +52,7 @@ export function isRealArtifactOpenAt(content, idx) {
52
52
  * @complexity O(n) in `buffer.length` — one line-by-line scan plus one
53
53
  * backtick scan per accumulated paragraph block.
54
54
  */
55
- export function computeSkipRanges(buffer) {
55
+ export function computeSkipRanges({ buffer }) {
56
56
  const ranges = [];
57
57
  // Paragraph-block regions are contiguous spans of paragraph lines outside
58
58
  // any fenced code block; inline-code scanning is restricted to one block at
@@ -115,7 +115,7 @@ export function computeSkipRanges(buffer) {
115
115
  return { ranges, unclosedFenceStart: inFence ? fenceStart : null };
116
116
  }
117
117
  /** `true` when position `p` falls inside one of `ranges` (half-open intervals). */
118
- export function rangeContains(ranges, p) {
118
+ export function rangeContains({ ranges, p }) {
119
119
  for (const [s, e] of ranges) {
120
120
  if (p >= s && p < e)
121
121
  return true;
@@ -16,5 +16,7 @@
16
16
  * Parse `name="value"` / `name='value'` pairs out of a tag's raw attribute
17
17
  * string (the content between the tag name and the closing `>`).
18
18
  */
19
- export declare function parseQuotedAttrs(raw: string): Record<string, string>;
19
+ export declare function parseQuotedAttrs({ raw }: {
20
+ raw: string;
21
+ }): Record<string, string>;
20
22
  //# sourceMappingURL=markup-attributes.d.ts.map
@@ -16,7 +16,7 @@
16
16
  * Parse `name="value"` / `name='value'` pairs out of a tag's raw attribute
17
17
  * string (the content between the tag name and the closing `>`).
18
18
  */
19
- export function parseQuotedAttrs(raw) {
19
+ export function parseQuotedAttrs({ raw }) {
20
20
  const re = /(\w+)\s*=\s*(?:"([^"]*)"|'([^']*)')/g;
21
21
  const out = {};
22
22
  let m = re.exec(raw);
@@ -16,7 +16,7 @@ export type ArtifactEvent = {
16
16
  fullContent: string;
17
17
  };
18
18
  /**
19
- * Create a fresh streaming artifact parser. Call `feed(delta)` for each
19
+ * Create a fresh streaming artifact parser. Call `feed({ delta })` for each
20
20
  * chunk as it arrives (iterate its generator to drain queued events), and
21
21
  * `flush()` once at end-of-stream to emit whatever is still buffered.
22
22
  *
@@ -25,9 +25,11 @@ export type ArtifactEvent = {
25
25
  * the generator), which is the standard tradeoff for streaming tag
26
26
  * detection over an ever-growing buffer.
27
27
  */
28
- export declare function createArtifactParser(): {
29
- feed: (delta: string) => Generator<ArtifactEvent>;
30
- flush: () => Generator<ArtifactEvent>;
28
+ export declare function createArtifactParser(_requiredArgs: Record<string, never>): {
29
+ feed: (args: {
30
+ delta: string;
31
+ }) => Generator<ArtifactEvent>;
32
+ flush: (args: Record<string, never>) => Generator<ArtifactEvent>;
31
33
  };
32
34
  /**
33
35
  * Convenience wrapper over {@link createArtifactParser} for the common
@@ -38,5 +40,7 @@ export declare function createArtifactParser(): {
38
40
  * @param content - A complete (already fully-arrived) message body.
39
41
  * @complexity O(n) in `content.length` (one `feed` + one `flush` over the whole string).
40
42
  */
41
- export declare function parseArtifacts(content: string): ArtifactEvent[];
43
+ export declare function parseArtifacts({ content }: {
44
+ content: string;
45
+ }): ArtifactEvent[];
42
46
  //# sourceMappingURL=parser.d.ts.map
@@ -24,7 +24,7 @@ const CLOSE_TAG = '</artifact>';
24
24
  // future chunk may turn it into an inline code span.
25
25
  function findOpenTag(buffer) {
26
26
  const len = buffer.length;
27
- const { ranges, unclosedFenceStart } = computeSkipRanges(buffer);
27
+ const { ranges, unclosedFenceStart } = computeSkipRanges({ buffer: buffer });
28
28
  // Pass 1: scan for the earliest *complete* real `<artifact …>` open outside
29
29
  // any skip range, before any hold-back decision — otherwise a stray
30
30
  // backtick or fence-opener prefix on a tail line would suppress an
@@ -35,7 +35,7 @@ function findOpenTag(buffer) {
35
35
  const idx = buffer.indexOf(OPEN_PREFIX, from);
36
36
  if (idx === -1)
37
37
  break;
38
- if (rangeContains(ranges, idx)) {
38
+ if (rangeContains({ ranges: ranges, p: idx })) {
39
39
  from = idx + OPEN_PREFIX.length;
40
40
  continue;
41
41
  }
@@ -53,7 +53,7 @@ function findOpenTag(buffer) {
53
53
  earliestPartialOpen = idx;
54
54
  break;
55
55
  }
56
- if (!isRealArtifactOpenAt(buffer, idx)) {
56
+ if (!isRealArtifactOpenAt({ content: buffer, idx: idx })) {
57
57
  from = after; // e.g. "<artifactual" — not a real open, keep scanning
58
58
  continue;
59
59
  }
@@ -101,7 +101,7 @@ function findOpenTag(buffer) {
101
101
  for (let k = lastNl + 1; k < len; k++) {
102
102
  if (buffer.charAt(k) !== '`')
103
103
  continue;
104
- if (rangeContains(ranges, k))
104
+ if (rangeContains({ ranges: ranges, p: k }))
105
105
  continue;
106
106
  if (parity === 0) {
107
107
  firstUnmatched = k;
@@ -115,7 +115,7 @@ function findOpenTag(buffer) {
115
115
  note(firstUnmatched);
116
116
  // Strict prefix at the tail (e.g. "<art") — hold back.
117
117
  const tailLt = buffer.lastIndexOf('<');
118
- if (tailLt !== -1 && !rangeContains(ranges, tailLt)) {
118
+ if (tailLt !== -1 && !rangeContains({ ranges: ranges, p: tailLt })) {
119
119
  const slice = buffer.slice(tailLt);
120
120
  if (OPEN_PREFIX.startsWith(slice) && slice.length < OPEN_PREFIX.length) {
121
121
  note(tailLt);
@@ -126,7 +126,7 @@ function findOpenTag(buffer) {
126
126
  return { kind: 'none' };
127
127
  }
128
128
  /**
129
- * Create a fresh streaming artifact parser. Call `feed(delta)` for each
129
+ * Create a fresh streaming artifact parser. Call `feed({ delta })` for each
130
130
  * chunk as it arrives (iterate its generator to drain queued events), and
131
131
  * `flush()` once at end-of-stream to emit whatever is still buffered.
132
132
  *
@@ -135,7 +135,7 @@ function findOpenTag(buffer) {
135
135
  * the generator), which is the standard tradeoff for streaming tag
136
136
  * detection over an ever-growing buffer.
137
137
  */
138
- export function createArtifactParser() {
138
+ export function createArtifactParser(_requiredArgs) {
139
139
  const state = {
140
140
  inside: false,
141
141
  buffer: '',
@@ -144,7 +144,7 @@ export function createArtifactParser() {
144
144
  title: '',
145
145
  content: '',
146
146
  };
147
- function* feed(delta) {
147
+ function* feed({ delta }) {
148
148
  state.buffer += delta;
149
149
  while (state.buffer.length > 0) {
150
150
  if (!state.inside) {
@@ -164,7 +164,7 @@ export function createArtifactParser() {
164
164
  if (open.start > 0) {
165
165
  yield { type: 'text', delta: state.buffer.slice(0, open.start) };
166
166
  }
167
- const attrs = parseQuotedAttrs(open.attrs);
167
+ const attrs = parseQuotedAttrs({ raw: open.attrs });
168
168
  state.inside = true;
169
169
  state.identifier = attrs['identifier'] ?? '';
170
170
  state.artifactType = attrs['type'] ?? '';
@@ -205,7 +205,7 @@ export function createArtifactParser() {
205
205
  state.content = '';
206
206
  }
207
207
  }
208
- function* flush() {
208
+ function* flush(_requiredArgs) {
209
209
  if (state.inside) {
210
210
  if (state.buffer.length > 0) {
211
211
  state.content += state.buffer;
@@ -231,8 +231,8 @@ export function createArtifactParser() {
231
231
  * @param content - A complete (already fully-arrived) message body.
232
232
  * @complexity O(n) in `content.length` (one `feed` + one `flush` over the whole string).
233
233
  */
234
- export function parseArtifacts(content) {
235
- const parser = createArtifactParser();
236
- return [...parser.feed(content), ...parser.flush()];
234
+ export function parseArtifacts({ content }) {
235
+ const parser = createArtifactParser({});
236
+ return [...parser.feed({ delta: content }), ...parser.flush({})];
237
237
  }
238
238
  //# sourceMappingURL=parser.js.map
@@ -27,7 +27,9 @@ export declare function recoverHtmlArtifactFromPrecedingDocument({ artifactHtml,
27
27
  */
28
28
  export declare function resolvePersistedArtifactHtml(input: RecoverHtmlArtifactInput): string;
29
29
  /** Recover a complete `<html>…</html>` document that IS the entire (trimmed) `sourceText`, or `null` otherwise. */
30
- export declare function recoverStandaloneHtmlDocument(sourceText: string | null | undefined): string | null;
30
+ export declare function recoverStandaloneHtmlDocument({ sourceText }: {
31
+ sourceText: string | null | undefined;
32
+ }): string | null;
31
33
  /**
32
34
  * Recover a complete HTML document from a *single* ```html fenced block in
33
35
  * `sourceText`. Returns `null` when there is no such fence, more than one
@@ -35,6 +37,8 @@ export declare function recoverStandaloneHtmlDocument(sourceText: string | null
35
37
  * candidates are ambiguous about which one is "the" artifact, so none is
36
38
  * chosen automatically.
37
39
  */
38
- export declare function recoverHtmlDocumentFromMarkdownFence(sourceText: string | null | undefined): string | null;
40
+ export declare function recoverHtmlDocumentFromMarkdownFence({ sourceText }: {
41
+ sourceText: string | null | undefined;
42
+ }): string | null;
39
43
  export {};
40
44
  //# sourceMappingURL=recover.d.ts.map
@@ -44,7 +44,7 @@ function lastIndexOfRegex(re, text) {
44
44
  export function recoverHtmlArtifactFromPrecedingDocument({ artifactHtml, identifier, sourceText }) {
45
45
  if (!sourceText)
46
46
  return null;
47
- if (validateHtmlArtifact(artifactHtml).ok)
47
+ if (validateHtmlArtifact({ content: artifactHtml }).ok)
48
48
  return null;
49
49
  const artifactOpen = findLastArtifactOpen(sourceText, identifier);
50
50
  if (artifactOpen === -1)
@@ -67,7 +67,7 @@ export function recoverHtmlArtifactFromPrecedingDocument({ artifactHtml, identif
67
67
  const adjacentDoctype = beforeHtmlOpen.match(ADJACENT_DOCTYPE_RE);
68
68
  const htmlStart = adjacentDoctype ? htmlOpenStart - adjacentDoctype[0].length : htmlOpenStart;
69
69
  const candidate = beforeArtifact.slice(htmlStart, htmlClose + closeMatch[0].length).trim();
70
- return validateHtmlArtifact(candidate).ok ? candidate : null;
70
+ return validateHtmlArtifact({ content: candidate }).ok ? candidate : null;
71
71
  }
72
72
  /**
73
73
  * Resolve the HTML that should actually be persisted for an artifact. When
@@ -84,11 +84,11 @@ export function resolvePersistedArtifactHtml(input) {
84
84
  return recoverHtmlArtifactFromPrecedingDocument(input) ?? input.artifactHtml;
85
85
  }
86
86
  /** Recover a complete `<html>…</html>` document that IS the entire (trimmed) `sourceText`, or `null` otherwise. */
87
- export function recoverStandaloneHtmlDocument(sourceText) {
87
+ export function recoverStandaloneHtmlDocument({ sourceText }) {
88
88
  const candidate = String(sourceText || '').replace(/^/, '').trim();
89
89
  if (!/<\/html\s*>$/i.test(candidate))
90
90
  return null;
91
- return validateHtmlArtifact(candidate).ok ? candidate : null;
91
+ return validateHtmlArtifact({ content: candidate }).ok ? candidate : null;
92
92
  }
93
93
  /**
94
94
  * Recover a complete HTML document from a *single* ```html fenced block in
@@ -97,7 +97,7 @@ export function recoverStandaloneHtmlDocument(sourceText) {
97
97
  * candidates are ambiguous about which one is "the" artifact, so none is
98
98
  * chosen automatically.
99
99
  */
100
- export function recoverHtmlDocumentFromMarkdownFence(sourceText) {
100
+ export function recoverHtmlDocumentFromMarkdownFence({ sourceText }) {
101
101
  const text = String(sourceText || '');
102
102
  HTML_FENCE_RE.lastIndex = 0;
103
103
  let recovered = null;
@@ -107,7 +107,7 @@ export function recoverHtmlDocumentFromMarkdownFence(sourceText) {
107
107
  const candidate = (match[1] || '').replace(/^/, '').trim();
108
108
  if (!/<\/html\s*>$/i.test(candidate))
109
109
  continue;
110
- if (!validateHtmlArtifact(candidate).ok)
110
+ if (!validateHtmlArtifact({ content: candidate }).ok)
111
111
  continue;
112
112
  recovered = candidate;
113
113
  count += 1;
@@ -14,7 +14,9 @@
14
14
  * @complexity O(n) in `content.length` — one skip-range computation plus a
15
15
  * pair of linear scans for the open/close tags.
16
16
  */
17
- export declare function stripArtifact(content: string): string;
17
+ export declare function stripArtifact({ content }: {
18
+ content: string;
19
+ }): string;
18
20
  /**
19
21
  * Display-only cleanup for a fallback shape some models emit: a complete
20
22
  * HTML document as a standalone reply, or as a single ```html fenced block,
@@ -29,7 +31,11 @@ export declare function stripArtifact(content: string): string;
29
31
  *
30
32
  * @complexity O(n) in `content.length` (plus one bounded regex scan over `sourceText` for the fence-recovery path).
31
33
  */
32
- export declare function stripRecoveredHtmlFallbackForDisplay(content: string, sourceText?: string): string;
34
+ export declare function stripRecoveredHtmlFallbackForDisplay({ content }: {
35
+ content: string;
36
+ }, { sourceText }?: {
37
+ sourceText?: (string) | undefined;
38
+ }): string;
33
39
  /**
34
40
  * A persisted file a host confirms an artifact save wrote to storage.
35
41
  * `identifier` is the artifact manifest's `metadata.identifier` when present
@@ -48,7 +54,10 @@ export interface PersistedArtifactFileRef {
48
54
  *
49
55
  * @complexity O(m) in `persistedFiles.length` (linear `find`s).
50
56
  */
51
- export declare function matchPersistedArtifactFile(attrs: Record<string, string>, persistedFiles: ReadonlyArray<PersistedArtifactFileRef>): PersistedArtifactFileRef | null;
57
+ export declare function matchPersistedArtifactFile({ attrs, persistedFiles }: {
58
+ attrs: Record<string, string>;
59
+ persistedFiles: ReadonlyArray<PersistedArtifactFileRef>;
60
+ }): PersistedArtifactFileRef | null;
52
61
  /**
53
62
  * Replace every real `<artifact …>…</artifact>` block whose body is
54
63
  * CONFIRMED persisted to a file with a one-line summary, for use in a
@@ -77,7 +86,10 @@ export declare function matchPersistedArtifactFile(attrs: Record<string, string>
77
86
  * consumes at least one full artifact block or the remaining tail), times
78
87
  * O(m) for the `persistedFiles` lookup per block.
79
88
  */
80
- export declare function summarizeArtifactsForTranscript(content: string, persistedFiles: ReadonlyArray<PersistedArtifactFileRef>): string;
89
+ export declare function summarizeArtifactsForTranscript({ content, persistedFiles }: {
90
+ content: string;
91
+ persistedFiles: ReadonlyArray<PersistedArtifactFileRef>;
92
+ }): string;
81
93
  export interface StreamingArtifact {
82
94
  artifactType: string;
83
95
  title: string;
@@ -105,7 +117,9 @@ export interface StreamingArtifact {
105
117
  *
106
118
  * @complexity O(n) in `content.length`.
107
119
  */
108
- export declare function splitStreamingArtifact(content: string): {
120
+ export declare function splitStreamingArtifact({ content }: {
121
+ content: string;
122
+ }): {
109
123
  head: string;
110
124
  live: StreamingArtifact | null;
111
125
  };
@@ -20,7 +20,7 @@ function findUnskipped(content, needle, fromIndex, ranges) {
20
20
  const idx = content.indexOf(needle, from);
21
21
  if (idx === -1)
22
22
  return -1;
23
- if (!rangeContains(ranges, idx))
23
+ if (!rangeContains({ ranges: ranges, p: idx }))
24
24
  return idx;
25
25
  from = idx + needle.length;
26
26
  }
@@ -38,7 +38,7 @@ function findRealOpen(content, fromIndex, ranges) {
38
38
  const idx = content.indexOf(OPEN, from);
39
39
  if (idx === -1)
40
40
  return -1;
41
- if (rangeContains(ranges, idx) || !isRealArtifactOpenAt(content, idx)) {
41
+ if (rangeContains({ ranges: ranges, p: idx }) || !isRealArtifactOpenAt({ content: content, idx: idx })) {
42
42
  from = idx + OPEN.length;
43
43
  continue;
44
44
  }
@@ -61,8 +61,8 @@ function findRealOpen(content, fromIndex, ranges) {
61
61
  * @complexity O(n) in `content.length` — one skip-range computation plus a
62
62
  * pair of linear scans for the open/close tags.
63
63
  */
64
- export function stripArtifact(content) {
65
- const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges(content);
64
+ export function stripArtifact({ content }) {
65
+ const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges({ buffer: content });
66
66
  // For complete (non-streaming) content, an unclosed fence renders as a code
67
67
  // block extending to end of input — the stripper mirrors that, otherwise a
68
68
  // literal `<artifact …>` tucked into a trailing code example (no trailing
@@ -86,7 +86,7 @@ function findSingleRecoverableHtmlFence(content) {
86
86
  let match = HTML_FENCE_RE.exec(content);
87
87
  while (match !== null) {
88
88
  const html = (match[1] || '').replace(/^/, '').trim();
89
- if (recoverHtmlDocumentFromMarkdownFence(match[0]) === html) {
89
+ if (recoverHtmlDocumentFromMarkdownFence({ sourceText: match[0] }) === html) {
90
90
  recovered = { start: match.index, end: match.index + match[0].length, html };
91
91
  count += 1;
92
92
  }
@@ -95,7 +95,7 @@ function findSingleRecoverableHtmlFence(content) {
95
95
  return count === 1 ? recovered : null;
96
96
  }
97
97
  function findRecoverablePrecedingHtmlArtifact(sourceText) {
98
- const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges(sourceText);
98
+ const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges({ buffer: sourceText });
99
99
  const ranges = unclosedFenceStart !== null ? [...baseRanges, [unclosedFenceStart, sourceText.length]] : baseRanges;
100
100
  let from = 0;
101
101
  // `findRealOpen` already returns -1 once `from` runs past `sourceText.length`
@@ -111,7 +111,7 @@ function findRecoverablePrecedingHtmlArtifact(sourceText) {
111
111
  const end = findUnskipped(sourceText, CLOSE, closeTag, ranges);
112
112
  if (end === -1)
113
113
  return null;
114
- const attrs = parseQuotedAttrs(sourceText.slice(open, closeTag));
114
+ const attrs = parseQuotedAttrs({ raw: sourceText.slice(open, closeTag) });
115
115
  const recovered = recoverHtmlArtifactFromPrecedingDocument({
116
116
  artifactHtml: sourceText.slice(closeTag + 1, end),
117
117
  identifier: attrs['identifier'],
@@ -145,11 +145,11 @@ function stripRecoverablePrecedingHtml(content, sourceText) {
145
145
  *
146
146
  * @complexity O(n) in `content.length` (plus one bounded regex scan over `sourceText` for the fence-recovery path).
147
147
  */
148
- export function stripRecoveredHtmlFallbackForDisplay(content, sourceText = content) {
148
+ export function stripRecoveredHtmlFallbackForDisplay({ content }, { sourceText = content } = {}) {
149
149
  const withoutPrecedingDocument = stripRecoverablePrecedingHtml(content, sourceText);
150
150
  if (withoutPrecedingDocument !== null)
151
151
  return withoutPrecedingDocument;
152
- if (recoverStandaloneHtmlDocument(content))
152
+ if (recoverStandaloneHtmlDocument({ sourceText: content }))
153
153
  return '';
154
154
  const fence = findSingleRecoverableHtmlFence(content);
155
155
  if (!fence)
@@ -188,7 +188,7 @@ function artifactBaseNameForAttrs(attrs) {
188
188
  *
189
189
  * @complexity O(m) in `persistedFiles.length` (linear `find`s).
190
190
  */
191
- export function matchPersistedArtifactFile(attrs, persistedFiles) {
191
+ export function matchPersistedArtifactFile({ attrs, persistedFiles }) {
192
192
  const identifier = attrs['identifier'] ?? '';
193
193
  if (identifier) {
194
194
  const byManifest = persistedFiles.find((f) => f.identifier === identifier);
@@ -228,7 +228,7 @@ export function matchPersistedArtifactFile(attrs, persistedFiles) {
228
228
  * consumes at least one full artifact block or the remaining tail), times
229
229
  * O(m) for the `persistedFiles` lookup per block.
230
230
  */
231
- export function summarizeArtifactsForTranscript(content, persistedFiles) {
231
+ export function summarizeArtifactsForTranscript({ content, persistedFiles }) {
232
232
  if (persistedFiles.length === 0)
233
233
  return content;
234
234
  let result = '';
@@ -237,7 +237,7 @@ export function summarizeArtifactsForTranscript(content, persistedFiles) {
237
237
  // stay valid as we consume the string left to right.
238
238
  while (cursor <= content.length) {
239
239
  const tail = content.slice(cursor);
240
- const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges(tail);
240
+ const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges({ buffer: tail });
241
241
  const ranges = unclosedFenceStart !== null ? [...baseRanges, [unclosedFenceStart, tail.length]] : baseRanges;
242
242
  const open = findRealOpen(tail, 0, ranges);
243
243
  if (open === -1) {
@@ -256,8 +256,8 @@ export function summarizeArtifactsForTranscript(content, persistedFiles) {
256
256
  result += tail;
257
257
  break;
258
258
  }
259
- const attrs = parseQuotedAttrs(tail.slice(open, gt));
260
- const persisted = matchPersistedArtifactFile(attrs, persistedFiles);
259
+ const attrs = parseQuotedAttrs({ raw: tail.slice(open, gt) });
260
+ const persisted = matchPersistedArtifactFile({ attrs: attrs, persistedFiles: persistedFiles });
261
261
  result += persisted
262
262
  ? tail.slice(0, open) + artifactTranscriptSummary(attrs, persisted)
263
263
  : // Unconfirmed save — the transcript copy may be the only surviving
@@ -294,8 +294,8 @@ function artifactTranscriptSummary(attrs, persisted) {
294
294
  *
295
295
  * @complexity O(n) in `content.length`.
296
296
  */
297
- export function splitStreamingArtifact(content) {
298
- const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges(content);
297
+ export function splitStreamingArtifact({ content }) {
298
+ const { ranges: baseRanges, unclosedFenceStart } = computeSkipRanges({ buffer: content });
299
299
  const ranges = unclosedFenceStart !== null ? [...baseRanges, [unclosedFenceStart, content.length]] : baseRanges;
300
300
  const open = findRealOpen(content, 0, ranges);
301
301
  if (open === -1)
@@ -313,7 +313,7 @@ export function splitStreamingArtifact(content) {
313
313
  // A matching close means the block is complete; defer to stripArtifact.
314
314
  if (findUnskipped(content, CLOSE, gt, ranges) !== -1)
315
315
  return { head: content, live: null };
316
- const attrs = parseQuotedAttrs(content.slice(open, gt));
316
+ const attrs = parseQuotedAttrs({ raw: content.slice(open, gt) });
317
317
  const artifactType = attrs['type'] ?? '';
318
318
  // Only HTML/text artifacts read as code. An unknown type (attrs not fully
319
319
  // parsed, or omitted) is treated as code-eligible since the dominant case
@@ -46,5 +46,7 @@ export type HtmlArtifactValidationResult = {
46
46
  *
47
47
  * @complexity O(n) in `content.length` — a handful of linear regex scans.
48
48
  */
49
- export declare function validateHtmlArtifact(content: string): HtmlArtifactValidationResult;
49
+ export declare function validateHtmlArtifact({ content }: {
50
+ content: string;
51
+ }): HtmlArtifactValidationResult;
50
52
  //# sourceMappingURL=validate.d.ts.map
@@ -51,7 +51,7 @@ const CSS_IMPORT_RE = /@import\s+(?:url\(\s*(?:"([^"]*)"|'([^']*)'|([^)]*?))\s*\
51
51
  *
52
52
  * @complexity O(n) in `content.length` — a handful of linear regex scans.
53
53
  */
54
- export function validateHtmlArtifact(content) {
54
+ export function validateHtmlArtifact({ content }) {
55
55
  const trimmed = content.replace(/^/, '').trim();
56
56
  if (trimmed.length === 0) {
57
57
  return { ok: false, reason: 'empty content' };