feat(platform): sticker spanKind and stage/delete spans for Phase 542

Add sticker.stage and sticker.delete spans with spanKind and
activeChannelId; extend sticker.create and sticker.send span ends.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Raven Scott
2026-05-24 13:02:09 -04:00
co-authored by Cursor
parent 97b70077c9
commit be546134f3
2 changed files with 104 additions and 52 deletions
+2
View File
@@ -45,6 +45,8 @@ Expose a single `EventEmitter` API the UI drives over IPC (`apps/pearcord/index.
**v0.8.452 (Phase 489):** `slash.register` `customCount`; `slash.delete` `deleted`; `slash.invoke` `replyLen`/`commandFound`. UI slash compositor + hints. Bundle: `npm run test:phase489-slash`. See [SLASH_COMMANDS.md](../../docs/SLASH_COMMANDS.md). **v0.8.452 (Phase 489):** `slash.register` `customCount`; `slash.delete` `deleted`; `slash.invoke` `replyLen`/`commandFound`. UI slash compositor + hints. Bundle: `npm run test:phase489-slash`. See [SLASH_COMMANDS.md](../../docs/SLASH_COMMANDS.md).
**v0.8.505 (Phase 542):** Sticker spans extend — `sticker.create`/`sticker.delete`/`sticker.stage`/`sticker.send` with `spanKind` + `activeChannelId`. UI split sticker compositor panels, `lastStickerTileName`, dedicated **sticker-errors** dev-log filter. Bundle: `npm run test:phase542-stickers`. See [STICKERS.md](../../docs/STICKERS.md).
**v0.8.504 (Phase 541):** Emoji spans extend — `emoji.upsert` ends with `spanKind: 'emoji.create'`; new `emoji.delete` + `emoji.stage` spans with `activeChannelId`. UI split emoji compositor panels, picker tile `lastEmojiTileName`, clipboard emoji busy flags. Bundle: `npm run test:phase541-emoji`. See [EMOJI.md](../../docs/EMOJI.md). **v0.8.504 (Phase 541):** Emoji spans extend — `emoji.upsert` ends with `spanKind: 'emoji.create'`; new `emoji.delete` + `emoji.stage` spans with `activeChannelId`. UI split emoji compositor panels, picker tile `lastEmojiTileName`, clipboard emoji busy flags. Bundle: `npm run test:phase541-emoji`. See [EMOJI.md](../../docs/EMOJI.md).
**v0.8.503 (Phase 540):** Automation spans extend — `automation.hook`/`automation.manifest`/`automation.hook.dryRun`/`automation.dispatch` end metadata (`spanKind`, `activeChannelId`). UI automation panel compositor wrappers, hook row `lastAutomationHookRowId` + roving `tabindex`, clipboard automation busy flags. Bundle: `npm run test:phase540-automation`. See [AUTOMATION_EXPORT.md](../../docs/AUTOMATION_EXPORT.md). **v0.8.503 (Phase 540):** Automation spans extend — `automation.hook`/`automation.manifest`/`automation.hook.dryRun`/`automation.dispatch` end metadata (`spanKind`, `activeChannelId`). UI automation panel compositor wrappers, hook row `lastAutomationHookRowId` + roving `tabindex`, clipboard automation busy flags. Bundle: `npm run test:phase540-automation`. See [AUTOMATION_EXPORT.md](../../docs/AUTOMATION_EXPORT.md).
+56 -6
View File
@@ -8491,7 +8491,11 @@ class PearcordPlatform extends EventEmitter {
.filter(Boolean) .filter(Boolean)
.slice(0, 3) .slice(0, 3)
if (!names.length) { if (!names.length) {
span.end({ resolved: 0 }) span.end({
resolved: 0,
spanKind: 'sticker.send',
activeChannelId: this.activeChannelId
})
return [] return []
} }
if (this.mode !== 'guild' || !this.guild?.guild) { if (this.mode !== 'guild' || !this.guild?.guild) {
@@ -8505,12 +8509,17 @@ class PearcordPlatform extends EventEmitter {
if (!row) throw new Error(`unknown sticker: ${name}`) if (!row) throw new Error(`unknown sticker: ${name}`)
out.push(row.name) out.push(row.name)
} }
span.end({ resolved: out.length, names: out }) span.end({
resolved: out.length,
names: out,
spanKind: 'sticker.send',
activeChannelId: this.activeChannelId
})
return out return out
} catch (err) { } catch (err) {
this.log.error('sticker.send error', { this.log.error('sticker.send error', {
channelId: this.activeChannelId || null, channelId: this.activeChannelId || null,
err: err?.message || String(err) error: err?.message || String(err)
}) })
span.fail(err) span.fail(err)
throw err throw err
@@ -9113,10 +9122,12 @@ class PearcordPlatform extends EventEmitter {
} }
async stageGuildStickerImage ({ data, filename, mimeType }) { async stageGuildStickerImage ({ data, filename, mimeType }) {
const guildId = this.guild?.guild?.id || null
const span = this.log.time('sticker.stage', { guildId, filename: filename || null })
try {
if (!this.attachments) throw new Error('attachments not ready') if (!this.attachments) throw new Error('attachments not ready')
const user = this.identity.user const user = this.identity.user
if (!user) throw new Error('register first') if (!user) throw new Error('register first')
const guildId = this.guild?.guild?.id
if (!guildId) throw new Error('no guild') if (!guildId) throw new Error('no guild')
const buf = Buffer.isBuffer(data) ? data : Buffer.from(data || []) const buf = Buffer.isBuffer(data) ? data : Buffer.from(data || [])
let mt = String(mimeType || '').toLowerCase() let mt = String(mimeType || '').toLowerCase()
@@ -9133,7 +9144,7 @@ class PearcordPlatform extends EventEmitter {
if (buf.length > MAX_STICKER_BYTES) { if (buf.length > MAX_STICKER_BYTES) {
throw new Error('sticker file too large (max 512 KB)') throw new Error('sticker file too large (max 512 KB)')
} }
return this.attachments.stage({ const att = await this.attachments.stage({
data: buf, data: buf,
filename: filename || (fmt === 'lottie' ? 'sticker.json' : 'sticker.gif'), filename: filename || (fmt === 'lottie' ? 'sticker.json' : 'sticker.gif'),
mimeType: mt, mimeType: mt,
@@ -9141,6 +9152,22 @@ class PearcordPlatform extends EventEmitter {
channelId: '__sticker__', channelId: '__sticker__',
authorId: user.id authorId: user.id
}) })
span.end({
guildId,
attachmentId: att?.id || null,
spanKind: 'sticker.stage',
activeChannelId: this.activeChannelId
})
return att
} catch (err) {
this.log.error('sticker.stage error', {
guildId,
filename: filename || null,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
} }
async upsertGuildSticker ({ name, description, attachmentId, image, packName }) { async upsertGuildSticker ({ name, description, attachmentId, image, packName }) {
@@ -9186,7 +9213,12 @@ class PearcordPlatform extends EventEmitter {
meta: { name: row.name } meta: { name: row.name }
}) })
this.emit('guild-sticker', row) this.emit('guild-sticker', row)
span.end({ name: row.name, guildId }) span.end({
name: row.name,
guildId,
spanKind: 'sticker.create',
activeChannelId: this.activeChannelId
})
return row return row
} catch (err) { } catch (err) {
this.log.error('sticker.create error', { this.log.error('sticker.create error', {
@@ -9200,6 +9232,9 @@ class PearcordPlatform extends EventEmitter {
} }
async removeGuildSticker (name) { async removeGuildSticker (name) {
const guildId = this.guild?.guild?.id || null
const span = this.log.time('sticker.delete', { name: name || null, guildId })
try {
if (!this.guild?.guild) throw new Error('no guild') if (!this.guild?.guild) throw new Error('no guild')
const user = this.identity.user const user = this.identity.user
if (!user) throw new Error('register first') if (!user) throw new Error('register first')
@@ -9221,7 +9256,22 @@ class PearcordPlatform extends EventEmitter {
meta: { name: removed.name } meta: { name: removed.name }
}) })
this.emit('guild-sticker-delete', payload) this.emit('guild-sticker-delete', payload)
span.end({
name: removed.name,
guildId,
spanKind: 'sticker.delete',
activeChannelId: this.activeChannelId
})
return removed return removed
} catch (err) {
this.log.error('sticker.delete error', {
name: name || null,
guildId,
error: err?.message || String(err)
})
span.fail(err)
throw err
}
} }
async upsertStickerPack ({ async upsertStickerPack ({