-
Notifications
You must be signed in to change notification settings - Fork 2
Revert "fix: upload chat-message markup as MarkupBlobRef instead of raw HTML (HULY-20)" #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,6 @@ import { | |
| } from '../output/format.js' | ||
| import { withSpinner } from '../output/progress.js' | ||
| import { CliError, ExitCode } from '../output/errors.js' | ||
| import { uploadMarkup, generateId } from './_helpers.js' | ||
|
|
||
| type ActivityMessage = Doc & { | ||
| message?: string | ||
|
|
@@ -372,12 +371,7 @@ export async function addReply(opts: ReplyOpts): Promise<void> { | |
| const client = await connectCli({ url: opts.url, workspace: opts.workspace }) | ||
| try { | ||
| const { id, doc } = await fetchActivity(client, opts.target) | ||
| // HULY-20: upload the markup first so `message` stores a MarkupBlobRef | ||
| // (prosemirror-JSON-backed), not raw HTML. The id is generated up-front | ||
| // so the markup blob's collabId and the reply doc share the same id. | ||
| const newReplyId = generateId() | ||
| const messageRef = await uploadMarkup(client, ACTIVITY_CLASS, newReplyId, 'message', opts.body, 'markup') | ||
| const data: Record<string, unknown> = { message: messageRef } | ||
| const data: Record<string, unknown> = { message: opts.body } | ||
| const rid = await withSpinner( | ||
| 'Replying…', | ||
| () => | ||
|
|
@@ -388,7 +382,6 @@ export async function addReply(opts: ReplyOpts): Promise<void> { | |
| ACTIVITY_CLASS, | ||
| 'replies', | ||
| data as any, | ||
| newReplyId, | ||
| ), | ||
| opts, | ||
| ) | ||
|
|
@@ -415,13 +408,11 @@ export async function updateReply( | |
| // attachedTo pointing at the parent). `message` lives on the reply | ||
| // doc itself — updateDoc, NOT updateCollection against the parent's | ||
| // 'replies' tuple (which doesn't exist). | ||
| // HULY-20: upload markup first so the update lands a MarkupBlobRef. | ||
| const messageRef = await uploadMarkup(client, ACTIVITY_CLASS, id, 'message', opts.body, 'markup') | ||
| await client.updateDoc( | ||
| ACTIVITY_CLASS, | ||
| doc.space as unknown as Ref<Space>, | ||
| id as Ref<Doc>, | ||
| { message: messageRef, modifiedOn: Date.now() } as any, | ||
| { message: opts.body, modifiedOn: Date.now() } as any, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| ) | ||
| updated('updated reply', refString(id)) | ||
| } finally { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -18,7 +18,6 @@ import { | |
| } from '../output/format.js' | ||
| import { withSpinner } from '../output/progress.js' | ||
| import { CliError, ExitCode } from '../output/errors.js' | ||
| import { uploadMarkup, generateId } from './_helpers.js' | ||
|
|
||
| const REQUEST_STATUSES = ['Active', 'Completed', 'Rejected', 'Cancelled'] as const | ||
| type RequestStatus = (typeof REQUEST_STATUSES)[number] | ||
|
|
@@ -298,19 +297,7 @@ export async function commentOnApproval(opts: CommentOpts): Promise<void> { | |
| const client = await connectCli({ url: opts.url, workspace: opts.workspace }) | ||
| try { | ||
| const { id, doc } = await fetchRequest(client, opts.ref!) | ||
| // HULY-20: upload markup so `message` stores a MarkupBlobRef, not raw | ||
| // HTML. Generate id up-front so the markup blob's collabId matches | ||
| // the ChatMessage doc's id. No --dry-run flag on this surface today. | ||
| const newCommentId = generateId() | ||
| const messageRef = await uploadMarkup( | ||
| client, | ||
| 'chunter:class:ChatMessage' as Ref<Class<Doc>>, | ||
| newCommentId, | ||
| 'message', | ||
| opts.body, | ||
| 'markup', | ||
| ) | ||
| const data: Record<string, unknown> = { message: messageRef } | ||
| const data: Record<string, unknown> = { message: opts.body } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| if (opts.decision) data.decision = opts.decision | ||
| const cid = await withSpinner( | ||
| 'Commenting…', | ||
|
|
@@ -322,7 +309,6 @@ export async function commentOnApproval(opts: CommentOpts): Promise<void> { | |
| REQUEST_CLASS, | ||
| 'comments', | ||
| data as any, | ||
| newCommentId, | ||
| ), | ||
| opts, | ||
| ) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,6 @@ import { normalizeSocialKey } from '../auth/social.js' | |
| import { shouldJson, json, table, COLUMNS, C, success, updated, bulkRemoved } from '../output/format.js' | ||
| import { withSpinner } from '../output/progress.js' | ||
| import { CliError, ExitCode } from '../output/errors.js' | ||
| import { uploadMarkup, generateId } from './_helpers.js' | ||
|
|
||
| type Channel = Doc & { | ||
| name: string | ||
|
|
@@ -547,21 +546,8 @@ export async function sendChannelMessage( | |
| const client = await connectCli({ url: opts.url, workspace: opts.workspace }) | ||
| try { | ||
| const channel = await resolveChannel(client, ref) | ||
| // HULY-20: pre-upload the markup so `message` stores a MarkupBlobRef, | ||
| // not raw HTML. Generate the id up-front so the markup blob's collabId | ||
| // matches the ChatMessage doc's id (the platform keys the blob by | ||
| // `${class}:${id}:${attribute}`). | ||
| const newMessageId = generateId() | ||
| // Defer the actual upload until after the dry-run guard below — same | ||
| // pattern as the HULY-8 updateIssue fix. Dry-run must not write to | ||
| // MinIO. The dry-run preview shows `message: ''` (the placeholder) + | ||
| // a `wouldUploadMarkup` note so users see what would happen. | ||
| let messageRef = '' | ||
| if (!opts.dryRun) { | ||
| messageRef = await uploadMarkup(client, CHAT_MESSAGE_CLASS, newMessageId, 'message', body, 'markup') | ||
| } | ||
| const data: Record<string, unknown> = { | ||
| message: messageRef, | ||
| message: body, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Note: this hunk also silently drops the Reply with |
||
| } | ||
| if (opts.dryRun) { | ||
| console.log('would send channel message:') | ||
|
|
@@ -574,12 +560,6 @@ export async function sendChannelMessage( | |
| attachedToClass: CHANNEL_CLASS, | ||
| collection: 'messages', | ||
| data, | ||
| wouldUploadMarkup: { | ||
| objectClass: CHAT_MESSAGE_CLASS, | ||
| objectId: newMessageId, | ||
| objectAttr: 'message', | ||
| bodyBytes: body.length, | ||
| }, | ||
| }, | ||
| null, | ||
| 2, | ||
|
|
@@ -595,7 +575,6 @@ export async function sendChannelMessage( | |
| CHANNEL_CLASS, | ||
| 'messages', | ||
| data as any, | ||
| newMessageId, | ||
| ), | ||
| ) | ||
| if (shouldJson({ json: opts.json, ci: opts.ci })) { | ||
|
|
@@ -631,23 +610,8 @@ export async function updateChannelMessage( | |
| if (msg.attachedTo !== channel._id) { | ||
| throw new CliError(ExitCode.NotFound, 'message does not belong to this channel') | ||
| } | ||
| // HULY-20: upload the markup so the update lands a MarkupBlobRef in | ||
| // `message`, not raw HTML. The existing messageId is reused so the | ||
| // markup blob's collabId stays consistent across updates. Deferred | ||
| // until after the dry-run guard below (same pattern as HULY-8). | ||
| let messageRef = '' | ||
| if (!opts.dryRun) { | ||
| messageRef = await uploadMarkup( | ||
| client, | ||
| CHAT_MESSAGE_CLASS, | ||
| messageId as Ref<Doc>, | ||
| 'message', | ||
| body, | ||
| 'markup', | ||
| ) | ||
| } | ||
| const data: Record<string, unknown> = { | ||
| message: messageRef, | ||
| message: body, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| editedOn: Date.now(), | ||
| } | ||
| if (opts.dryRun) { | ||
|
|
@@ -773,24 +737,8 @@ export async function addThreadReply( | |
| try { | ||
| const parent = await client.findOne(CHAT_MESSAGE_CLASS, { _id: targetId as Ref<ChatMessage> }) | ||
| if (!parent) throw new CliError(ExitCode.NotFound, `target message ${targetId} not found`) | ||
| // HULY-20: upload markup first so `message` stores a MarkupBlobRef. | ||
| // The reply lives in chunter:class:ThreadMessage (subclass of | ||
| // ChatMessage), and the markup blob is keyed by that subclass id. | ||
| // Deferred until after the dry-run guard (same pattern as HULY-8). | ||
| const newReplyId = generateId() | ||
| let messageRef = '' | ||
| if (!opts.dryRun) { | ||
| messageRef = await uploadMarkup( | ||
| client, | ||
| 'chunter:class:ThreadMessage' as Ref<Class<Doc>>, | ||
| newReplyId, | ||
| 'message', | ||
| body, | ||
| 'markup', | ||
| ) | ||
| } | ||
| const data: Record<string, unknown> = { | ||
| message: messageRef, | ||
| message: body, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| } | ||
| if (opts.dryRun) { | ||
| console.log('would add thread reply:') | ||
|
|
@@ -811,7 +759,6 @@ export async function addThreadReply( | |
| CHAT_MESSAGE_CLASS, | ||
| 'replies', | ||
| data as any, | ||
| newReplyId, | ||
| ), | ||
| ) | ||
| if (shouldJson({ json: opts.json, ci: opts.ci })) { | ||
|
|
@@ -844,20 +791,7 @@ export async function updateThreadReply( | |
| _id: replyId as Ref<ChatMessage>, | ||
| }) | ||
| if (!reply) throw new CliError(ExitCode.NotFound, `thread reply ${replyId} not found`) | ||
| // HULY-20: upload markup so the update lands a MarkupBlobRef. Deferred | ||
| // until after the dry-run guard (same pattern as HULY-8). | ||
| let messageRef = '' | ||
| if (!opts.dryRun) { | ||
| messageRef = await uploadMarkup( | ||
| client, | ||
| 'chunter:class:ThreadMessage' as Ref<Class<Doc>>, | ||
| replyId as Ref<Doc>, | ||
| 'message', | ||
| body, | ||
| 'markup', | ||
| ) | ||
| } | ||
| const data: Record<string, unknown> = { message: messageRef, editedOn: Date.now() } | ||
| const data: Record<string, unknown> = { message: body, editedOn: Date.now() } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| if (opts.dryRun) { | ||
| console.log(`would update thread reply ${replyId}:`) | ||
| console.log( | ||
|
|
@@ -1105,14 +1039,7 @@ export async function sendDmMessage( | |
| }) | ||
| const dm = await client.findOne(DM_CLASS, { _id: dmId as Ref<DirectMessage> }) | ||
| if (!dm) throw new CliError(ExitCode.NotFound, `DM ${dmRef} not found`) | ||
| // HULY-20: upload markup so `message` stores a MarkupBlobRef, not raw | ||
| // HTML. Deferred until after the dry-run guard (same pattern as HULY-8). | ||
| const newMessageId = generateId() | ||
| let messageRef = '' | ||
| if (!opts.dryRun) { | ||
| messageRef = await uploadMarkup(client, CHAT_MESSAGE_CLASS, newMessageId, 'message', body, 'markup') | ||
| } | ||
| const data: Record<string, unknown> = { message: messageRef } | ||
| const data: Record<string, unknown> = { message: body } | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Note: this hunk also silently drops the Reply with |
||
| if (opts.dryRun) { | ||
| console.log('would send DM:') | ||
| console.log( | ||
|
|
@@ -1124,12 +1051,6 @@ export async function sendDmMessage( | |
| attachedToClass: DM_CLASS, | ||
| collection: 'messages', | ||
| data, | ||
| wouldUploadMarkup: { | ||
| objectClass: CHAT_MESSAGE_CLASS, | ||
| objectId: newMessageId, | ||
| objectAttr: 'message', | ||
| bodyBytes: body.length, | ||
| }, | ||
| }, | ||
| null, | ||
| 2, | ||
|
|
@@ -1145,7 +1066,6 @@ export async function sendDmMessage( | |
| DM_CLASS, | ||
| 'messages', | ||
| data as any, | ||
| newMessageId, | ||
| ), | ||
| ) | ||
| if (shouldJson({ json: opts.json, ci: opts.ci })) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,6 @@ import { shouldJson, json, table, COLUMNS, success, updated, bulkRemoved } from | |
| import { withSpinner } from '../output/progress.js' | ||
| import { CliError, ExitCode } from '../output/errors.js' | ||
| import { readEnv } from '../auth/env.js' | ||
| import { uploadMarkup, generateId } from './_helpers.js' | ||
|
|
||
| type ChatMessage = Doc & { | ||
| message: string | ||
|
|
@@ -86,19 +85,6 @@ export async function addComment(opts: { | |
| }) | ||
| const issue = await client.findOne(CLASS.Issue as Ref<Class<Doc>>, { _id: issueId }) | ||
| if (!issue) throw new CliError(ExitCode.NotFound, `issue ${opts.issue} not found`) | ||
| // HULY-20: pre-upload the markup so the `message` field stores a | ||
| // MarkupBlobRef (pointing to a prosemirror-JSON blob in MinIO) instead of | ||
| // a raw HTML string. Generating the id up-front lets us use the same | ||
| // id for both the markup blob's collabId and the ChatMessage doc. | ||
| const newMessageId = generateId() | ||
| const messageRef = await uploadMarkup( | ||
| client, | ||
| CLASS.ChatMessage as Ref<Class<Doc>>, | ||
| newMessageId, | ||
| 'message', | ||
| body, | ||
| 'markup', | ||
| ) | ||
| const id = await withSpinner( | ||
| 'Adding comment…', | ||
| () => | ||
|
|
@@ -108,14 +94,13 @@ export async function addComment(opts: { | |
| issueId, | ||
| CLASS.Issue, | ||
| 'comments', | ||
| { message: messageRef } as any, | ||
| newMessageId, | ||
| { message: body } as any, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| ), | ||
| opts, | ||
| ) | ||
| invalidateIndex(client, CLASS.ChatMessage) | ||
| if (shouldJson({ json: opts.json, ci: opts.ci })) { | ||
| json({ _id: id, attachedTo: issueId, message: messageRef }) | ||
| json({ _id: id, attachedTo: issueId, message: body }) | ||
| } else { | ||
| success('added comment', `on ${opts.issue}`, id) | ||
| } | ||
|
|
@@ -145,24 +130,14 @@ export async function updateComment( | |
| }) | ||
| const comment = await client.findOne(CLASS.ChatMessage as Ref<Class<ChatMessage>>, { _id: commentId }) | ||
| if (!comment) throw new CliError(ExitCode.NotFound, `comment ${ref} not found`) | ||
| // HULY-20: same fix as addComment — upload the markup first so the | ||
| // update lands a MarkupBlobRef in `message`, not raw HTML. | ||
| const messageRef = await uploadMarkup( | ||
| client, | ||
| CLASS.ChatMessage as Ref<Class<Doc>>, | ||
| commentId, | ||
| 'message', | ||
| body, | ||
| 'markup', | ||
| ) | ||
| await withSpinner( | ||
| 'Updating comment…', | ||
| () => | ||
| client.updateDoc( | ||
| CLASS.ChatMessage as Ref<Class<ChatMessage>>, | ||
| (comment as Doc).space as Ref<Doc>, | ||
| commentId as Ref<Doc>, | ||
| { message: messageRef, editedOn: Date.now() } as any, | ||
| { message: body, editedOn: Date.now() } as any, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. CRITICAL: This revert restores raw HTML in the Reply with |
||
| ), | ||
| opts, | ||
| ) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CRITICAL: This revert restores raw HTML in the
messagefield foraddReply, reintroducing the HULY-20 bug that #44 fixed. The Huly platform expectsmessageto be aMarkupBlobRef(prosemirror-JSON blob in MinIO keyed by${class}:${id}:${attribute}); storing raw HTML breaks prosemirror rendering, search/indexing, and consistency with the web/desktop clients.Reply with
@kilocode-bot fix itto have Kilo Code address this issue.