@ai-matrx/rich-content 0.2.170 → 0.2.172

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.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,19 @@
1
1
  # Changelog
2
2
 
3
- ## 0.2.170
3
+ ## 0.2.172
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/rich-content/src`.
7
7
 
8
+ ## 0.2.170
9
+
10
+ SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
11
+ so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
12
+ Diff: `git diff 3d2ed872f6 44398623d1 -- apps/shared/rich-content/src`
13
+
14
+ Changed shipped source files (1):
15
+ - `apps/shared/rich-content/src/display/blocks/chart/ChartCanvas.tsx`
16
+
8
17
  ## 0.2.169
9
18
 
10
19
  Automatic changed-only republish (docs/metadata drift since the last published version; verified: `git diff aad1943517 3d2ed872f6 -- apps/shared/rich-content/src`
@@ -1,3 +1,4 @@
1
+ import { parseUnifiedDiff } from "./parse-unified-diff.js";
1
2
  const searchReplaceHandler = {
2
3
  name: "search-replace",
3
4
  canShowPartial: false,
@@ -55,13 +56,11 @@ const unifiedDiffHandler = {
55
56
  }
56
57
  };
57
58
  },
58
- parse: (content) => {
59
- return { lines: content.split("\n") };
60
- }
59
+ parse: (content) => parseUnifiedDiff(content)
61
60
  };
62
61
  const DIFF_STYLE_HANDLERS = [
63
62
  searchReplaceHandler
64
- // unifiedDiffHandler, // Add when ready
63
+ // unifiedDiffHandler, // parse() is real; register once a unified renderer exists
65
64
  // Add more handlers here as needed
66
65
  ];
67
66
  function detectDiffStyle(content) {
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Unified diff parser, safe on a stream: a partial last hunk parses as far as it goes and reports
3
+ * `isComplete: false` until the line counts in its `@@ -a,b +c,d @@` header are met.
4
+ */
5
+ import type { UnifiedDiffBlock } from './types.js';
6
+ export declare function parseUnifiedDiff(content: string): UnifiedDiffBlock;
@@ -0,0 +1,77 @@
1
+ const HUNK_HEADER = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@ ?(.*)$/;
2
+ function parseUnifiedDiff(content) {
3
+ const lines = content.split("\n");
4
+ if (lines.length > 1 && lines[lines.length - 1] === "") lines.pop();
5
+ const parsed = [];
6
+ const hunks = [];
7
+ let added = 0;
8
+ let removed = 0;
9
+ let oldLine = 0;
10
+ let newLine = 0;
11
+ let oldLeft = 0;
12
+ let newLeft = 0;
13
+ let open = null;
14
+ const closeHunk = () => {
15
+ if (open) open.to = parsed.length - 1;
16
+ open = null;
17
+ };
18
+ for (const raw of lines) {
19
+ const header = HUNK_HEADER.exec(raw);
20
+ if (header) {
21
+ closeHunk();
22
+ const oldCount = header[2] === void 0 ? 1 : Number(header[2]);
23
+ const newCount = header[4] === void 0 ? 1 : Number(header[4]);
24
+ open = {
25
+ oldStart: Number(header[1]),
26
+ oldCount,
27
+ newStart: Number(header[3]),
28
+ newCount,
29
+ section: header[5] ?? "",
30
+ from: parsed.length,
31
+ to: parsed.length
32
+ };
33
+ hunks.push(open);
34
+ oldLine = open.oldStart;
35
+ newLine = open.newStart;
36
+ oldLeft = oldCount;
37
+ newLeft = newCount;
38
+ parsed.push({ kind: "hunk", text: raw, oldLine: null, newLine: null });
39
+ continue;
40
+ }
41
+ const insideBody = open !== null && (oldLeft > 0 || newLeft > 0);
42
+ if (insideBody) {
43
+ const marker = raw[0];
44
+ if (marker === "+") {
45
+ parsed.push({ kind: "add", text: raw.slice(1), oldLine: null, newLine: newLine++ });
46
+ newLeft--;
47
+ added++;
48
+ continue;
49
+ }
50
+ if (marker === "-") {
51
+ parsed.push({ kind: "remove", text: raw.slice(1), oldLine: oldLine++, newLine: null });
52
+ oldLeft--;
53
+ removed++;
54
+ continue;
55
+ }
56
+ if (marker === "\\") {
57
+ parsed.push({ kind: "no-newline", text: raw, oldLine: null, newLine: null });
58
+ continue;
59
+ }
60
+ parsed.push({ kind: "context", text: marker === " " ? raw.slice(1) : raw, oldLine: oldLine++, newLine: newLine++ });
61
+ oldLeft--;
62
+ newLeft--;
63
+ continue;
64
+ }
65
+ if (open) closeHunk();
66
+ if (raw.startsWith("--- ")) parsed.push({ kind: "file-old", text: raw.slice(4), oldLine: null, newLine: null });
67
+ else if (raw.startsWith("+++ ")) parsed.push({ kind: "file-new", text: raw.slice(4), oldLine: null, newLine: null });
68
+ else if (raw.startsWith("\\")) parsed.push({ kind: "no-newline", text: raw, oldLine: null, newLine: null });
69
+ else parsed.push({ kind: "meta", text: raw, oldLine: null, newLine: null });
70
+ }
71
+ closeHunk();
72
+ const isComplete = hunks.length > 0 && oldLeft <= 0 && newLeft <= 0;
73
+ return { lines, parsed, hunks, added, removed, isComplete };
74
+ }
75
+ export {
76
+ parseUnifiedDiff
77
+ };
@@ -24,8 +24,37 @@ export interface SearchReplaceBlock {
24
24
  /**
25
25
  * Parsed unified diff (line-based) block
26
26
  */
27
+ export type UnifiedDiffLineKind = 'meta' | 'file-old' | 'file-new' | 'hunk' | 'add' | 'remove' | 'context' | 'no-newline';
28
+ export interface UnifiedDiffLine {
29
+ kind: UnifiedDiffLineKind;
30
+ /** The line without its leading +/-/space marker (full text for meta, file and hunk lines). */
31
+ text: string;
32
+ /** 1-based line number in the old file; null for added and structural lines. */
33
+ oldLine: number | null;
34
+ /** 1-based line number in the new file; null for removed and structural lines. */
35
+ newLine: number | null;
36
+ }
37
+ export interface UnifiedDiffHunk {
38
+ oldStart: number;
39
+ oldCount: number;
40
+ newStart: number;
41
+ newCount: number;
42
+ /** Text after the second `@@` (usually the enclosing function). */
43
+ section: string;
44
+ /** Index range into `UnifiedDiffBlock.parsed` covered by this hunk (header included). */
45
+ from: number;
46
+ to: number;
47
+ }
27
48
  export interface UnifiedDiffBlock {
49
+ /** The raw lines, unchanged. */
28
50
  lines: string[];
51
+ /** Every line classified, with old/new line numbers tracked through the hunks. */
52
+ parsed: UnifiedDiffLine[];
53
+ hunks: UnifiedDiffHunk[];
54
+ added: number;
55
+ removed: number;
56
+ /** True when the last hunk has received every line its header promised. */
57
+ isComplete: boolean;
29
58
  }
30
59
  /**
31
60
  * Union of every shape a diff style handler's parse() can return.
@@ -201,6 +201,12 @@ export interface RichDocumentActionContextCallbacks {
201
201
  * so the host can narrow to that part; null or [] means "nothing to offer".
202
202
  */
203
203
  tableRows?: (selection: string | null) => ReadonlyArray<Record<string, unknown>> | null;
204
+ /**
205
+ * This content exactly as produced, reasoning included, when the host keeps reasoning apart from
206
+ * the text (a chat answer's thinking blocks). Alchemy's "Raw with thinking" copies it; null when
207
+ * there was no reasoning.
208
+ */
209
+ rawWithThinking?: () => string | null;
204
210
  /**
205
211
  * The rendered table the right-click landed on, as table text with its shape kept (header +
206
212
  * rows) — set by the context-menu shell from the clicked element, so "Save to a table" opens on
@@ -46,7 +46,11 @@ function AlchemyDocumentMenu({
46
46
  label: "Document",
47
47
  data: () => {
48
48
  const ctx = getCtx();
49
- return { value: ctx.content, type: ctx.source?.type === "chat-message" ? "AI response" : "Document" };
49
+ return {
50
+ value: ctx.content,
51
+ type: ctx.source?.type === "chat-message" ? "AI response" : "Document",
52
+ withThinking: ctx.callbacks?.rawWithThinking?.() ?? null
53
+ };
50
54
  },
51
55
  className: size === "xs" ? "matrx-alchemy-xs" : void 0,
52
56
  ...triggerHidden ? { triggerHidden: true } : {},
@@ -1,4 +1,4 @@
1
- import { classifyMediaUrl, isDurableMediaUrl, shareableMediaUrl, type MediaUrlKind } from "@ai-matrx/data/files";
1
+ import { classifyMediaUrl, isDurableMediaUrl, shareableMediaUrl, type MediaUrlKind } from "@ai-matrx/files/client";
2
2
  export { classifyMediaUrl, isDurableMediaUrl, shareableMediaUrl };
3
3
  export type { MediaUrlKind };
4
4
  /**
@@ -3,7 +3,7 @@ import {
3
3
  createFileUrlRecognizer,
4
4
  isDurableMediaUrl,
5
5
  shareableMediaUrl
6
- } from "@ai-matrx/data/files";
6
+ } from "@ai-matrx/files/client";
7
7
  import { captureError } from "../../host/diagnostics.js";
8
8
  const recognizer = createFileUrlRecognizer();
9
9
  function fileIdFromUserFilesUrl(url) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-matrx/rich-content",
3
- "version": "0.2.170",
3
+ "version": "0.2.172",
4
4
  "description": "The AI Matrx formatted-text engine: the one markdown renderer, streaming markdown, the block splitter and renderer, the generic blocks, <RichContent> levels, the rich-document action registry and menus, copy, and the selection toolbar — as portable React.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -130,21 +130,22 @@
130
130
  "unist-util-visit": "^5.1.0",
131
131
  "unist-util-visit-parents": "^6.0.2",
132
132
  "yaml": "^2.9.1",
133
+ "@ai-matrx/agents": "latest",
133
134
  "@ai-matrx/alchemy": "latest",
134
135
  "@ai-matrx/api": "latest",
135
136
  "@ai-matrx/canvas": "latest",
136
137
  "@ai-matrx/content-ir": "latest",
137
138
  "@ai-matrx/content-ir-react": "latest",
138
- "@ai-matrx/data": "latest",
139
139
  "@ai-matrx/design-system": "latest",
140
- "@ai-matrx/agents": "latest",
141
140
  "@ai-matrx/diff": "latest",
142
- "@ai-matrx/media": "latest",
143
- "@ai-matrx/print": "latest",
144
- "@ai-matrx/kit": "latest",
141
+ "@ai-matrx/data": "latest",
145
142
  "@ai-matrx/icons": "latest",
146
- "@ai-matrx/records": "latest",
147
- "@ai-matrx/records-ui": "latest"
143
+ "@ai-matrx/files": "latest",
144
+ "@ai-matrx/kit": "latest",
145
+ "@ai-matrx/print": "latest",
146
+ "@ai-matrx/records-ui": "latest",
147
+ "@ai-matrx/media": "latest",
148
+ "@ai-matrx/records": "latest"
148
149
  },
149
150
  "peerDependencies": {
150
151
  "react": ">=19.0.0",
@@ -205,5 +206,5 @@
205
206
  "verify:modules-tarball": "node ./scripts/verify-modules-tarball.mjs",
206
207
  "verify:tarball": "node ./scripts/verify-tarball.mjs"
207
208
  },
208
- "gitHead": "44398623d1fc90e4f200f6201c08b8b2b1585607"
209
+ "gitHead": "de1c78033bf8d06b35b03b2443e3c99cb9ed6f19"
209
210
  }