dsh-atlassian-plugin 0.0.0-stage → 0.3.2

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.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/index.ts", "../../integration-ui/src/card/definition.ts", "../../integration-ui/src/styles/styles.css.ts", "../../integration-ui/src/card/tail.tsx", "../../integration-ui/src/fact.tsx", "../../integration-ui/src/host-api.ts", "../../integration-ui/src/panel/body.tsx", "../../integration-ui/src/panel/definition.ts", "../../integration-ui/src/panel/open.ts", "../../integration-ui/src/panel/title.tsx", "../../integration-ui/src/settings/section.tsx", "../../integration-ui/src/settings/tab.ts", "../../integration-ui/src/styles/runtime.ts", "../../integration-ui/src/tool/row.tsx", "../../mcp-oauth/src/tool-name.ts", "../src/shared/tool-names.ts", "../src/shared/presentation.ts", "../src/shared/tone.ts", "../src/client/sidebar/definition.ts", "../src/client/sidebar/open.ts", "../src/client/styles/styles.css.ts", "../src/client/components/issue-item.tsx", "../src/client/components/page-item.tsx", "../src/client/components/presentation-card.tsx", "../src/client/conversation/presentation-definition.ts", "../src/client/components/presentation-tail.tsx", "../src/client/host-api.ts", "../src/client/components/settings-section.tsx", "../src/shared/meta.ts", "../src/client/components/tool-row.tsx", "../src/client/plugin-id.ts", "../src/client/sidebar/panel.tsx", "../src/shared/panel.ts", "../src/client/styles/styles-runtime.ts"],
4
+ "sourcesContent": ["/**\n * dsh-atlassian \u2014 the Web Client half.\n *\n * It contributes four things to the page:\n * - one tab of the suite's single **Integrations** page in Settings, with the\n * sign-in state and the button that starts the OAuth flow in the host;\n * - one keyed tool view per known Atlassian tool, so a Jira search or issue\n * read renders as cards instead of raw JSON;\n * - a turn tail seat, so `atlassian_present` puts its card under the agent's\n * answer rather than inside the collapsible tool group;\n * - a right-Sidebar panel, where a click on a card opens the whole issue or\n * page and the actions that change it.\n *\n * The seats themselves \u2014 the panel body, the card, the tool row, the settings\n * card, and the stylesheet they are drawn with \u2014 come from\n * `dsh-integration-ui`; this half says what is Atlassian's and registers each\n * seat under this plugin's own tab kind and tool names. The settings card is one\n * tab of a page another plugin owns, which is what keeps five integrations from\n * becoming five entries in the Settings navigation.\n *\n * The bundle is built into the client module system's lazy factory format, so\n * this module's exports are the Cordis plugin the loader hands to the tree.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\n// Each import below carries a declaration this half needs: the slot registry\n// itself, the slot contracts, the Chat node kind registry, and the right\n// Sidebar's tab-type registry.\nimport type {} from \"@deepseek-ai/dsh-client-ui-chat/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-renderer/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-tool/client\";\nimport { registerIntegrationsTab } from \"dsh-integration-ui\";\nimport { PUBLIC_TOOL_NAMES } from \"../shared/tool-names\";\nimport { PresentationTail } from \"./components/presentation-tail\";\nimport { AtlassianSection } from \"./components/settings-section\";\nimport { AtlassianToolRow } from \"./components/tool-row\";\nimport { atlassianPresentation } from \"./conversation/presentation-definition\";\nimport { PLUGIN_ID } from \"./plugin-id\";\nimport { PANEL_ID, panelDefinition } from \"./sidebar/definition\";\nimport { installPanelOpener } from \"./sidebar/open\";\nimport { AtlassianPanel, AtlassianPanelTitle } from \"./sidebar/panel\";\nimport { installAtlassianStyles } from \"./styles/styles-runtime\";\n\n/** The client services this half needs. */\nexport const inject = [\"slots\", \"uiConversation\"];\n\n/**\n * Register the section, the tool views, the presentation cards, and the panel.\n * @param ctx - the browser Cordis context carrying the slot registry.\n */\nexport const apply = (ctx: Context): void => {\n\t// The compiled stylesheet is inlined into this bundle at build time and\n\t// tagged with the plugin id, so turning the plugin off removes it too.\n\tctx.effect(() => installAtlassianStyles(), \"atlassian: stylesheet\");\n\n\t// The card's payload arrives as a durable session record; this definition\n\t// turns it into a Chat node the turn tail can select.\n\tctx.uiConversation.events.register(atlassianPresentation.definition);\n\n\t// Cards open the panel through this, and it is a no-op in a build without\n\t// one: the click then stays with the browser.\n\tinstallPanelOpener(ctx);\n\n\t// The Sidebar's tab registry may not be composed at all, and this plugin\n\t// must not wait for it: everything else it contributes \u2014 the settings\n\t// section, the tool rows, the cards \u2014 has to work either way.\n\tctx.inject([\"sidebarRightTabs\"], (scoped) => {\n\t\tscoped.effect(\n\t\t\t() => scoped.sidebarRightTabs.register(panelDefinition()),\n\t\t\t\"atlassian: panel type\",\n\t\t);\n\n\t\tscoped.slots.inject(\"sidebar.right.pane.tab\", () =>\n\t\t\tscoped.slots.register(\n\t\t\t\t{ name: \"sidebar.right.pane.tab\", key: PANEL_ID },\n\t\t\t\tAtlassianPanel,\n\t\t\t),\n\t\t);\n\n\t\tscoped.slots.inject(\"sidebar.right.pane.tab.title\", () =>\n\t\t\tscoped.slots.register(\n\t\t\t\t{ name: \"sidebar.right.pane.tab.title\", key: PANEL_ID },\n\t\t\t\tAtlassianPanelTitle,\n\t\t\t),\n\t\t);\n\t});\n\n\t// The card is one tab of the suite's single Integrations page. The helper\n\t// waits for that page to be composed, so a build without it leaves the tools\n\t// and the panel working and the card with nowhere to appear.\n\tregisterIntegrationsTab(\n\t\tctx,\n\t\t{ id: \"atlassian\", order: 10, label: \"Atlassian\" },\n\t\tAtlassianSection,\n\t);\n\n\tctx.slots.inject(\"tool.call.toolview\", () => {\n\t\tconst disposers = PUBLIC_TOOL_NAMES.map((name) =>\n\t\t\tctx.slots.register(\n\t\t\t\t{ name: \"tool.call.toolview\", key: name },\n\t\t\t\tAtlassianToolRow,\n\t\t\t),\n\t\t);\n\n\t\treturn () => {\n\t\t\tfor (const dispose of disposers) dispose();\n\t\t};\n\t});\n\n\t// Under the closing prose of the turn, beside the delivered-file cards.\n\tctx.slots.inject(\"conversation.chat.turnTail\", () =>\n\t\tctx.slots.register(\n\t\t\t{\n\t\t\t\tname: \"conversation.chat.turnTail\",\n\t\t\t\tid: PLUGIN_ID,\n\t\t\t\torder: 20,\n\t\t\t},\n\t\t\tPresentationTail,\n\t\t),\n\t);\n};\n", "/**\n * The turn-scoped card one integration's `present` tool shows.\n *\n * This definition publishes the card the tool asked to show against its Turn, so\n * the turn tail renders it under the closing prose. Nothing extra is written to\n * the session: the card is narrowed from the tool result's persisted\n * `presentationMeta`, which means Session-log replay reproduces it exactly, with\n * no host-side record and no extra durable vocabulary.\n *\n * The call's own Tool-group cell stays with the generic keyed tool view, so this\n * module contributes only the turn-level card.\n */\n\nimport type {\n\tConversationLocationData,\n\tConversationMatch,\n\tConversationNodeDefinition,\n\tConversationTurnDataMap,\n\tTurnLocation,\n} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type { CardProvider } from \"./types\";\n\n/** One card plus the log position it settled at. */\nexport interface PresentedCard<TCard> {\n\treadonly card: TCard;\n\treadonly seq: number;\n}\n\n/** Immutable cards published against one Turn. */\nexport interface PresentationTurnData<TCard> {\n\treadonly presentations: readonly PresentedCard<TCard>[];\n}\n\n/**\n * Turn-tail owner currency this seat reads.\n *\n * Structurally equal to ui-chat's `TurnTailOwnerProps`; the fields are named\n * locally so this module depends only on the conversation contract.\n */\nexport interface PresentationTurnOwner {\n\treadonly turn: TurnLocation;\n\treadonly seq: number;\n}\n\n/** One in-window root call head, kept so its result can be attributed. */\ninterface PresentCall {\n\treadonly name: string;\n}\n\n/** The state the definition accumulates for one Turn. */\nexport interface PresentationTurnState<TCard> {\n\treadonly turn: number;\n\treadonly calls: ReadonlyMap<string, PresentCall>;\n\treadonly presentations: readonly PresentedCard<TCard>[];\n}\n\n/** A location value this definition published earlier, read back for identity. */\ninterface PriorTurnData<TCard> {\n\treadonly kind: string;\n\treadonly turn: number;\n\treadonly key: string;\n\treadonly value: PresentationTurnData<TCard>;\n}\n\n/** What one integration's card is, on the wire and on the page. */\nexport interface PresentationSpec<\n\tTCard,\n\tK extends Extract<keyof ConversationTurnDataMap, string>,\n\tTOwner = unknown,\n> {\n\t/** The Turn-data key this card publishes under. */\n\treadonly turnDataKey: K;\n\t/** The wire name whose settled result carries one card. */\n\treadonly toolName: string;\n\t/**\n\t * How many of this kind's cards one Turn keeps.\n\t *\n\t * `all` (the default) is for a card that shows a *thing* the reader asked to\n\t * see: two searches in one Turn are two answers, and each keeps its place.\n\t * `last` is for a card that reports a *state*: a second run supersedes the\n\t * first, and a wall of them buries the one that is current.\n\t */\n\treadonly keep?: \"all\" | \"last\";\n\t/** Narrow one tool result's `meta`. */\n\tparse(value: unknown): TCard | undefined;\n\t/** How the card draws itself. */\n\treadonly card: CardProvider<TCard, TOwner>;\n}\n\n/** One integration's card, as its plugin registers and renders it. */\nexport interface PresentationType<TCard, TOwner = unknown> {\n\t/** The definition the conversation registry takes. */\n\treadonly definition: ConversationNodeDefinition<PresentationTurnState<TCard>>;\n\t/** The cards one closing Turn asked to show. */\n\tselect(owner: PresentationTurnOwner): PresentationTurnData<TCard> | null;\n\t/** How the card draws itself. */\n\treadonly card: CardProvider<TCard, TOwner>;\n}\n\n/** The tool-call id a settled result answers, when the event carries one. */\nconst resultCallId = (match: ConversationMatch): string | undefined => {\n\tif (match.event.type !== \"tool/result\") return undefined;\n\n\tconst source = match.event.data.message.source as { callId?: unknown };\n\treturn typeof source.callId === \"string\" ? source.callId : undefined;\n};\n\n/**\n * Build one integration's card definition and its turn-tail reader.\n * @param spec - the wire name, the Turn-data key, the payload narrowing, and the card's own drawing rules.\n */\nexport const createPresentationType = <\n\tTCard,\n\tK extends Extract<keyof ConversationTurnDataMap, string>,\n\tTOwner = unknown,\n>(\n\tspec: PresentationSpec<TCard, K, TOwner>,\n): PresentationType<TCard, TOwner> => {\n\t/**\n\t * Select the cards one Turn asked to show.\n\t *\n\t * The bound is the Turn's own end rather than the closing Assistant text, so\n\t * a card recorded after a failed request or a user stop still belongs to its\n\t * Turn.\n\t */\n\tconst select = (\n\t\towner: PresentationTurnOwner,\n\t): PresentationTurnData<TCard> | null => {\n\t\tconst data = owner.turn.data.get(spec.turnDataKey) as\n\t\t\t| Readonly<PresentationTurnData<TCard>>\n\t\t\t| undefined;\n\t\tif (data === undefined) return null;\n\n\t\tconst bound = owner.turn.end?.seq ?? owner.seq;\n\t\tconst presentations = data.presentations.filter(\n\t\t\t(presentation) => presentation.seq <= bound,\n\t\t);\n\n\t\treturn presentations.length === 0 ? null : { presentations };\n\t};\n\n\tconst definition: ConversationNodeDefinition<PresentationTurnState<TCard>> = {\n\t\tkind: spec.turnDataKey,\n\t\tmatch: (event) => {\n\t\t\tif (event.type === \"turn/start\")\n\t\t\t\treturn { id: String(event.data.turn), role: \"start\" };\n\n\t\t\t// Every call head is remembered, so a result can be attributed to its\n\t\t\t// tool: the result itself carries only the call id, not the name.\n\t\t\tif (event.type === \"tool/call\" || event.type === \"tool/result\")\n\t\t\t\treturn { id: String(event.data.turn), role: \"update\" };\n\n\t\t\treturn null;\n\t\t},\n\t\tstart: (_context, match) => {\n\t\t\tif (match.event.type !== \"turn/start\")\n\t\t\t\tthrow new Error(`${spec.turnDataKey} start requires turn/start`);\n\n\t\t\treturn {\n\t\t\t\tturn: match.event.data.turn,\n\t\t\t\tcalls: new Map<string, PresentCall>(),\n\t\t\t\tpresentations: [],\n\t\t\t};\n\t\t},\n\t\tupdate: (context, match) => {\n\t\t\tif (match.event.type === \"tool/call\") {\n\t\t\t\tconst calls = new Map(context.state.calls);\n\t\t\t\tcalls.set(String(match.event.data.callId), {\n\t\t\t\t\tname: match.event.data.name,\n\t\t\t\t});\n\n\t\t\t\treturn { ...context.state, calls };\n\t\t\t}\n\n\t\t\tif (match.event.type !== \"tool/result\") return context.state;\n\t\t\tif (match.event.data.message.isError === true) return context.state;\n\n\t\t\tconst callId = resultCallId(match);\n\t\t\tif (callId === undefined) return context.state;\n\t\t\tif (context.state.calls.get(callId)?.name !== spec.toolName)\n\t\t\t\treturn context.state;\n\n\t\t\tconst card = spec.parse(match.event.data.meta);\n\t\t\tif (card === undefined) return context.state;\n\n\t\t\tconst present = { card, seq: match.event.seq };\n\n\t\t\treturn {\n\t\t\t\t...context.state,\n\t\t\t\tpresentations:\n\t\t\t\t\tspec.keep === \"last\"\n\t\t\t\t\t\t? [present]\n\t\t\t\t\t\t: [...context.state.presentations, present],\n\t\t\t};\n\t\t},\n\t\tbuildLocationData: (context, scope, previous) => {\n\t\t\tif (scope !== \"turn\" || context.state === undefined) return null;\n\n\t\t\tconst prior = previous as PriorTurnData<TCard> | null;\n\n\t\t\tif (\n\t\t\t\tprior?.kind === \"turn\" &&\n\t\t\t\tprior.turn === context.state.turn &&\n\t\t\t\tprior.key === spec.turnDataKey &&\n\t\t\t\tprior.value.presentations === context.state.presentations\n\t\t\t)\n\t\t\t\treturn previous;\n\n\t\t\t// The key belongs to the plugin, and only its declaration-merged map\n\t\t\t// entry types the value under it; the library cannot name that entry.\n\t\t\treturn {\n\t\t\t\tkind: \"turn\",\n\t\t\t\tturn: context.state.turn,\n\t\t\t\tkey: spec.turnDataKey,\n\t\t\t\tvalue: { presentations: context.state.presentations },\n\t\t\t} as unknown as ConversationLocationData;\n\t\t},\n\t};\n\n\treturn { definition, select, card: spec.card };\n};\n", "export var actions = '_9d1h6n8';\nexport var badges = '_9d1h6n6';\nexport var caption = '_9d1h6n7';\nexport var card = '_9d1h6n1';\nexport var cardMeta = '_9d1h6nv';\nexport var code = '_9d1h6no';\nexport var error = '_9d1h6np';\nexport var factInline = '_9d1h6nf';\nexport var factInlineLabel = '_9d1h6ng';\nexport var factLabel = '_9d1h6nc';\nexport var factValue = '_9d1h6nd';\nexport var facts = '_9d1h6nb';\nexport var factsInline = '_9d1h6ne';\nexport var field = '_9d1h6na';\nexport var head = '_9d1h6n2';\nexport var item = '_9d1h6ni';\nexport var itemHead = '_9d1h6nj';\nexport var itemLink = '_9d1h6nl';\nexport var itemTitle = '_9d1h6nk';\nexport var link = '_9d1h6nn';\nexport var list = '_9d1h6nh';\nexport var mono = '_9d1h6n19';\nexport var panel = '_9d1h6nz';\nexport var panelHead = '_9d1h6n12';\nexport var panelKey = '_9d1h6n15';\nexport var panelLoading = '_9d1h6n11';\nexport var panelScroll = '_9d1h6n10';\nexport var panelSection = '_9d1h6n17';\nexport var panelSectionTitle = '_9d1h6n18';\nexport var panelSummary = '_9d1h6n16';\nexport var panelTitleRow = '_9d1h6n14';\nexport var presentation = '_9d1h6nr';\nexport var presentationCount = '_9d1h6nu';\nexport var presentationHead = '_9d1h6ns';\nexport var presentationTitle = '_9d1h6nt';\nexport var presentations = '_9d1h6nq';\nexport var query = '_9d1h6nw';\nexport var row = '_9d1h6n9';\nexport var rowButton = '_9d1h6nm';\nexport var section = '_9d1h6n0';\nexport var state = '_9d1h6n4';\nexport var stateWord = '_9d1h6n5';\nexport var tabs = '_9d1h6n13';\nexport var title = '_9d1h6n3';\nexport var toolLabel = '_9d1h6ny';\nexport var toolRow = '_9d1h6nx';", "/**\n * The cards one turn contributes, under the closing text of its turn.\n *\n * A turn tail is the right seat for this: a card is an answer-shaped artifact\n * rather than a step in the work, so it belongs beneath the prose, outside the\n * collapsible tool group \u2014 the same place `present` puts its file cards.\n *\n * The seat renders for every completed turn and narrows its own turn here, so\n * two cards shown in one turn both render, in call order.\n */\n\nimport type {} from \"@deepseek-ai/dsh-client-ui-chat/client\";\nimport type { PropsRuntime } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport type { ReactNode } from \"react\";\nimport * as styles from \"../styles/styles.css\";\nimport type { PresentationType } from \"./definition\";\n\n/** Past this many rows a card scrolls instead of growing without limit. */\nconst SCROLL_AFTER = 4;\n\n/**\n * Build the turn-tail seat for one integration.\n * @param type - the card definition, its turn reader, and its drawing rules.\n * @returns the component the plugin registers in `conversation.chat.turnTail`.\n */\nexport const createPresentationTail = <TCard, TOwner = unknown>(\n\ttype: PresentationType<TCard, TOwner>,\n): ((props: PropsRuntime<\"conversation.chat.turnTail\">) => ReactNode) => {\n\tconst Tail = (\n\t\tprops: PropsRuntime<\"conversation.chat.turnTail\">,\n\t): ReactNode => {\n\t\tconst matched = type.select(props);\n\n\t\tif (matched === null) return null;\n\n\t\treturn (\n\t\t\t<div className={styles.presentations}>\n\t\t\t\t{matched.presentations.map((presentation) => {\n\t\t\t\t\tconst card = presentation.card;\n\t\t\t\t\tconst callId = type.card.callId(card);\n\t\t\t\t\tconst title = type.card.title(card);\n\t\t\t\t\tconst meta = type.card.meta?.(card, props as TOwner);\n\t\t\t\t\tconst footer = type.card.footer?.(card, props as TOwner);\n\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<section\n\t\t\t\t\t\t\tkey={callId}\n\t\t\t\t\t\t\tclassName={styles.presentation}\n\t\t\t\t\t\t\tdata-integration-card={callId}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<div className={styles.presentationHead}>\n\t\t\t\t\t\t\t\t{title === undefined ? null : (\n\t\t\t\t\t\t\t\t\t<span className={styles.presentationTitle}>{title}</span>\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t\t<span className={styles.presentationCount}>\n\t\t\t\t\t\t\t\t\t{type.card.count(card)}\n\t\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{meta}\n\n\t\t\t\t\t\t\t<ul\n\t\t\t\t\t\t\t\tclassName={styles.list}\n\t\t\t\t\t\t\t\tdata-layout={type.card.layout(card)}\n\t\t\t\t\t\t\t\tdata-scrollable={\n\t\t\t\t\t\t\t\t\ttype.card.length(card) > SCROLL_AFTER ? \"true\" : undefined\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t{type.card.items(card, props as TOwner)}\n\t\t\t\t\t\t\t</ul>\n\n\t\t\t\t\t\t\t{footer}\n\t\t\t\t\t\t</section>\n\t\t\t\t\t);\n\t\t\t\t})}\n\t\t\t</div>\n\t\t);\n\t};\n\n\treturn Tail;\n};\n", "/**\n * The named facts about one item, and the coloured value that is not a fact.\n *\n * A panel's metadata is mostly a list of fields the reader scans rather than\n * reads: who it is assigned to, when it was last seen, how many times it fired.\n * Stacked as chips that list becomes a wall of boxes, so a fact is a row \u2014\n * a tertiary label and a primary value \u2014 and the same component serves a card in\n * Settings and an item in the Sidebar.\n *\n * A fact without a value renders nothing, so a caller lists every field it knows\n * about without branching on each one. What keeps a chip is the value whose\n * colour is the information: a state, a priority, a draft marker.\n *\n * `Facts` draws the grid; `Chip` is one coloured value, optionally named.\n */\n\nimport type { TagTone } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { Tag } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport { Fragment, type ReactNode } from \"react\";\nimport * as styles from \"./styles/styles.css\";\n\n/** One field: its name, and what the provider knows about it. */\nexport interface FactItem {\n\t/** The field's name, as the provider words it (\"Assignee\", \"Last seen\"). */\n\treadonly label: string;\n\t/** The value; a node when it is a link. Absence drops the row. */\n\treadonly value?: ReactNode;\n}\n\n/** Whether a fact has anything to show. */\nconst hasValue = (item: FactItem): boolean =>\n\titem.value !== undefined &&\n\titem.value !== null &&\n\titem.value !== \"\" &&\n\t// React collapses a fragment of nulls to nothing; an empty array is the same\n\t// answer from a provider that built its rows conditionally.\n\t!(Array.isArray(item.value) && item.value.length === 0);\n\n/**\n * How a set of facts is laid out.\n *\n * `rows` is for one item read on its own \u2014 a panel, a settings card: the values\n * line up in a column. `inline` is for an item that is one entry of a list, where\n * the fields are a caption under the title and a column of two-cell rows would\n * push the next entry off the screen.\n */\nexport type FactsLayout = \"rows\" | \"inline\";\n\n/**\n * Render one item's named fields as a label-and-value list.\n * @param props.items - the fields, in the order the reader should scan them.\n * @param props.layout - a column of rows, or one wrapping line.\n * @returns the list, or nothing when no field has a value.\n */\nexport const Facts = ({\n\titems,\n\tlayout = \"rows\",\n}: {\n\treadonly items: readonly FactItem[];\n\treadonly layout?: FactsLayout;\n}) => {\n\tconst shown = items.filter(hasValue);\n\n\tif (shown.length === 0) return null;\n\n\tif (layout === \"inline\") {\n\t\treturn (\n\t\t\t<ul className={styles.factsInline}>\n\t\t\t\t{shown.map((item) => (\n\t\t\t\t\t<li className={styles.factInline} key={item.label}>\n\t\t\t\t\t\t<span className={styles.factInlineLabel}>{item.label}</span>\n\t\t\t\t\t\t<span className={styles.factValue}>{item.value}</span>\n\t\t\t\t\t</li>\n\t\t\t\t))}\n\t\t\t</ul>\n\t\t);\n\t}\n\n\treturn (\n\t\t<dl className={styles.facts}>\n\t\t\t{shown.map((item) => (\n\t\t\t\t<Fragment key={item.label}>\n\t\t\t\t\t<dt className={styles.factLabel}>{item.label}</dt>\n\t\t\t\t\t<dd className={styles.factValue}>{item.value}</dd>\n\t\t\t\t</Fragment>\n\t\t\t))}\n\t\t</dl>\n\t);\n};\n\ninterface ChipProps {\n\t/** The field's name, when the value needs one (\"Priority: P2\"). */\n\treadonly label?: string;\n\treadonly value?: string;\n\t/** Which palette the value earns. */\n\treadonly tone?: TagTone;\n}\n\n/**\n * One coloured value.\n *\n * With a `label` it reads as a named field; without one it is the value itself,\n * which is how a state becomes a coloured chip instead of another \"State: \u2026\".\n */\nexport const Chip = ({ label, value, tone = \"outline\" }: ChipProps) => {\n\tif (value === undefined || value === \"\") return null;\n\n\treturn (\n\t\t<Tag tone={tone}>{label === undefined ? value : `${label}: ${value}`}</Tag>\n\t);\n};\n", "/**\n * The browser half's channel to a plugin's host half.\n *\n * Both run on the same loopback origin, so the settings card and the side panel\n * reach the host through the plugin's own named route with ordinary same-origin\n * requests. Every call answers with JSON; a failed call answers with `{ error }`,\n * which this turns back into the message the user sees.\n */\n\ntype Method = \"GET\" | \"POST\";\n\n/** One request into a plugin's host route. */\nexport type HostRequest = <T>(\n\tpath: string,\n\tmethod: Method,\n\tbody?: unknown,\n\tsignal?: AbortSignal,\n) => Promise<T>;\n\n/**\n * Build the request function one integration's host API is written on.\n * @param basePath - the route prefix the plugin registered, such as `/dsh-sentry`.\n */\nexport const createHostRequest = (basePath: string): HostRequest => {\n\t/** The host's own words about why a call failed. */\n\tconst failureOf = async (response: Response): Promise<string> => {\n\t\ttry {\n\t\t\tconst body: unknown = await response.json();\n\n\t\t\tif (\n\t\t\t\tbody !== null &&\n\t\t\t\ttypeof body === \"object\" &&\n\t\t\t\ttypeof (body as { error?: unknown }).error === \"string\"\n\t\t\t)\n\t\t\t\treturn (body as { error: string }).error;\n\t\t} catch {\n\t\t\t// Not JSON: the status line is all this can say.\n\t\t}\n\n\t\treturn `host answered ${response.status} ${response.statusText}`;\n\t};\n\n\treturn async <T>(\n\t\tpath: string,\n\t\tmethod: Method,\n\t\tbody?: unknown,\n\t\tsignal?: AbortSignal,\n\t): Promise<T> => {\n\t\tconst response = await fetch(`${basePath}${path}`, {\n\t\t\tmethod,\n\t\t\theaders:\n\t\t\t\tbody === undefined\n\t\t\t\t\t? { accept: \"application/json\" }\n\t\t\t\t\t: { accept: \"application/json\", \"content-type\": \"application/json\" },\n\t\t\t...(body === undefined ? {} : { body: JSON.stringify(body) }),\n\t\t\t...(signal === undefined ? {} : { signal }),\n\t\t});\n\n\t\tif (!response.ok) throw new Error(await failureOf(response));\n\n\t\treturn (await response.json()) as T;\n\t};\n};\n", "/**\n * The shared side-panel body.\n *\n * The body is a right-Sidebar tab of the integration's own kind, so it renders\n * inside the harness's panel and follows its theme. It reads what to show from\n * its tab's navigation parameters \u2014 the Sidebar hands those to every body \u2014 and\n * fetches the document through the plugin's own host route, because only the\n * host half holds the MCP connection.\n *\n * Writes are the same channel, one step at a time: run it, and the host answers\n * with the document as it now stands, so the panel never renders an assumption\n * about what a change did.\n */\n\nimport {\n\tButton,\n\tMarkdownDelegateProvider,\n\tStateDot,\n\tTextShimmer,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\nimport type { PropsRuntime } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport type { ReactNode } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport * as styles from \"../styles/styles.css\";\nimport type { PanelActions, PanelProvider, PanelWrite } from \"./types\";\n\n/** What the panel currently knows. */\ntype Load<TData, TParams> =\n\t| { readonly status: \"loading\" }\n\t| { readonly status: \"ready\"; readonly data: TData; readonly params: TParams }\n\t| { readonly status: \"error\"; readonly message: string };\n\n/** The reason inside an unknown thrown value, as a sentence. */\nconst messageOf = (error: unknown): string =>\n\terror instanceof Error ? error.message : String(error);\n\n/**\n * Build the body seat for one integration.\n * @param provider - everything that is the integration's rather than the body's.\n * @returns the component the plugin registers under its own tab id.\n */\nexport const createPanelBody = <TData, TParams>(\n\tprovider: PanelProvider<TData, TParams>,\n): ((props: PropsRuntime<\"sidebar.right.pane.tab\">) => ReactNode) => {\n\tconst Panel = (props: PropsRuntime<\"sidebar.right.pane.tab\">): ReactNode => {\n\t\tconst { tab } = props.useTabInfo();\n\t\tconst params = provider.parseParams(tab.navigation.params);\n\t\tconst revision = tab.navigation.revision;\n\t\tconst identity = params === undefined ? \"\" : provider.identity(params);\n\n\t\tconst [load, setLoad] = useState<Load<TData, TParams>>({\n\t\t\tstatus: \"loading\",\n\t\t});\n\t\tconst [failure, setFailure] = useState<string | undefined>(undefined);\n\t\tconst [busy, setBusy] = useState(false);\n\n\t\t// The effect below is keyed by identity, so the fetch reads the target from a\n\t\t// ref rather than closing over one render's copy of it.\n\t\tconst current = useRef<TParams | undefined>(params);\n\t\tcurrent.current = params;\n\n\t\tconst fetchPanel = useCallback(\n\t\t\tasync (signal?: AbortSignal): Promise<void> => {\n\t\t\t\tconst wanted = current.current;\n\n\t\t\t\tif (wanted === undefined) {\n\t\t\t\t\tsetLoad({ status: \"error\", message: provider.emptyMessage });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsetLoad({ status: \"loading\" });\n\n\t\t\t\ttry {\n\t\t\t\t\tconst data = provider.parse(await provider.fetch(wanted, signal));\n\n\t\t\t\t\tif (data === undefined)\n\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\"the host answered with a document this version cannot draw\",\n\t\t\t\t\t\t);\n\t\t\t\t\tif (signal?.aborted !== true)\n\t\t\t\t\t\tsetLoad({ status: \"ready\", data, params: wanted });\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (signal?.aborted !== true)\n\t\t\t\t\t\tsetLoad({ status: \"error\", message: messageOf(error) });\n\t\t\t\t}\n\t\t\t},\n\t\t\t[],\n\t\t);\n\n\t\t// `identity` is what to show and `revision` is \"navigated again\"; the fetch\n\t\t// reads the target from a ref, so the effect body names neither of them.\n\t\t// biome-ignore lint/correctness/useExhaustiveDependencies: both key the refetch\n\t\tuseEffect(() => {\n\t\t\tconst controller = new AbortController();\n\t\t\tsetFailure(undefined);\n\t\t\tvoid fetchPanel(controller.signal);\n\n\t\t\treturn () => {\n\t\t\t\tcontroller.abort();\n\t\t\t};\n\t\t}, [identity, revision, fetchPanel]);\n\n\t\t/** One write, then the truth about what it did. */\n\t\tconst run = useCallback(\n\t\t\t(write: PanelWrite<TParams>): void => {\n\t\t\t\tconst wanted = current.current;\n\t\t\t\tif (wanted === undefined) return;\n\n\t\t\t\tsetBusy(true);\n\t\t\t\tsetFailure(undefined);\n\n\t\t\t\twrite(wanted)\n\t\t\t\t\t.then((answer) => {\n\t\t\t\t\t\tconst data = provider.parse(answer);\n\n\t\t\t\t\t\tif (data === undefined)\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\"the host answered with a document this version cannot draw\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tsetLoad({ status: \"ready\", data, params: wanted });\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error: unknown) => {\n\t\t\t\t\t\tsetFailure(messageOf(error));\n\t\t\t\t\t\t// The write may have failed after the host changed nothing; asking\n\t\t\t\t\t\t// again is what tells the two apart.\n\t\t\t\t\t\tvoid fetchPanel();\n\t\t\t\t\t})\n\t\t\t\t\t.finally(() => {\n\t\t\t\t\t\tsetBusy(false);\n\t\t\t\t\t});\n\t\t\t},\n\t\t\t[fetchPanel],\n\t\t);\n\n\t\tconst actions: PanelActions<TParams> = { busy, run };\n\n\t\treturn (\n\t\t\t<div className={styles.panel}>\n\t\t\t\t<div className={styles.panelScroll}>\n\t\t\t\t\t{load.status === \"loading\" ? (\n\t\t\t\t\t\t<div\n\t\t\t\t\t\t\tclassName={styles.panelLoading}\n\t\t\t\t\t\t\trole=\"status\"\n\t\t\t\t\t\t\taria-live=\"polite\"\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<StateDot state=\"ongoing\" size={20} />\n\n\t\t\t\t\t\t\t<TextShimmer active>Loading\u2026</TextShimmer>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{load.status === \"error\" ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<p className={styles.error}>{load.message}</p>\n\t\t\t\t\t\t\t<div className={styles.actions}>\n\t\t\t\t\t\t\t\t<Button size=\"sm\" onClick={() => void fetchPanel()}>\n\t\t\t\t\t\t\t\t\tTry again\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{failure === undefined ? null : (\n\t\t\t\t\t\t<p className={styles.error}>{failure}</p>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{load.status === \"ready\" ? (\n\t\t\t\t\t\t<MarkdownDelegateProvider\n\t\t\t\t\t\t\t// Markdown links belong to the browser: a click here must not\n\t\t\t\t\t\t\t// navigate the panel itself away from the harness.\n\t\t\t\t\t\t\topenExternalLink={(href) => {\n\t\t\t\t\t\t\t\twindow.open(href, \"_blank\", \"noopener,noreferrer\");\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{provider.view({\n\t\t\t\t\t\t\t\tdata: load.data,\n\t\t\t\t\t\t\t\tparams: load.params,\n\t\t\t\t\t\t\t\tactions,\n\t\t\t\t\t\t\t})}\n\t\t\t\t\t\t</MarkdownDelegateProvider>\n\t\t\t\t\t) : null}\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t);\n\t};\n\n\treturn Panel;\n};\n", "/**\n * One integration's side panel, as a right-Sidebar tab type.\n *\n * A type reaches the Sidebar through its public path only: the definition into\n * `ctx.sidebarRightTabs`, the body into the keyed `sidebar.right.pane.tab` seat,\n * and the chip title into `sidebar.right.pane.tab.title`, both under this\n * definition's `id`. Nothing here reaches into the Sidebar's store or panes \u2014\n * the same two-stage registration a package shipped with the product uses.\n *\n * No `multiple`: one panel per pane. Opening another item navigates the one that\n * is there, which is what makes clicking through a search result feel like\n * following a link rather than opening windows.\n */\n\nimport type { SidebarRightTabDefinition } from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\n\n/** What one integration's tab type says about itself. */\nexport interface PanelTypeSpec {\n\t/** This implementation's identity in the tab system; a package name. */\n\treadonly id: string;\n\t/** The tab kind this plugin owns; what `openTab` names. */\n\treadonly kind: string;\n\t/** The chip's fallback title, until the provider names the item. */\n\treadonly title: string;\n}\n\n/**\n * Build one integration's registry definition; its body and title carry the rest.\n * @param spec - the implementation's identity, its kind, and its fallback title.\n */\nexport const createPanelDefinition = (\n\tspec: PanelTypeSpec,\n): SidebarRightTabDefinition => {\n\treturn {\n\t\tid: spec.id,\n\t\tkind: spec.kind,\n\t\t// A type from outside the product outranks the shipped ones, which is the\n\t\t// band the Sidebar's own documentation reserves for exactly this.\n\t\tpriority: \"extension\",\n\t\ttitle: () => spec.title,\n\t};\n};\n", "/**\n * Opening one integration's side panel from anywhere in the page.\n *\n * The cards do not hold the client context, and the panel belongs to a package\n * that may not be composed at all, so the opener keeps the context the plugin\n * was applied with and resolves the Sidebar's navigation face on every click. A\n * build without the right panel answers `false`, and the caller leaves the click\n * to the browser rather than swallowing it.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type { SidebarRightTabParamsFor } from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\nimport type { MouseEvent } from \"react\";\n\n/** The navigation face one integration's cards open their panel through. */\nexport interface PanelOpener<K extends string> {\n\t/**\n\t * Show one item in the harness's own right panel.\n\t * @param params - what to open.\n\t * @returns whether a panel took it; `false` means there is no panel here.\n\t */\n\topen(params: NonNullable<SidebarRightTabParamsFor<K>>): boolean;\n}\n\n/**\n * Build the opener for one integration's tab kind.\n * @param ctx - the plugin's client context.\n * @param kind - the tab kind this plugin registered.\n */\nexport const createPanelOpener = <K extends string>(\n\tctx: Context,\n\tkind: K,\n): PanelOpener<K> => {\n\treturn {\n\t\topen: (params) => {\n\t\t\tconst sidebar = ctx.get(\"sidebarRight\");\n\t\t\tif (sidebar === undefined) return false;\n\n\t\t\ttry {\n\t\t\t\tsidebar.openTab(kind, { params });\n\t\t\t\treturn true;\n\t\t\t} catch {\n\t\t\t\t// Nothing registered the kind: a wiring mistake inside this plugin, and\n\t\t\t\t// still no reason to eat the user's click.\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t};\n};\n\n/**\n * Whether a click is the user asking for the browser.\n *\n * A modified click, a middle click, or a click on a link that is already handled\n * elsewhere must keep its native behaviour.\n * @param event - the click on a card's link.\n * @returns whether the card should do nothing and let the anchor work.\n */\nexport const wantsBrowser = (event: MouseEvent<HTMLElement>): boolean => {\n\treturn (\n\t\tevent.metaKey ||\n\t\tevent.ctrlKey ||\n\t\tevent.shiftKey ||\n\t\tevent.altKey ||\n\t\tevent.button !== 0\n\t);\n};\n", "/**\n * The panel's chip in the Sidebar's tab strip.\n *\n * The title is read from the tab's own navigation parameters rather than from\n * the document, so the chip says what the panel is showing before \u2014 and even\n * when \u2014 the host has answered.\n */\n\nimport type {} from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\nimport type { PropsRuntime } from \"@deepseek-ai/dsh-client-ui-slots\";\nimport type { ReactNode } from \"react\";\nimport type { PanelProvider } from \"./types\";\n\n/**\n * Build the title seat for one integration.\n * @param provider - everything that is the integration's rather than the body's.\n * @returns the component the plugin registers under its own tab id.\n */\nexport const createPanelTitle = <TData, TParams>(\n\tprovider: PanelProvider<TData, TParams>,\n): ((props: PropsRuntime<\"sidebar.right.pane.tab.title\">) => ReactNode) => {\n\tconst Title = (\n\t\tprops: PropsRuntime<\"sidebar.right.pane.tab.title\">,\n\t): ReactNode => {\n\t\tconst { tab } = props.useTabInfo();\n\t\tconst params = provider.parseParams(tab.navigation.params);\n\n\t\treturn (\n\t\t\t(params === undefined ? undefined : provider.title(params)) ?? tab.title\n\t\t);\n\t};\n\n\treturn Title;\n};\n", "/**\n * The shared settings card.\n *\n * It shows the sign-in state and the connection state, and it is the only place\n * a user has to go to connect: the button starts the OAuth flow in the host,\n * which opens the browser, and this card follows the attempt until it settles.\n *\n * Three kinds of provider share it, and `credentials` says which one this is: a\n * browser flow, a credential the user types, or nothing at all for a server that\n * answers whoever is on the machine. The three are alternatives rather than\n * options, so the type does not let a card carry two of them.\n *\n * The card shows one thing at a time. A signed-in provider reports its state and\n * offers to sign out; the field that replaces its credential appears only when\n * the user asks for it, because a token box beside a working connection reads as\n * an unfinished setup. What the user has to read \u2014 the account, the expiry, the\n * failure \u2014 is a row of facts rather than a row of chips.\n *\n * Everything a provider says about itself is one field of the spec, so the two\n * can never drift apart between integrations; what the provider adds \u2014 the\n * account it works with \u2014 arrives as those facts.\n */\n\nimport { Button, Input, StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { IntegrationStatus } from \"dsh-integration-host/status\";\nimport type { ReactNode } from \"react\";\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport { type FactItem, Facts } from \"../fact\";\nimport * as styles from \"../styles/styles.css\";\n\n/** How often to re-read the host while an attempt is running. */\nconst POLL_MS = 1500;\n\ntype ConnectionState = \"done\" | \"ongoing\" | \"idle\";\n\n/** The operations every settings card drives. */\nexport interface SettingsApi<TStatus extends IntegrationStatus> {\n\t/** Read the current sign-in and connection state. */\n\tstatus(): Promise<TStatus>;\n\t/** Start a sign-in attempt; a token card has no flow to start. */\n\tlogin?(): Promise<TStatus>;\n\t/** Forget the stored credential and withdraw the published tools. */\n\tlogout(): Promise<TStatus>;\n\t/** Verify the stored credential and re-publish the integration's tools. */\n\tsync(): Promise<TStatus>;\n}\n\n/**\n * A credential the user types, for an integration with no browser flow.\n *\n * Some providers have no page to send the user to: a personal access token, a\n * client id and secret the administrator issued. The card then offers a field\n * instead of a sign-in button, and the same status document says whether what\n * was stored works.\n */\nexport interface TokenFieldSpec<TStatus extends IntegrationStatus> {\n\t/** The field's own name, such as \"Personal access token\". */\n\treadonly label: string;\n\treadonly placeholder: string;\n\t/** Where the user gets one, in one sentence. */\n\treadonly hint: string;\n\treadonly saveLabel: string;\n\t/** What the button that opens the field says once a credential is stored. */\n\treadonly replaceLabel: string;\n\t/** What the button that forgets the stored credential says. */\n\treadonly clearLabel: string;\n\t/**\n\t * Store one typed credential and verify it.\n\t * @returns the status as it now stands, error and all.\n\t */\n\tsave(token: string): Promise<TStatus>;\n}\n\n/** What every settings card says, whatever it does to connect. */\ninterface SectionCommon<TStatus extends IntegrationStatus> {\n\treadonly title: string;\n\treadonly blurb: string;\n\t/** What the card says while the first read is in flight. */\n\treadonly checking: string;\n\t/** What the card says when the host half does not answer at all. */\n\treadonly unreachable: string;\n\treadonly syncLabel: string;\n\treadonly api: SettingsApi<TStatus>;\n\t/**\n\t * Rows the provider adds under the blurb, such as the account it works with.\n\t *\n\t * A row without a value renders nothing, so a provider lists every field it\n\t * knows about without branching on each one.\n\t */\n\treadonly details?: (status: TStatus) => readonly FactItem[];\n}\n\n/** A card whose provider signs in through a browser. */\ninterface BrowserSection<TStatus extends IntegrationStatus>\n\textends SectionCommon<TStatus> {\n\treadonly credentials: \"browser\";\n\treadonly signInLabel: string;\n\t/** A browser card has no field: the two are alternatives, not options. */\n\treadonly token?: undefined;\n\t/** Its provider can start a flow, so its api must offer one. */\n\treadonly api: SettingsApi<TStatus> & { login(): Promise<TStatus> };\n}\n\n/** A card whose provider's credential is typed by the user. */\ninterface TokenSection<TStatus extends IntegrationStatus>\n\textends SectionCommon<TStatus> {\n\treadonly credentials: \"typed\";\n\treadonly token: TokenFieldSpec<TStatus>;\n\treadonly signInLabel?: undefined;\n}\n\n/**\n * A card for a provider that needs no credential at all.\n *\n * A local MCP server answers whoever is on the machine, so there is nothing to\n * type and no page to open: the card reports what the connection is doing and\n * offers the same re-check every other card does.\n */\ninterface OpenSection<TStatus extends IntegrationStatus>\n\textends SectionCommon<TStatus> {\n\treadonly credentials: \"none\";\n\treadonly signInLabel?: undefined;\n\treadonly token?: undefined;\n}\n\n/** Everything one integration's settings card says and does. */\nexport type SettingsSectionSpec<TStatus extends IntegrationStatus> =\n\t| BrowserSection<TStatus>\n\t| TokenSection<TStatus>\n\t| OpenSection<TStatus>;\n\n/** Human text for the connection state, for the tooltip and the dot. */\nconst connectionState = (status: IntegrationStatus | null): ConnectionState => {\n\tif (status?.inFlight === true) return \"ongoing\";\n\n\treturn status?.connected === true ? \"done\" : \"idle\";\n};\n\n/** The one word the card prints beside its dot. */\nconst stateText = (\n\tstatus: IntegrationStatus,\n\tcredentials: \"browser\" | \"typed\" | \"none\",\n): string => {\n\tif (status.inFlight === true) return \"Connecting\";\n\n\tif (credentials === \"none\")\n\t\treturn status.connected === true ? \"Connected\" : \"Not connected\";\n\n\treturn status.signedIn === true ? \"Signed in\" : \"Not signed in\";\n};\n\n/**\n * Build the settings section for one integration.\n * @param spec - the integration's copy, its host calls, and what it adds.\n * @returns the component the plugin registers in `integrations.tab`.\n */\nexport const createSettingsSection = <TStatus extends IntegrationStatus>(\n\tspec: SettingsSectionSpec<TStatus>,\n): (() => ReactNode) => {\n\tconst Section = (): ReactNode => {\n\t\tconst mounted = useRef(true);\n\n\t\tconst [status, setStatus] = useState<TStatus | null>(null);\n\t\tconst [failure, setFailure] = useState<string | null>(null);\n\t\t/** Which action is running, so only the button that was pressed says so. */\n\t\tconst [pending, setPending] = useState<string | null>(null);\n\t\tconst [typed, setTyped] = useState(\"\");\n\t\t/** Whether the typed field is open on a card that already holds one. */\n\t\tconst [replacing, setReplacing] = useState(false);\n\n\t\tconst refresh = useCallback(async () => {\n\t\t\ttry {\n\t\t\t\tconst next = await spec.api.status();\n\n\t\t\t\tif (!mounted.current) return;\n\n\t\t\t\tsetStatus(next);\n\t\t\t\tsetFailure(null);\n\t\t\t} catch (error) {\n\t\t\t\tif (!mounted.current) return;\n\n\t\t\t\tsetStatus(null);\n\t\t\t\tsetFailure(error instanceof Error ? error.message : String(error));\n\t\t\t}\n\t\t}, []);\n\n\t\tuseEffect(() => {\n\t\t\tmounted.current = true;\n\t\t\tvoid refresh();\n\n\t\t\treturn () => {\n\t\t\t\tmounted.current = false;\n\t\t\t};\n\t\t}, [refresh]);\n\n\t\t// Follow a running attempt until the host reports it settled.\n\t\tuseEffect(() => {\n\t\t\tif (status?.inFlight !== true) return;\n\n\t\t\tconst timer = setInterval(refresh, POLL_MS);\n\n\t\t\treturn () => clearInterval(timer);\n\t\t}, [status?.inFlight, refresh]);\n\n\t\tconst act = useCallback(\n\t\t\tasync (key: string, action: () => Promise<TStatus>) => {\n\t\t\t\tsetPending(key);\n\n\t\t\t\ttry {\n\t\t\t\t\tconst next = await action();\n\n\t\t\t\t\tif (!mounted.current) return;\n\n\t\t\t\t\tsetStatus(next);\n\t\t\t\t\tsetFailure(null);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tif (!mounted.current) return;\n\n\t\t\t\t\tsetFailure(error instanceof Error ? error.message : String(error));\n\t\t\t\t} finally {\n\t\t\t\t\tif (mounted.current) setPending(null);\n\t\t\t\t}\n\t\t\t},\n\t\t\t[],\n\t\t);\n\n\t\t// No status yet: either the first read is still in flight, or the host half\n\t\t// did not answer. Returning here is what narrows `status` for the card below.\n\t\tconst tokenField = spec.token;\n\n\t\tif (status === null) {\n\t\t\treturn (\n\t\t\t\t<section className={styles.section}>\n\t\t\t\t\t<div className={styles.card}>\n\t\t\t\t\t\t<div className={styles.head}>\n\t\t\t\t\t\t\t<span className={styles.title}>{spec.title}</span>\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t<div className={styles.caption}>\n\t\t\t\t\t\t\t{failure === null ? spec.checking : spec.unreachable}\n\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t{failure === null ? null : (\n\t\t\t\t\t\t\t<div className={styles.code}>{failure}</div>\n\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t<div className={styles.actions}>\n\t\t\t\t\t\t\t<Button variant=\"outline\" onClick={refresh}>\n\t\t\t\t\t\t\t\tTry again\n\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t</div>\n\t\t\t\t</section>\n\t\t\t);\n\t\t}\n\n\t\tconst signedIn = status.signedIn === true;\n\t\tconst waiting = status.inFlight === true;\n\t\tconst toolCount = status.tools.length;\n\t\t// A card for a server that needs no credential has no token to expire, and\n\t\t// says so by never showing the line rather than by showing an empty one.\n\t\tconst expiry =\n\t\t\tsignedIn && spec.credentials !== \"none\" ? status.expiresAt : null;\n\t\t// A field belongs on the card when nothing is stored yet, or when the user\n\t\t// asked to replace what is.\n\t\tconst showField = tokenField !== undefined && (!signedIn || replacing);\n\t\tconst field = spec.token;\n\n\t\t/** The label of one action: the running one says what it is doing. */\n\t\tconst label = (key: string, text: string): string =>\n\t\t\tpending === key ? \"Working\u2026\" : text;\n\n\t\treturn (\n\t\t\t<section className={styles.section}>\n\t\t\t\t<div className={styles.card}>\n\t\t\t\t\t<div className={styles.head}>\n\t\t\t\t\t\t<span className={styles.title}>{spec.title}</span>\n\n\t\t\t\t\t\t<span className={styles.state}>\n\t\t\t\t\t\t\t<StateDot state={connectionState(status)} />\n\n\t\t\t\t\t\t\t<span className={styles.stateWord}>\n\t\t\t\t\t\t\t\t{stateText(status, spec.credentials)}\n\t\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t\t{toolCount === 0 ? null : (\n\t\t\t\t\t\t\t\t<span>{`\u00B7 ${toolCount} tool${toolCount === 1 ? \"\" : \"s\"}`}</span>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t<div className={styles.caption}>{spec.blurb}</div>\n\n\t\t\t\t\t<Facts\n\t\t\t\t\t\titems={[\n\t\t\t\t\t\t\t...(spec.details?.(status) ?? []),\n\t\t\t\t\t\t\t...(expiry === null\n\t\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t\t: [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tlabel: \"Token\",\n\t\t\t\t\t\t\t\t\t\t\tvalue: `valid until ${new Date(expiry).toLocaleString()}`,\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t]),\n\t\t\t\t\t\t]}\n\t\t\t\t\t/>\n\n\t\t\t\t\t{waiting ? (\n\t\t\t\t\t\t<div className={styles.row}>\n\t\t\t\t\t\t\t<StateDot state=\"ongoing\" />\n\n\t\t\t\t\t\t\t<span className={styles.caption}>\n\t\t\t\t\t\t\t\tWaiting for you to approve the sign-in in your browser\u2026\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{status.notice?.url !== undefined ? (\n\t\t\t\t\t\t<div className={styles.row}>\n\t\t\t\t\t\t\t<span className={styles.caption}>{status.notice.message}</span>\n\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\tclassName={styles.link}\n\t\t\t\t\t\t\t\thref={status.notice.url}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\tOpen the sign-in page\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{status.error != null ? (\n\t\t\t\t\t\t<div className={styles.row}>\n\t\t\t\t\t\t\t<span className={styles.error}>{status.error}</span>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{showField && field !== undefined ? (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t<div className={styles.field}>\n\t\t\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\t\t\ttype=\"password\"\n\t\t\t\t\t\t\t\t\tvalue={typed}\n\t\t\t\t\t\t\t\t\tplaceholder={field.placeholder}\n\t\t\t\t\t\t\t\t\taria-label={field.label}\n\t\t\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\t\t\t\tsetTyped(event.target.value);\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t<div className={styles.caption}>{field.hint}</div>\n\t\t\t\t\t\t</>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t<div className={styles.actions}>\n\t\t\t\t\t\t{spec.credentials === \"browser\" ? (\n\t\t\t\t\t\t\tsignedIn ? (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\t\t\tonClick={() => void act(\"logout\", spec.api.logout)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{label(\"logout\", \"Sign out\")}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t\t\t\t\tdisabled={pending !== null || waiting}\n\t\t\t\t\t\t\t\t\tonClick={() => void act(\"login\", spec.api.login)}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{label(\"login\", waiting ? \"Waiting\u2026\" : spec.signInLabel)}\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) : null}\n\n\t\t\t\t\t\t{spec.credentials === \"typed\" && field !== undefined ? (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{showField ? (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"primary\"\n\t\t\t\t\t\t\t\t\t\t\tdisabled={pending !== null || typed.trim() === \"\"}\n\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\tvoid act(\"save\", async () => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tconst next = await field.save(typed);\n\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetTyped(\"\");\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetReplacing(false);\n\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn next;\n\t\t\t\t\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{label(\"save\", field.saveLabel)}\n\t\t\t\t\t\t\t\t\t\t</Button>\n\n\t\t\t\t\t\t\t\t\t\t{signedIn ? (\n\t\t\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetTyped(\"\");\n\t\t\t\t\t\t\t\t\t\t\t\t\tsetReplacing(false);\n\t\t\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tsetReplacing(true);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{field.replaceLabel}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t\t{signedIn ? (\n\t\t\t\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\t\t\t\tdisabled={pending !== null}\n\t\t\t\t\t\t\t\t\t\tonClick={() => void act(\"logout\", spec.api.logout)}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{label(\"logout\", field.clearLabel)}\n\t\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t\t) : null}\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) : null}\n\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={pending !== null || waiting}\n\t\t\t\t\t\t\tonClick={() => void act(\"sync\", spec.api.sync)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{label(\"sync\", spec.syncLabel)}\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</section>\n\t\t);\n\t};\n\n\treturn Section;\n};\n", "/**\n * The seat one integration's settings card occupies.\n *\n * This suite shows one Settings page rather than five: `dsh-integrations-plugin`\n * owns the page and declares `integrations.tab`, and each integration registers\n * the card for its own provider into it. The contract lives here, in the library\n * every integration already depends on, so four plugins name one slot instead of\n * inventing one each.\n *\n * The tab's copy is the registering plugin's, `label` included: the page renders\n * whatever the ledger says, resolved at read time, so a label declared as a thunk\n * follows the active locale without re-registering.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-renderer/client\";\nimport type {\n\tPropsRuntime,\n\tSlotComponent,\n} from \"@deepseek-ai/dsh-client-ui-slots\";\n\ndeclare module \"@deepseek-ai/dsh-client-ui-slots\" {\n\tinterface SlotMap {\n\t\t/**\n\t\t * One integration's card inside the shared Integrations settings page.\n\t\t *\n\t\t * `id` is the tab key and what the page dispatches by, `order` its place\n\t\t * in the strip, and `label` the tab's text.\n\t\t */\n\t\t\"integrations.tab\": {\n\t\t\tkind: \"list\";\n\t\t\tscope: \"root\";\n\t\t};\n\t}\n}\n\n/** What one integration contributes to the shared page. */\nexport interface IntegrationsTabSpec {\n\t/** The integration's key: the tab's id, and what the page dispatches by. */\n\treadonly id: string;\n\t/** Its place in the strip, ascending. */\n\treadonly order: number;\n\t/** The tab's text, or a thunk read per render for one that follows a locale. */\n\treadonly label: string | (() => string);\n}\n\n/**\n * Register one integration's card into the shared Integrations page.\n *\n * The registration waits for the page to be composed, so a build without\n * `dsh-integrations-plugin` leaves the integration's own tools working and its\n * card simply nowhere to appear \u2014 never a plugin that fails to activate.\n * @param ctx - the plugin's own client context.\n * @param spec - the tab's identity in the strip.\n * @param card - the card the tab shows.\n */\nexport const registerIntegrationsTab = (\n\tctx: Context,\n\tspec: IntegrationsTabSpec,\n\tcard: SlotComponent<PropsRuntime<\"integrations.tab\">>,\n): void => {\n\tctx.slots.inject(\"integrations.tab\", () =>\n\t\tctx.slots.register(\n\t\t\t{\n\t\t\t\tname: \"integrations.tab\",\n\t\t\t\tid: spec.id,\n\t\t\t\torder: spec.order,\n\t\t\t\tlabel: spec.label,\n\t\t\t},\n\t\t\tcard,\n\t\t),\n\t);\n};\n", "/**\n * Putting a plugin's compiled stylesheet into the page.\n *\n * vanilla-extract compiles `*.css.ts` to static CSS at build time, but the\n * client module system serves exactly one artifact per package, so there is\n * nowhere to put a stylesheet file. Each plugin's build compiles its CSS first\n * and substitutes its text for its own placeholder, then hands it here.\n *\n * The `data-plugin` tag is what the module system matches on when the plugin is\n * turned off, so the rules leave with it.\n */\n\n/**\n * Add one plugin's stylesheet to the document.\n * @param pluginId - the plugin the rules belong to.\n * @param css - the compiled stylesheet.\n * @returns a disposer that removes it again.\n */\nexport const installStyles = (pluginId: string, css: string): (() => void) => {\n\tconst style = document.createElement(\"style\");\n\tstyle.setAttribute(\"data-plugin\", pluginId);\n\tstyle.textContent = css;\n\n\tdocument.head.append(style);\n\n\treturn () => style.remove();\n};\n", "/**\n * The terse tool row one integration's calls render as.\n *\n * Claiming a tool name in the `tool.call.toolview` slot replaces the generic row\n * for **every** shape of that call \u2014 preparing, running, failed, replayed \u2014 so\n * this component owns all of them.\n *\n * It stays deliberately terse. The server's payload is large, and a tool group\n * that reproduces it buries the answer; the cards belong to the integration's\n * own `present` tool, which puts them where the user is actually reading. What\n * this row adds is a human label, the count, and the query the call resolved.\n *\n * The label is the integration's own words rather than the wire name: a reader\n * watching the work wants \"Project checks\", not `checks`. The wire name stays on\n * the row as its tooltip, which is where somebody debugging a claim looks for it.\n */\n\nimport { StateDot } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { ReactNode } from \"react\";\nimport * as styles from \"../styles/styles.css\";\n\n/** The block shapes a tool row may be handed, narrowed to what it reads. */\nexport interface ToolRowBlock {\n\treadonly argsRaw?: unknown;\n\treadonly call?: { readonly argsRaw?: unknown } | null;\n\treadonly meta?: unknown;\n\treadonly isError?: boolean;\n\treadonly content?: readonly {\n\t\treadonly type?: string;\n\t\treadonly text?: string;\n\t}[];\n}\n\n/** What one integration says about its own calls. */\nexport interface ToolRowSpec {\n\t/**\n\t * What the row leads with, in the reader's words rather than the wire's.\n\t * @param toolName - the name the slot dispatched the call under, for a\n\t * provider that draws several tools with one row.\n\t */\n\tdisplayName(toolName: string | undefined): string;\n\t/** What a preparing call asked for, from its arguments. */\n\tasked?(block: ToolRowBlock | undefined): string | undefined;\n\t/** One short phrase describing what a settled call found. */\n\tsummarize(block: ToolRowBlock | undefined): string;\n\t/**\n\t * What the settled dot says.\n\t *\n\t * A call that answered is usually done, but an integration whose answer\n\t * reports a failure \u2014 a check that did not pass \u2014 says so here.\n\t */\n\tstate?(block: ToolRowBlock | undefined): \"done\" | \"error\";\n}\n\n/** What the tool-view seat hands the row. */\nexport interface ToolRowProps {\n\treadonly phase?: string;\n\treadonly block?: ToolRowBlock;\n\treadonly toolName?: string;\n}\n\n/** The server's own words, as a last resort for a failed call. */\nconst resultText = (block: ToolRowBlock | undefined): string =>\n\t(block?.content ?? [])\n\t\t.filter((item) => item.type === \"text\" && typeof item.text === \"string\")\n\t\t.map((item) => item.text ?? \"\")\n\t\t.join(\"\\n\")\n\t\t.trim();\n\n/**\n * The arguments of a call, when the row can still see them.\n *\n * A preparing call may hold half-written JSON, so a failed parse answers an empty\n * object rather than throwing: what a row says about a call in flight is a\n * courtesy, and every argument it reads is optional anyway.\n * @param block - the block the tool-view seat handed the row.\n * @returns the parsed arguments, or an empty object.\n */\nexport const blockArgs = (\n\tblock: ToolRowBlock | undefined,\n): Record<string, unknown> => {\n\tfor (const raw of [block?.argsRaw, block?.call?.argsRaw]) {\n\t\tif (typeof raw !== \"string\" || raw === \"\") continue;\n\n\t\ttry {\n\t\t\tconst parsed: unknown = JSON.parse(raw);\n\n\t\t\tif (\n\t\t\t\tparsed !== null &&\n\t\t\t\ttypeof parsed === \"object\" &&\n\t\t\t\t!Array.isArray(parsed)\n\t\t\t)\n\t\t\t\treturn parsed as Record<string, unknown>;\n\t\t} catch {\n\t\t\t// A preparing call can hold half-written JSON; the arguments are optional.\n\t\t}\n\t}\n\n\treturn {};\n};\n\n/**\n * Build the tool row for one integration.\n * @param spec - the integration's label for the tool and what it says about calls.\n * @returns the component the plugin registers under each tool name it draws.\n */\nexport const createToolRow = (\n\tspec: ToolRowSpec,\n): ((props: ToolRowProps) => ReactNode) => {\n\tconst Row = ({ phase, block, toolName }: ToolRowProps): ReactNode => {\n\t\tconst name = spec.displayName(toolName);\n\n\t\tif (phase !== \"result\") {\n\t\t\treturn (\n\t\t\t\t<div className={styles.toolRow} data-tool={toolName} title={toolName}>\n\t\t\t\t\t<StateDot state=\"ongoing\" />\n\t\t\t\t\t<span className={styles.toolLabel}>{name}</span>\n\t\t\t\t\t{spec.asked === undefined ? null : (\n\t\t\t\t\t\t<span className={styles.caption}>{spec.asked(block) ?? \"\u2026\"}</span>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\tif (block?.isError === true) {\n\t\t\treturn (\n\t\t\t\t<div className={styles.toolRow} data-tool={toolName} title={toolName}>\n\t\t\t\t\t<StateDot state=\"error\" />\n\t\t\t\t\t<span className={styles.toolLabel}>{name}</span>\n\t\t\t\t\t<span className={`${styles.caption} ${styles.error}`}>\n\t\t\t\t\t\t{resultText(block) || \"failed\"}\n\t\t\t\t\t</span>\n\t\t\t\t</div>\n\t\t\t);\n\t\t}\n\n\t\treturn (\n\t\t\t<div className={styles.toolRow} data-tool={toolName} title={toolName}>\n\t\t\t\t<StateDot state={spec.state?.(block) ?? \"done\"} />\n\t\t\t\t<span className={styles.toolLabel}>{name}</span>\n\t\t\t\t<span className={styles.caption}>{spec.summarize(block)}</span>\n\t\t\t</div>\n\t\t);\n\t};\n\n\treturn Row;\n};\n", "/**\n * The harness's public tool names.\n *\n * A published MCP tool is renamed into the harness's namespace, which is capped\n * at 64 characters. Both halves of a plugin key their UI by the result \u2014 the\n * host publishes under it and the browser half claims it \u2014 so the rule lives in\n * exactly one place, bundled into each half rather than shared at runtime, and\n * the two can never disagree.\n */\n\n/** The harness caps a tool name at this many characters. */\nconst MAX_TOOL_NAME = 64;\n\n/** The prefix every published tool of one namespace carries. */\nexport function toolPrefix(namespace: string): string {\n\treturn `mcp__${namespace}__`;\n}\n\n/**\n * The public harness tool name for one server tool.\n *\n * The server's own spelling is kept whenever it fits, because that is what\n * makes a plugin's keyed tool views line up; a name that does not fit gets a\n * digest appended, so two long names can never collapse into one.\n * @param serverTool - the tool name as the server spells it.\n * @param namespace - the plugin's namespace (\"atlassian\").\n */\nexport function publicToolName(serverTool: string, namespace: string): string {\n\tconst cleaned = serverTool.replace(/[^A-Za-z0-9_-]/gu, \"_\") || \"tool\";\n\tconst full = `${toolPrefix(namespace)}${cleaned}`;\n\n\tif (full.length <= MAX_TOOL_NAME) return full;\n\n\tconst digest = digestOf(serverTool);\n\n\treturn `${full.slice(0, MAX_TOOL_NAME - digest.length - 1)}_${digest}`;\n}\n\n/**\n * A deterministic 12-hex-character digest of a string.\n *\n * Disambiguating two long tool names needs no cryptography, only a hash that\n * runs identically in Node and in the browser.\n */\nfunction digestOf(input: string): string {\n\tlet hash = 0xcbf29ce484222325n;\n\tconst prime = 0x100000001b3n;\n\tconst mask = 0xffffffffffffffffn;\n\n\tfor (let index = 0; index < input.length; index += 1) {\n\t\thash = ((hash ^ BigInt(input.charCodeAt(index))) * prime) & mask;\n\t}\n\n\treturn hash.toString(16).padStart(16, \"0\").slice(0, 12);\n}\n", "/**\n * The Atlassian server tools this plugin knows how to draw.\n *\n * Atlassian publishes a few primary tools in `tools/list` and reaches the rest\n * through `discover` / `executeRead` / `executeWrite`, and the v1 and v2\n * generations use different names for the same idea \u2014 both sets are listed.\n * A name the server no longer offers is harmless; a name that is missing simply\n * falls back to the generic tool row, so this list is a presentation detail\n * rather than a contract.\n */\nimport { publicToolName } from \"dsh-mcp-oauth/tool-name\";\n\n/** The namespace every published tool of this plugin lives under. */\nconst TOOL_NAMESPACE = \"atlassian\";\n\nexport const TOOL_NAMES = [\n\t// Shared and v2 gateway tools.\n\t\"atlassianUserInfo\",\n\t\"getAccessibleAtlassianResources\",\n\t\"discover\",\n\t\"getContentFormatGuide\",\n\t\"executeRead\",\n\t\"executeWrite\",\n\t\"executeDestructive\",\n\t// Jira, both generations.\n\t\"getJiraIssue\",\n\t\"searchJiraIssuesUsingJql\",\n\t\"createJiraIssue\",\n\t\"editJiraIssue\",\n\t\"transitionJiraIssue\",\n\t\"addOrEditJiraIssueComment\",\n\t\"addCommentToJiraIssue\",\n\t\"getJiraProjectIssueTypesMetadata\",\n\t\"listJiraProjects\",\n\t\"listJiraIssueComments\",\n\t\"listJiraIssueTransitions\",\n\t\"listJiraStatuses\",\n\t\"getJiraUser\",\n\t\"getJiraCurrentUser\",\n\t\"lookupJiraAccountId\",\n\t\"listJiraIssueAssignableUsers\",\n\t\"listJiraIssueWorklogs\",\n\t\"listJiraIssueLinkTypes\",\n\t\"listJiraIssueRemoteIssueLinks\",\n\t\"listJiraIssueChangelogs\",\n\t\"listJiraFilters\",\n\t\"listJiraDashboards\",\n\t\"listJiraBoards\",\n\t\"getJiraBoardConfig\",\n\t\"getJiraBoardIssueData\",\n\t\"getJiraBoardSprintData\",\n\t\"listJiraBoardSprints\",\n\t\"listJiraProjectComponents\",\n\t\"getJiraProjectVersions\",\n\t\"getJiraEntityProperty\",\n\t\"addOrEditJiraIssueWorklog\",\n\t\"createJiraIssueLink\",\n\t\"watchJiraIssue\",\n\t\"manageJiraSprint\",\n\t\"manageJiraProjectVersion\",\n\t\"uploadAttachmentToJiraIssue\",\n\t\"downloadJiraIssueAttachment\",\n\t// Confluence, both generations.\n\t\"getConfluencePage\",\n\t\"getConfluenceContent\",\n\t\"searchConfluenceUsingCql\",\n\t\"searchConfluence\",\n\t\"createConfluencePage\",\n\t\"updateConfluencePage\",\n\t\"createConfluenceContent\",\n\t\"updateConfluenceContent\",\n\t\"getConfluenceSpaces\",\n\t\"listConfluenceSpaces\",\n\t\"getConfluenceSpace\",\n\t\"listConfluenceContent\",\n\t\"listConfluenceComments\",\n\t\"getConfluenceComment\",\n\t\"listConfluenceAttachments\",\n\t\"getConfluenceAttachment\",\n\t\"listConfluenceContentVersions\",\n\t\"getConfluenceContentVersion\",\n\t\"exportConfluenceContent\",\n\t\"listConfluenceTasks\",\n\t\"getConfluenceTask\",\n\t\"listConfluenceTemplates\",\n\t\"getConfluenceTemplate\",\n\t\"getConfluenceContentPermissions\",\n\t\"getConfluenceSpaceInstructions\",\n\t\"createConfluenceComment\",\n\t\"updateConfluenceComment\",\n\t\"createConfluenceAttachment\",\n\t// Rovo search, which often answers a Jira or Confluence question.\n\t\"search\",\n] as const;\n\n/** Every public tool name this plugin knows how to draw. */\nexport const PUBLIC_TOOL_NAMES: readonly string[] = TOOL_NAMES.map((name) =>\n\tpublicToolName(name, TOOL_NAMESPACE),\n);\n", "/**\n * The card the agent can put in front of the user.\n *\n * The host half publishes one of these as a tool result's `presentationMeta`;\n * the browser half narrows it out of the persisted result and renders it as a\n * card under the closing text of the turn. The payload is opaque JSON on the\n * wire, so both halves share this type and the browser half validates it before\n * rendering.\n */\n\nimport type { IssueCard, PageCard } from \"./meta\";\n\n/** How much room one card gives each item. */\nexport type PresentationLayout = \"single\" | \"compact\" | \"list\";\n\n/** What the tool accepts; `auto` is resolved by the host before recording. */\nexport type PresentationLayoutInput = PresentationLayout | \"auto\";\n\n/** One thing on the card. */\nexport type PresentationItem =\n\t| { readonly kind: \"issue\"; readonly issue: IssueCard }\n\t| { readonly kind: \"page\"; readonly page: PageCard };\n\n/** One recorded presentation, as the browser half reads it. */\nexport interface AtlassianPresentation {\n\t/** The tool call that produced it; the card's identity. */\n\treadonly callId: string;\n\t/** Optional heading, such as \"\u041F\u043B\u0430\u043D \u043D\u0430 \u0434\u0435\u043D\u044C\". */\n\treadonly title?: string;\n\treadonly layout: PresentationLayout;\n\t/**\n\t * How many items the search matched, when that is more than the card shows.\n\t *\n\t * A card that scrolls says \"25 of 137 issues\"; a card that shows everything\n\t * leaves this out rather than repeating the item count.\n\t */\n\treadonly total?: number;\n\t/** Issues and pages, in the order the tool put them. */\n\treadonly items: readonly PresentationItem[];\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asItem(value: unknown): PresentationItem | undefined {\n\tif (!isRecord(value)) return undefined;\n\n\tif (\n\t\tvalue.kind === \"issue\" &&\n\t\tisRecord(value.issue) &&\n\t\ttypeof value.issue.key === \"string\"\n\t)\n\t\treturn { kind: \"issue\", issue: value.issue as unknown as IssueCard };\n\n\tif (\n\t\tvalue.kind === \"page\" &&\n\t\tisRecord(value.page) &&\n\t\ttypeof value.page.title === \"string\"\n\t)\n\t\treturn { kind: \"page\", page: value.page as unknown as PageCard };\n\n\treturn undefined;\n}\n\n/**\n * Validate one opaque record payload.\n * @param value - the record's `data`, as delivered to the browser.\n * @returns the presentation, or undefined when the record is not one of ours or\n * was written by a version whose payload this one cannot render. A card that\n * cannot be validated renders nothing, which is why the tool keeps a text\n * result as the source of truth for the model.\n */\nexport function asPresentation(\n\tvalue: unknown,\n): AtlassianPresentation | undefined {\n\tif (!isRecord(value)) return undefined;\n\tif (typeof value.callId !== \"string\" || value.callId === \"\") return undefined;\n\tif (!Array.isArray(value.items)) return undefined;\n\n\tconst layout: PresentationLayout =\n\t\tvalue.layout === \"single\" ||\n\t\tvalue.layout === \"compact\" ||\n\t\tvalue.layout === \"list\"\n\t\t\t? value.layout\n\t\t\t: \"list\";\n\n\tconst items: PresentationItem[] = [];\n\tfor (const candidate of value.items) {\n\t\tconst item = asItem(candidate);\n\t\tif (item !== undefined) items.push(item);\n\t}\n\n\tif (items.length === 0) return undefined;\n\n\treturn {\n\t\tcallId: value.callId,\n\t\t...(typeof value.title === \"string\" && value.title !== \"\"\n\t\t\t? { title: value.title }\n\t\t\t: {}),\n\t\tlayout,\n\t\t...(typeof value.total === \"number\" &&\n\t\tNumber.isFinite(value.total) &&\n\t\tvalue.total > items.length\n\t\t\t? { total: value.total }\n\t\t\t: {}),\n\t\titems,\n\t};\n}\n", "/**\n * Which colour an issue's type and priority earn on a card.\n *\n * Atlassian serves these as free text in whatever language the site is set to \u2014\n * this one answers \"\u0417\u0430\u0434\u0430\u0447\u0430\", \"\u0411\u0430\u0433\" and a priority of \"\u04203\" \u2014 so the mapping is\n * by name, in both languages. The Cyrillic letters that look Latin (\"\u04203\",\n * \"\u04211\") are folded before the second lookup, because a homoglyph is a spelling\n * of the same scheme value rather than a different one.\n *\n * An unrecognized name is a neutral fact rather than a guess: a wrong colour is\n * worse than no colour. The union matches `TagTone` structurally, so this\n * module stays free of any browser dependency.\n */\n\n/** The palettes the harness's `Tag` can render. */\nexport type CardTone =\n\t| \"outline\"\n\t| \"solid\"\n\t| \"neutral\"\n\t| \"quiet\"\n\t| \"success\"\n\t| \"info\"\n\t| \"warning\"\n\t| \"danger\";\n\n/** Issue types this version knows, as sites spell them. */\nconst TYPE_TONES: Readonly<Record<string, CardTone>> = {\n\tbug: \"danger\",\n\tdefect: \"danger\",\n\t\u0431\u0430\u0433: \"danger\",\n\t\u043E\u0448\u0438\u0431\u043A\u0430: \"danger\",\n\tstory: \"success\",\n\t\"user story\": \"success\",\n\t\u0438\u0441\u0442\u043E\u0440\u0438\u044F: \"success\",\n\tfeature: \"success\",\n\timprovement: \"success\",\n\t\u0443\u043B\u0443\u0447\u0448\u0435\u043D\u0438\u0435: \"success\",\n\ttask: \"info\",\n\t\u0437\u0430\u0434\u0430\u0447\u0430: \"info\",\n\t// An epic is the container the others hang from, so it gets the one loud\n\t// palette: it should be recognizable at a glance in a mixed list.\n\tepic: \"solid\",\n\t\u044D\u043F\u0438\u043A: \"solid\",\n\tquestion: \"warning\",\n\t\u0432\u043E\u043F\u0440\u043E\u0441: \"warning\",\n\tsupport: \"warning\",\n\t\"sub-task\": \"quiet\",\n\tsubtask: \"quiet\",\n\t\u043F\u043E\u0434\u0437\u0430\u0434\u0430\u0447\u0430: \"quiet\",\n};\n\n/** Priority names and scheme values this version knows. */\nconst PRIORITY_TONES: Readonly<Record<string, CardTone>> = {\n\tp0: \"danger\",\n\tp1: \"danger\",\n\tblocker: \"danger\",\n\tblocking: \"danger\",\n\thighest: \"danger\",\n\tcritical: \"danger\",\n\t\u043A\u0440\u0438\u0442\u0438\u0447\u0435\u0441\u043A\u0438\u0439: \"danger\",\n\tp2: \"warning\",\n\thigh: \"warning\",\n\tmajor: \"warning\",\n\t\u0432\u044B\u0441\u043E\u043A\u0438\u0439: \"warning\",\n\t\u0431\u043B\u043E\u043A\u0438\u0440\u0443\u044E\u0449\u0438\u0439: \"warning\",\n\t// A low or medium priority is a quiet fact, not a status: text only.\n\tp3: \"quiet\",\n\tp4: \"quiet\",\n\tp5: \"quiet\",\n\tmedium: \"quiet\",\n\taverage: \"quiet\",\n\tnormal: \"quiet\",\n\tlow: \"quiet\",\n\tlowest: \"quiet\",\n\tminor: \"quiet\",\n\ttrivial: \"quiet\",\n\t\u0441\u0440\u0435\u0434\u043D\u0438\u0439: \"quiet\",\n\t\u043D\u0438\u0437\u043A\u0438\u0439: \"quiet\",\n};\n\n/** Cyrillic letters a Jira scheme may use in place of their Latin twins. */\nconst HOMOGLYPHS: Readonly<Record<string, string>> = {\n\t\u0430: \"a\",\n\t\u0432: \"b\",\n\t\u0435: \"e\",\n\t\u043A: \"k\",\n\t\u043C: \"m\",\n\t\u043D: \"h\",\n\t\u043E: \"o\",\n\t\u0440: \"p\",\n\t\u0441: \"c\",\n\t\u0442: \"t\",\n\t\u0443: \"y\",\n\t\u0445: \"x\",\n};\n\n/**\n * The palette for one issue type.\n * @param type - the type name as the site spells it.\n * @returns a palette; `neutral` for a type this version does not know.\n */\nexport function issueTypeTone(type: string | undefined): CardTone {\n\treturn lookup(TYPE_TONES, type);\n}\n\n/**\n * The palette for one priority.\n * @param priority - the priority name or scheme value (\"P2\", \"High\", \"\u04204\").\n * @returns a palette; `neutral` when the value is missing or unknown.\n */\nexport function priorityTone(priority: string | undefined): CardTone {\n\treturn lookup(PRIORITY_TONES, priority);\n}\n\n/** Leading and trailing space, and case, are not part of a name. */\nfunction lookup(\n\ttable: Readonly<Record<string, CardTone>>,\n\tvalue: string | undefined,\n): CardTone {\n\tconst name = (value ?? \"\").trim().toLowerCase();\n\n\tif (name === \"\") return \"neutral\";\n\n\treturn table[name] ?? table[fold(name)] ?? \"neutral\";\n}\n\n/** Read a name as if its lookalike letters were Latin. */\nfunction fold(name: string): string {\n\treturn name.replace(\n\t\t/[\u0430\u0432\u0435\u043A\u043C\u043D\u043E\u0440\u0441\u0442\u0443\u0445]/gu,\n\t\t(letter) => HOMOGLYPHS[letter] ?? letter,\n\t);\n}\n", "/**\n * The Atlassian side panel, as a right-Sidebar tab type.\n *\n * A type reaches the Sidebar through its public path only: the definition into\n * `ctx.sidebarRightTabs`, the body into the keyed `sidebar.right.pane.tab` seat,\n * and the chip title into `sidebar.right.pane.tab.title`, both under this\n * definition's `id`. Nothing here reaches into the Sidebar's store or panes \u2014\n * the same two-stage registration a package shipped with the product uses, with\n * the shared shell of `dsh-integration-ui` doing the registering.\n *\n * No `multiple`: one panel per pane. Opening another issue navigates the one\n * that is there, which is what makes clicking through a search result feel like\n * following a link rather than opening windows.\n */\n\nimport type { SidebarRightTabDefinition } from \"@deepseek-ai/dsh-client-ui-sidebar-right/client\";\nimport { createPanelDefinition } from \"dsh-integration-ui\";\nimport type { PanelTarget } from \"../../shared/panel\";\n\n/** The tab kind this plugin owns; what `openTab` names. */\nexport const PANEL_KIND = \"atlassian\";\n\n/** This implementation's identity in the tab system: the key its body registers under. */\nexport const PANEL_ID = \"dsh-atlassian\";\n\ndeclare module \"@deepseek-ai/dsh-client-ui-sidebar-right/client\" {\n\tinterface SidebarRightTabParamsMap {\n\t\t/** What the Atlassian panel was last navigated to. */\n\t\tatlassian: PanelTarget;\n\t}\n}\n\n/** The panel's registry definition; the body and title carry the rest. */\nexport const panelDefinition = (): SidebarRightTabDefinition =>\n\tcreatePanelDefinition({ id: PANEL_ID, kind: PANEL_KIND, title: \"Atlassian\" });\n", "/**\n * Opening the side panel from anywhere in the page.\n *\n * The cards do not hold the client context, and the panel belongs to a package\n * that may not be composed at all, so this keeps the opener the plugin was\n * applied with and lets `dsh-integration-ui` resolve the Sidebar's navigation\n * face on every click. A build without the right panel answers `false`, and the\n * caller leaves the click to the browser rather than swallowing it.\n */\n\nimport type { Context } from \"@deepseek-ai/cordis\";\nimport {\n\tcreatePanelOpener,\n\ttype PanelOpener,\n\twantsBrowser,\n} from \"dsh-integration-ui\";\nimport type { PanelTarget } from \"../../shared/panel\";\nimport { PANEL_KIND } from \"./definition\";\n\nlet opener: PanelOpener<typeof PANEL_KIND> | undefined;\n\n/**\n * Remember the context the panel navigates through.\n * @param ctx - this plugin's client context.\n */\nexport const installPanelOpener = (ctx: Context): void => {\n\topener = createPanelOpener(ctx, PANEL_KIND);\n};\n\n/**\n * Show one issue or page in the harness's own right panel.\n * @param target - what to open.\n * @returns whether a panel took it; `false` means there is no panel here.\n */\nexport const openPanel = (target: PanelTarget): boolean =>\n\topener?.open(target) ?? false;\n\nexport { wantsBrowser };\n", "export var actions = '_9d1h6n8';\nexport var badges = '_9d1h6n6';\nexport var caption = '_9d1h6n7';\nexport var card = '_9d1h6n1';\nexport var cardMeta = '_9d1h6nv';\nexport var code = '_9d1h6no';\nexport var comment = 'd9jrn16';\nexport var commentAuthor = 'd9jrn18';\nexport var commentHead = 'd9jrn17';\nexport var comments = 'd9jrn15';\nexport var error = '_9d1h6np';\nexport var factInline = '_9d1h6nf';\nexport var factInlineLabel = '_9d1h6ng';\nexport var factLabel = '_9d1h6nc';\nexport var factValue = '_9d1h6nd';\nexport var facts = '_9d1h6nb';\nexport var factsInline = '_9d1h6ne';\nexport var field = '_9d1h6na';\nexport var head = '_9d1h6n2';\nexport var item = '_9d1h6ni';\nexport var itemHead = '_9d1h6nj';\nexport var itemLink = '_9d1h6nl';\nexport var itemText = 'd9jrn10';\nexport var itemTitle = '_9d1h6nk';\nexport var link = '_9d1h6nn';\nexport var list = '_9d1h6nh';\nexport var mono = '_9d1h6n19';\nexport var panel = '_9d1h6nz';\nexport var panelBody = 'd9jrn11';\nexport var panelHead = '_9d1h6n12';\nexport var panelKey = '_9d1h6n15';\nexport var panelLoading = '_9d1h6n11';\nexport var panelScroll = '_9d1h6n10';\nexport var panelSection = '_9d1h6n17';\nexport var panelSectionTitle = '_9d1h6n18';\nexport var panelSummary = '_9d1h6n16';\nexport var panelTitleRow = '_9d1h6n14';\nexport var people = 'd9jrn12';\nexport var person = 'd9jrn14';\nexport var personSearch = 'd9jrn13';\nexport var presentation = '_9d1h6nr';\nexport var presentationCount = '_9d1h6nu';\nexport var presentationHead = '_9d1h6ns';\nexport var presentationTitle = '_9d1h6nt';\nexport var presentations = '_9d1h6nq';\nexport var query = '_9d1h6nw';\nexport var row = '_9d1h6n9';\nexport var rowButton = '_9d1h6nm';\nexport var section = '_9d1h6n0';\nexport var state = '_9d1h6n4';\nexport var stateWord = '_9d1h6n5';\nexport var tabs = '_9d1h6n13';\nexport var theme = {radius:{sm:'var(--dsw-radius-sm)',md:'var(--dsw-radius-md)',lg:'var(--dsw-radius-lg)',xl:'var(--dsw-radius-xl)'},color:{labelPrimary:'var(--dsw-alias-label-primary)',labelSecondary:'var(--dsw-alias-label-secondary)',labelTertiary:'var(--dsw-alias-label-tertiary)',cardFill:'var(--dsw-alias-settings-card-fill)',cardStroke:'var(--dsw-alias-settings-card-stroke)',borderSubtle:'var(--dsw-alias-border-l2)',bgBase:'var(--dsw-alias-bg-base)',hoverFill:'var(--dsw-alias-interactive-bg-hover)',link:'var(--dsw-alias-link)',codeFill:'var(--dsw-alias-markdown-code-block)',danger:'var(--dsw-alias-state-error-primary)',success:'var(--dsw-alias-state-success-primary)',warn:'var(--dsw-alias-state-warn-primary)'},font:{code:'var(--ds-font-family-code)'}};\nexport var title = '_9d1h6n3';\nexport var toolLabel = '_9d1h6ny';\nexport var toolRow = '_9d1h6nx';", "/**\n * One Jira issue on a card.\n *\n * The row is the link: the title anchors a stretched overlay, so the whole card\n * opens the issue. The type is a coloured chip rather than a \"Type: \u2026\" badge,\n * because a colour is what makes a mixed list scannable at a glance.\n */\n\nimport { Chip, Facts } from \"dsh-integration-ui\";\nimport type { IssueCard } from \"../../shared/meta\";\nimport { issueTypeTone, priorityTone } from \"../../shared/tone\";\nimport { openPanel, wantsBrowser } from \"../sidebar/open\";\nimport * as styles from \"../styles/styles.css\";\n\ninterface Props {\n\tissue: IssueCard;\n}\n\nexport const IssueItem = ({ issue }: Props) => {\n\tconst title = [issue.key, issue.summary]\n\t\t.filter((part) => part !== undefined && part !== \"\")\n\t\t.join(\" \u00B7 \");\n\n\treturn (\n\t\t<li className={styles.item}>\n\t\t\t<div className={styles.itemHead}>\n\t\t\t\t<Chip value={issue.type} tone={issueTypeTone(issue.type)} />\n\n\t\t\t\t{issue.url === undefined ? (\n\t\t\t\t\t<span>{title}</span>\n\t\t\t\t) : (\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName={`${styles.link} ${styles.itemLink}`}\n\t\t\t\t\t\thref={issue.url}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t// The panel, when this build has one; the browser for a\n\t\t\t\t\t\t\t// modified click, or when it does not.\n\t\t\t\t\t\t\tif (wantsBrowser(event)) return;\n\t\t\t\t\t\t\tif (openPanel({ kind: \"issue\", key: issue.key }))\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{title}\n\t\t\t\t\t</a>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{issue.description === undefined ? null : (\n\t\t\t\t<p className={styles.itemText}>{issue.description}</p>\n\t\t\t)}\n\n\t\t\t<Facts\n\t\t\t\tlayout=\"inline\"\n\t\t\t\titems={[\n\t\t\t\t\t{ label: \"Status\", value: issue.status },\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Priority\",\n\t\t\t\t\t\tvalue:\n\t\t\t\t\t\t\tissue.priority === undefined ? undefined : (\n\t\t\t\t\t\t\t\t<Chip\n\t\t\t\t\t\t\t\t\tvalue={issue.priority}\n\t\t\t\t\t\t\t\t\ttone={priorityTone(issue.priority)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{ label: \"Assignee\", value: issue.assignee },\n\t\t\t\t\t{ label: \"Estimate\", value: issue.estimate },\n\t\t\t\t]}\n\t\t\t/>\n\t\t</li>\n\t);\n};\n", "/**\n * One Confluence page on a card.\n *\n * Like an issue row, the whole card is the link and the body is compressed to\n * the one sentence the card can afford.\n */\n\nimport { Facts } from \"dsh-integration-ui\";\nimport type { PageCard } from \"../../shared/meta\";\nimport { openPanel, wantsBrowser } from \"../sidebar/open\";\nimport * as styles from \"../styles/styles.css\";\n\ninterface Props {\n\tpage: PageCard;\n}\n\nexport const PageItem = ({ page }: Props) => {\n\treturn (\n\t\t<li className={styles.item}>\n\t\t\t<div className={styles.itemHead}>\n\t\t\t\t{page.url === undefined ? (\n\t\t\t\t\t<span>{page.title}</span>\n\t\t\t\t) : (\n\t\t\t\t\t<a\n\t\t\t\t\t\tclassName={`${styles.link} ${styles.itemLink}`}\n\t\t\t\t\t\thref={page.url}\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\tonClick={(event) => {\n\t\t\t\t\t\t\t// A page id is what the panel needs; a card that only knows a\n\t\t\t\t\t\t\t// URL leaves the click to the browser.\n\t\t\t\t\t\t\tif (wantsBrowser(event) || page.id === undefined) return;\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\topenPanel({\n\t\t\t\t\t\t\t\t\tkind: \"page\",\n\t\t\t\t\t\t\t\t\tid: page.id,\n\t\t\t\t\t\t\t\t\ttitle: page.title,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{page.title}\n\t\t\t\t\t</a>\n\t\t\t\t)}\n\t\t\t</div>\n\n\t\t\t{page.excerpt === undefined ? null : (\n\t\t\t\t<p className={styles.itemText}>{page.excerpt}</p>\n\t\t\t)}\n\n\t\t\t<Facts layout=\"inline\" items={[{ label: \"Space\", value: page.space }]} />\n\t\t</li>\n\t);\n};\n", "/**\n * How one Atlassian card draws itself.\n *\n * The shared tail owns the card's material, its heading and its list; this says\n * what the heading counts, which items go in the list, and how the two kinds of\n * item Atlassian returns \u2014 issues and pages \u2014 are drawn side by side.\n */\n\nimport type { CardProvider } from \"dsh-integration-ui\";\nimport type { AtlassianPresentation } from \"../../shared/presentation\";\nimport { IssueItem } from \"./issue-item\";\nimport { PageItem } from \"./page-item\";\n\n/**\n * What the card's heading says about its contents.\n * @param presentation - the card being drawn.\n * @returns \"3 issues\", \"2 pages\", or \"5 of 42 issues\" when more matched.\n */\nconst countLabel = (presentation: AtlassianPresentation): string => {\n\tconst issues = presentation.items.filter(\n\t\t(item) => item.kind === \"issue\",\n\t).length;\n\tconst pages = presentation.items.length - issues;\n\tconst total = presentation.total;\n\n\t// A single kind of item can say how many matched; a mixed card would have to\n\t// say \"of\" twice, so it keeps the plain counts.\n\tif (total !== undefined && (issues === 0 || pages === 0)) {\n\t\tconst noun = issues === 0 ? \"page\" : \"issue\";\n\n\t\treturn `${presentation.items.length} of ${total} ${noun}${total === 1 ? \"\" : \"s\"}`;\n\t}\n\n\treturn [\n\t\tissues === 0 ? \"\" : `${issues} issue${issues === 1 ? \"\" : \"s\"}`,\n\t\tpages === 0 ? \"\" : `${pages} page${pages === 1 ? \"\" : \"s\"}`,\n\t]\n\t\t.filter(Boolean)\n\t\t.join(\" \u00B7 \");\n};\n\n/** The Atlassian card, as the shared tail draws it. */\nexport const atlassianCard: CardProvider<AtlassianPresentation> = {\n\tcallId: (presentation) => presentation.callId,\n\ttitle: (presentation) => presentation.title,\n\tcount: countLabel,\n\tlength: (presentation) => presentation.items.length,\n\tlayout: (presentation) => presentation.layout,\n\titems: (presentation) =>\n\t\tpresentation.items.map((item, index) =>\n\t\t\titem.kind === \"issue\" ? (\n\t\t\t\t<IssueItem\n\t\t\t\t\tkey={item.issue.key ?? `issue-${index}`}\n\t\t\t\t\tissue={item.issue}\n\t\t\t\t/>\n\t\t\t) : (\n\t\t\t\t<PageItem key={item.page.id ?? `page-${index}`} page={item.page} />\n\t\t\t),\n\t\t),\n};\n", "/**\n * The turn-scoped card behind `atlassian_present`.\n *\n * The card itself \u2014 its wire name, the Turn-data key it publishes under, and\n * the state machine that collects one card per settled call \u2014 belongs to\n * `dsh-integration-ui`; what is Atlassian's is the payload narrowing and how the\n * card draws itself. Nothing extra is written to the session: the card is\n * narrowed from the tool result's persisted `presentationMeta`, which means\n * Session-log replay reproduces it exactly.\n */\n\nimport {\n\tcreatePresentationType,\n\ttype PresentationTurnData,\n} from \"dsh-integration-ui\";\nimport {\n\ttype AtlassianPresentation,\n\tasPresentation,\n} from \"../../shared/presentation\";\nimport { atlassianCard } from \"../components/presentation-card\";\n\n/** The wire name whose settled result carries one card. */\nexport const PRESENT_TOOL_NAME = \"atlassian_present\";\n\n/** The Turn-data key the tail reads. */\nexport const PRESENTATION_TURN_DATA_KEY = \"atlassian-presented\";\n\ndeclare module \"@deepseek-ai/dsh-client-ui-conversation/client\" {\n\tinterface ConversationTurnDataMap {\n\t\t/** Cards `atlassian_present` asked to show in this Turn, in call order. */\n\t\t\"atlassian-presented\": PresentationTurnData<AtlassianPresentation>;\n\t}\n}\n\n/** The Atlassian card, as this plugin registers and renders it. */\nexport const atlassianPresentation = createPresentationType<\n\tAtlassianPresentation,\n\t\"atlassian-presented\"\n>({\n\tturnDataKey: PRESENTATION_TURN_DATA_KEY,\n\ttoolName: PRESENT_TOOL_NAME,\n\tparse: asPresentation,\n\tcard: atlassianCard,\n});\n", "/**\n * The card `atlassian_present` shows, under the closing text of its turn.\n *\n * A turn tail is the right seat for this: the card is an answer-shaped artifact\n * rather than a step in the work, so it belongs beneath the prose, outside the\n * collapsible tool group \u2014 the same place `present` puts its file cards. The\n * seat renders for every completed turn and narrows its own turn, so two cards\n * shown in one turn both render, in call order.\n */\n\nimport { createPresentationTail } from \"dsh-integration-ui\";\nimport { atlassianPresentation } from \"../conversation/presentation-definition\";\n\n/** Every card one completed turn asked to show. */\nexport const PresentationTail = createPresentationTail(atlassianPresentation);\n", "/**\n * The browser half's channel to the host half.\n *\n * Both run on the same loopback origin, so the settings card and the side panel\n * reach the host through the named route `/dsh-atlassian` with ordinary\n * same-origin requests. The transport \u2014 JSON in both directions, `{ error }`\n * turned back into a message \u2014 belongs to `dsh-integration-ui`; this is the list\n * of calls Atlassian actually makes.\n */\n\nimport { createHostRequest } from \"dsh-integration-ui\";\nimport type {\n\tIssuePanel,\n\tPanelData,\n\tPanelPerson,\n\tPanelTarget,\n} from \"../shared/panel\";\nimport type { AtlassianStatus } from \"../shared/status\";\n\nconst request = createHostRequest(\"/dsh-atlassian\");\n\nexport const hostApi = {\n\t/** Read the current sign-in and connection state. */\n\tstatus: async (): Promise<AtlassianStatus> => {\n\t\treturn await request(\"/status\", \"GET\");\n\t},\n\n\t/** Start a sign-in attempt; resolves as soon as the attempt is running. */\n\tlogin: async (): Promise<AtlassianStatus> => {\n\t\treturn await request(\"/login\", \"POST\");\n\t},\n\n\t/** Forget the stored sign-in and withdraw the published tools. */\n\tlogout: async (): Promise<AtlassianStatus> => {\n\t\treturn await request(\"/logout\", \"POST\");\n\t},\n\n\t/** Reconnect and re-publish the Atlassian tools. */\n\tsync: async (): Promise<AtlassianStatus> => {\n\t\treturn await request(\"/sync\", \"POST\");\n\t},\n\n\t/** Everything one panel shows for its target. */\n\tgetPanel: async (\n\t\ttarget: PanelTarget,\n\t\tsignal?: AbortSignal,\n\t): Promise<PanelData> => {\n\t\treturn target.kind === \"issue\"\n\t\t\t? await request(\n\t\t\t\t\t`/issue?key=${encodeURIComponent(target.key)}`,\n\t\t\t\t\t\"GET\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tsignal,\n\t\t\t\t)\n\t\t\t: await request(\n\t\t\t\t\t`/page?id=${encodeURIComponent(target.id)}`,\n\t\t\t\t\t\"GET\",\n\t\t\t\t\tundefined,\n\t\t\t\t\tsignal,\n\t\t\t\t);\n\t},\n\n\t/**\n\t * The signed-in user, as the site names them.\n\t * @returns the reader, or null when the site names no account for this token.\n\t */\n\tme: async (): Promise<PanelPerson | null> => {\n\t\tconst answer = await request<{ person: PanelPerson | null }>(\"/me\", \"GET\");\n\n\t\treturn answer.person;\n\t},\n\n\t/** People the site matches to a search string. */\n\tfindPeople: async (\n\t\tquery: string,\n\t\tsignal?: AbortSignal,\n\t): Promise<PanelPerson[]> => {\n\t\tconst found: PanelPerson[] = await request(\n\t\t\t`/people?q=${encodeURIComponent(query)}`,\n\t\t\t\"GET\",\n\t\t\tundefined,\n\t\t\tsignal,\n\t\t);\n\n\t\treturn Array.isArray(found) ? found : [];\n\t},\n\n\t/** Move one issue through a workflow transition; answers with the fresh issue. */\n\ttransitionIssue: async (\n\t\tkey: string,\n\t\ttransitionId: string,\n\t): Promise<IssuePanel> => {\n\t\treturn await request(\"/issue/transition\", \"POST\", {\n\t\t\tkey,\n\t\t\ttransitionId,\n\t\t});\n\t},\n\n\t/** Set or clear one issue's assignee; answers with the fresh issue. */\n\tassignIssue: async (\n\t\tkey: string,\n\t\taccountId: string | null,\n\t): Promise<IssuePanel> => {\n\t\treturn await request(\"/issue/assignee\", \"POST\", { key, accountId });\n\t},\n};\n", "/**\n * The Atlassian settings card.\n *\n * It shows the sign-in state and the connection state, and it is the only place\n * a user has to go to connect: the button starts the OAuth flow in the host,\n * which opens the browser, and this card follows the attempt until it settles.\n * The card itself belongs to `dsh-integration-ui`; what is Atlassian's is its\n * copy and the tab it sits under.\n */\n\nimport { createSettingsSection } from \"dsh-integration-ui\";\nimport type { AtlassianStatus } from \"../../shared/status\";\nimport { hostApi } from \"../host-api\";\n\n/** The Atlassian settings card. */\nexport const AtlassianSection = createSettingsSection<AtlassianStatus>({\n\ttitle: \"Atlassian\",\n\tblurb: \"Jira and Confluence, through Atlassian\u2019s MCP server.\",\n\tchecking: \"Checking the Atlassian sign-in\u2026\",\n\tunreachable: \"The Atlassian host half is not reachable.\",\n\tcredentials: \"browser\",\n\tsignInLabel: \"Sign in with Atlassian\",\n\tsyncLabel: \"Re-check\",\n\tapi: hostApi,\n});\n", "/**\n * The wire contract between the two halves.\n *\n * The host half turns one MCP tool result into this shape and hands it to the\n * tool pipeline as `presentationMeta`; the harness persists it on the tool\n * result and the Web Client reads it back as `meta`. Both halves import these\n * types, and each bundle inlines its own copy \u2014 a type-only contract, not\n * shared runtime state.\n */\n\n/** A Jira issue, reduced to what a card shows. */\nexport type IssueCard = {\n\treadonly key: string;\n\treadonly summary?: string;\n\treadonly status?: string;\n\treadonly assignee?: string;\n\treadonly priority?: string;\n\treadonly type?: string;\n\t/** The issue's own estimate, as Jira states it (\"3d 4h\"). */\n\treadonly estimate?: string;\n\t/** One sentence about the issue, compressed from its description. */\n\treadonly description?: string;\n\treadonly url?: string;\n\t/**\n\t * The issue's description, before it was compressed.\n\t *\n\t * Host-side only, and only while a caller asks for it: this is what the gist\n\t * pass reads, and the tool projects a fresh card without it, so it can never\n\t * reach the recorded payload.\n\t */\n\treadonly rawText?: string;\n};\n\n/** A Confluence page (or any titled content), reduced to what a card shows. */\nexport type PageCard = {\n\treadonly id?: string;\n\treadonly title: string;\n\treadonly url?: string;\n\treadonly space?: string;\n\t/** One sentence about the page, compressed from its body. */\n\treadonly excerpt?: string;\n\t/** The page's body, before it was compressed. Host-side only. */\n\treadonly rawText?: string;\n};\n\n/** The kinds of result the host half recognizes. */\nexport type MetaKind = \"jira-issues\" | \"confluence-pages\" | \"text\";\n\n/**\n * What the host half publishes for one Atlassian tool result.\n *\n * `text` is always present so a card can fall back to the server's own words\n * even when nothing was recognized.\n */\nexport type AtlassianMeta = {\n\treadonly kind: MetaKind;\n\t/** The server's own tool name, before the `mcp__atlassian__` prefix. */\n\treadonly tool: string;\n\t/** The query or target the call carried, when it had one. */\n\treadonly query?: string;\n\t/**\n\t * How many matching items the server reported, when it said.\n\t *\n\t * A search answers with more than it returns, so a card says \"5 of 42\"\n\t * rather than implying that five is all there is.\n\t */\n\treadonly total?: number;\n\tissues: IssueCard[];\n\tpages: PageCard[];\n\treadonly text: string;\n};\n\n/** Narrow an unknown `meta` value from the wire to this contract. */\nexport function asAtlassianMeta(value: unknown): AtlassianMeta | undefined {\n\tif (value === null || typeof value !== \"object\") return undefined;\n\n\tconst candidate = value as Partial<AtlassianMeta>;\n\tif (typeof candidate.kind !== \"string\" || typeof candidate.tool !== \"string\")\n\t\treturn undefined;\n\n\tconst total =\n\t\ttypeof candidate.total === \"number\" && Number.isFinite(candidate.total)\n\t\t\t? candidate.total\n\t\t\t: undefined;\n\n\treturn {\n\t\tkind:\n\t\t\tcandidate.kind === \"jira-issues\" || candidate.kind === \"confluence-pages\"\n\t\t\t\t? candidate.kind\n\t\t\t\t: \"text\",\n\t\ttool: candidate.tool,\n\t\t...(typeof candidate.query === \"string\" ? { query: candidate.query } : {}),\n\t\t...(total === undefined ? {} : { total }),\n\t\tissues: Array.isArray(candidate.issues)\n\t\t\t? (candidate.issues as IssueCard[])\n\t\t\t: [],\n\t\tpages: Array.isArray(candidate.pages)\n\t\t\t? (candidate.pages as PageCard[])\n\t\t\t: [],\n\t\ttext: typeof candidate.text === \"string\" ? candidate.text : \"\",\n\t};\n}\n", "/**\n * The Atlassian tool row: one line about what the call did.\n *\n * Claiming a tool name in the `tool.call.toolview` slot replaces the generic row\n * for **every** shape of that call \u2014 preparing, running, failed, replayed \u2014 and\n * the row's own material belongs to `dsh-integration-ui`. What is Atlassian's is\n * what the line says: the surface the call works on, in the reader's words, and\n * what the settled call found.\n *\n * It stays deliberately terse. The server's payload is large JSON, and a tool\n * group that reproduces it buries the answer; the cards belong to\n * `atlassian_present`, which puts them where the user is actually reading.\n *\n * The server publishes a few gateway tools and hides the rest behind them, and\n * the two generations it speaks name the same idea differently. So the row leads\n * with the names a reader will actually meet, and reads anything else as words\n * rather than showing a camel-case identifier. The wire name itself stays on the\n * row as its tooltip.\n */\n\nimport { createToolRow, type ToolRowBlock } from \"dsh-integration-ui\";\nimport { asAtlassianMeta } from \"../../shared/meta\";\n\n/**\n * What the tools a reader meets are about.\n *\n * Not a contract: a name the server no longer offers is harmless, a name that is\n * missing simply falls through to {@link asWords}, and the summary after it says\n * what the call found either way.\n */\nconst TOOL_LABELS: Readonly<Record<string, string>> = {\n\tatlassianUserInfo: \"Atlassian account\",\n\tgetJiraCurrentUser: \"Atlassian account\",\n\tgetJiraUser: \"Jira person\",\n\tgetAccessibleAtlassianResources: \"Atlassian sites\",\n\tdiscover: \"Atlassian tools\",\n\tgetContentFormatGuide: \"Content format\",\n\texecuteRead: \"Atlassian read\",\n\texecuteWrite: \"Atlassian write\",\n\texecuteDestructive: \"Atlassian change\",\n\tsearchJiraIssuesUsingJql: \"Jira search\",\n\tgetJiraIssue: \"Jira issue\",\n\tcreateJiraIssue: \"New Jira issue\",\n\teditJiraIssue: \"Jira issue edit\",\n\ttransitionJiraIssue: \"Jira transition\",\n\taddCommentToJiraIssue: \"Jira comment\",\n\taddOrEditJiraIssueComment: \"Jira comment\",\n\tlookupJiraAccountId: \"Jira people\",\n\tlistJiraIssueAssignableUsers: \"Jira people\",\n\tsearchConfluenceUsingCql: \"Confluence search\",\n\tsearchConfluence: \"Confluence search\",\n\tgetConfluencePage: \"Confluence page\",\n\tgetConfluenceContent: \"Confluence content\",\n\tcreateConfluencePage: \"New Confluence page\",\n\tupdateConfluencePage: \"Confluence page edit\",\n\tcreateConfluenceComment: \"Confluence comment\",\n\tlistConfluenceComments: \"Confluence comments\",\n\tsearch: \"Atlassian search\",\n\tfetch: \"Atlassian resource\",\n};\n\n/**\n * One wire name read as words: `getJiraIssue` becomes \"Get Jira issue\".\n * @param name - the server's tool name, without this plugin's namespace.\n * @returns the name with its word boundaries spelled out.\n */\nconst asWords = (name: string): string => {\n\tconst words = name\n\t\t.replace(/([a-z0-9])([A-Z])/gu, \"$1 $2\")\n\t\t.replace(/[_-]+/gu, \" \")\n\t\t.trim();\n\n\tif (words === \"\") return \"Atlassian\";\n\n\treturn `${words.slice(0, 1).toUpperCase()}${words.slice(1)}`;\n};\n\n/** The surface one tool works on, in the reader's words. */\nconst toolLabel = (toolName: string | undefined): string => {\n\tconst name = (toolName ?? \"\").replace(/^mcp__atlassian__/u, \"\");\n\n\treturn TOOL_LABELS[name] ?? asWords(name);\n};\n\n/** \"found 3 issues\", or \"found 3 of 712 pages\" when the server said so. */\nconst found = (\n\tcount: number,\n\tnoun: string,\n\ttotal: number | undefined,\n): string => {\n\tconst plural = count === 1 ? \"\" : \"s\";\n\n\treturn total === undefined || total <= count\n\t\t? `found ${count} ${noun}${plural}`\n\t\t: `found ${count} of ${total} ${noun}${plural}`;\n};\n\n/** One short phrase describing what a settled call found. */\nconst summarize = (block: ToolRowBlock | undefined): string => {\n\tconst meta = asAtlassianMeta(block?.meta);\n\tif (meta === undefined) return \"done\";\n\n\tconst parts: string[] = [];\n\tconst total = meta.total;\n\n\tif (meta.issues.length > 0)\n\t\tparts.push(found(meta.issues.length, \"issue\", total));\n\telse if (meta.pages.length > 0)\n\t\tparts.push(found(meta.pages.length, \"page\", total));\n\n\tif (meta.query !== undefined) parts.push(meta.query);\n\tif (parts.length === 0) parts.push(\"done\");\n\n\treturn parts.join(\" \u00B7 \");\n};\n\n/** One Atlassian tool call, as a single line. */\nexport const AtlassianToolRow = createToolRow({\n\tdisplayName: toolLabel,\n\tsummarize,\n});\n", "/**\n * The plugin's identity in the Web Client.\n *\n * The client module system keys registration, style ownership, and the\n * `__ModuleLoader__.load` id by the package name, so it lives in one place\n * rather than being spelled out at each of those sites.\n */\nexport const PLUGIN_ID = \"dsh-atlassian\";\n", "/**\n * The Atlassian panel: one issue or page, and the actions that change it.\n *\n * The body is a right-Sidebar tab of this plugin's own kind, so it renders\n * inside the harness's panel and follows its theme. What to show arrives in the\n * tab's navigation parameters, the document itself comes through the host's\n * `/dsh-atlassian` route \u2014 only the host half holds the MCP connection \u2014 and the\n * loading, failing, retrying and writing belong to `dsh-integration-ui`.\n *\n * Writes are one step at a time: run it, and the host answers with the issue as\n * it now stands, so the panel never renders an assumption about what a\n * transition did.\n */\n\nimport type { MarkdownLabels } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\tButton,\n\tInput,\n\tMarkdownText,\n\tMenu,\n\ttype MenuEntry,\n} from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport {\n\tChip,\n\tcreatePanelBody,\n\tcreatePanelTitle,\n\tFacts,\n\ttype PanelActions,\n\ttype PanelProvider,\n} from \"dsh-integration-ui\";\nimport type { ReactNode } from \"react\";\nimport { useEffect, useState } from \"react\";\nimport {\n\tasPanelData,\n\tasPanelTarget,\n\ttype IssuePanel,\n\ttype PagePanel,\n\ttype PanelComment,\n\ttype PanelData,\n\ttype PanelPerson,\n\ttype PanelTarget,\n} from \"../../shared/panel\";\nimport { issueTypeTone, priorityTone } from \"../../shared/tone\";\nimport { hostApi } from \"../host-api\";\nimport * as styles from \"../styles/styles.css\";\n\n/** Chrome for the Markdown renderer; one identity for the whole panel. */\nconst MARKDOWN_LABELS: MarkdownLabels = {\n\tcode: { copyLabel: \"Copy\", copiedLabel: \"Copied\" },\n\tfootnotes: \"Footnotes\",\n};\n\n/** One date as the reader's own locale writes it. */\nfunction whenText(value: string): string {\n\tconst time = Date.parse(value);\n\n\treturn Number.isNaN(time)\n\t\t? value\n\t\t: new Date(time).toLocaleString(undefined, {\n\t\t\t\tdateStyle: \"medium\",\n\t\t\t\ttimeStyle: \"short\",\n\t\t\t});\n}\n\n/** One titled block. */\nconst Section = ({\n\ttitle,\n\tchildren,\n}: {\n\ttitle: string;\n\tchildren: ReactNode;\n}) => (\n\t<section className={styles.panelSection}>\n\t\t<span className={styles.panelSectionTitle}>{title}</span>\n\t\t{children}\n\t</section>\n);\n\n/** Rendered Markdown, with links leaving for the browser rather than the page. */\nconst Prose = ({ text }: { text: string }) => (\n\t<div className={styles.panelBody}>\n\t\t<MarkdownText text={text} labels={MARKDOWN_LABELS} variant=\"compact\" />\n\t</div>\n);\n\n/** The comment thread of an issue or a page. */\nconst Comments = ({ comments }: { comments: readonly PanelComment[] }) => {\n\tif (comments.length === 0)\n\t\treturn <span className={styles.caption}>No comments.</span>;\n\n\treturn (\n\t\t<ul className={styles.comments}>\n\t\t\t{comments.map((comment, index) => (\n\t\t\t\t<li\n\t\t\t\t\tkey={`${comment.author ?? \"comment\"}-${comment.created ?? index}`}\n\t\t\t\t\tclassName={styles.comment}\n\t\t\t\t>\n\t\t\t\t\t<div className={styles.commentHead}>\n\t\t\t\t\t\t<span className={styles.commentAuthor}>\n\t\t\t\t\t\t\t{comment.author ?? \"Someone\"}\n\t\t\t\t\t\t</span>\n\t\t\t\t\t\t{comment.created === undefined ? null : (\n\t\t\t\t\t\t\t<span className={styles.caption}>\n\t\t\t\t\t\t\t\t{whenText(comment.created)}\n\t\t\t\t\t\t\t</span>\n\t\t\t\t\t\t)}\n\t\t\t\t\t</div>\n\t\t\t\t\t<Prose text={comment.body} />\n\t\t\t\t</li>\n\t\t\t))}\n\t\t</ul>\n\t);\n};\n\ninterface Actions {\n\treadonly busy: boolean;\n\trun: PanelActions<PanelTarget>[\"run\"];\n}\n\n/**\n * Run one write against the issue the panel is showing.\n *\n * A page has no workflow and no assignee, so a write is refused rather than\n * sent at whatever the panel happens to hold.\n * @param actions - the shared body's action set.\n * @param write - the call, which takes the issue's key.\n */\nconst runIssue = (\n\tactions: Actions,\n\twrite: (key: string) => Promise<unknown>,\n): void => {\n\tactions.run(async (target) => {\n\t\tif (target.kind !== \"issue\")\n\t\t\tthrow new Error(\"this panel is not showing an issue\");\n\n\t\treturn await write(target.key);\n\t});\n};\n\n/** The transitions the workflow offers right now. */\nconst Transitions = ({\n\tissue,\n\tactions,\n}: {\n\tissue: IssuePanel;\n\tactions: Actions;\n}) => {\n\tif (issue.transitions.length === 0) return null;\n\n\tconst blocked = issue.transitions.some(\n\t\t(transition) => transition.needsFields,\n\t);\n\n\treturn (\n\t\t<Section title=\"Move to\">\n\t\t\t<div className={styles.actions}>\n\t\t\t\t{issue.transitions.map((transition) => (\n\t\t\t\t\t<Button\n\t\t\t\t\t\tkey={transition.id}\n\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\tvariant=\"outline\"\n\t\t\t\t\t\tdisabled={\n\t\t\t\t\t\t\tactions.busy || !transition.available || transition.needsFields\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttitle={\n\t\t\t\t\t\t\ttransition.needsFields\n\t\t\t\t\t\t\t\t? `${transition.name} opens a screen with required fields`\n\t\t\t\t\t\t\t\t: transition.to === undefined\n\t\t\t\t\t\t\t\t\t? transition.name\n\t\t\t\t\t\t\t\t\t: `${transition.name} \u2192 ${transition.to}`\n\t\t\t\t\t\t}\n\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\trunIssue(actions, (key) =>\n\t\t\t\t\t\t\t\thostApi.transitionIssue(key, transition.id),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}}\n\t\t\t\t\t>\n\t\t\t\t\t\t{transition.name}\n\t\t\t\t\t</Button>\n\t\t\t\t))}\n\t\t\t</div>\n\t\t\t{blocked ? (\n\t\t\t\t<span className={styles.caption}>\n\t\t\t\t\tA transition that needs a form is left to the Atlassian site.\n\t\t\t\t</span>\n\t\t\t) : null}\n\t\t</Section>\n\t);\n};\n\n/** People assigned from this page's session, so the second assignment is one click. */\nconst remembered: PanelPerson[] = [];\n\n/** How many remembered people the menu offers. */\nconst REMEMBERED_LIMIT = 4;\n\n/** Remember one person, most recent first. */\nfunction remember(person: PanelPerson): void {\n\tif (remembered.some((known) => known.accountId === person.accountId)) return;\n\n\tremembered.unshift(person);\n\tremembered.length = Math.min(remembered.length, REMEMBERED_LIMIT);\n}\n\n/**\n * Hand the issue to somebody else.\n *\n * The site's people lookup needs a search string, so the panel cannot offer a\n * list of everybody \u2014 but it should not make the reader type a name it already\n * knows either. The reader themselves is one click, the people assigned to from\n * this session are remembered, and the search field appears only when somebody\n * new has to be found by name.\n */\nconst Assignee = ({\n\tissue,\n\tactions,\n}: {\n\tissue: IssuePanel;\n\tactions: Actions;\n}) => {\n\tconst [open, setOpen] = useState(false);\n\tconst [searchOpen, setSearchOpen] = useState(false);\n\tconst [fetching, setFetching] = useState(false);\n\tconst [query, setQuery] = useState(\"\");\n\tconst [people, setPeople] = useState<readonly PanelPerson[]>([]);\n\tconst [me, setMe] = useState<PanelPerson | null>(null);\n\tconst [known, setKnown] = useState<readonly PanelPerson[]>(remembered);\n\n\t// Who the reader is, asked once: without it the panel simply offers no\n\t// self-assignment, and the search stays the only way to name anybody.\n\tuseEffect(() => {\n\t\tlet live = true;\n\n\t\thostApi\n\t\t\t.me()\n\t\t\t.then((person) => {\n\t\t\t\tif (live) setMe(person);\n\t\t\t})\n\t\t\t.catch(() => undefined);\n\n\t\treturn () => {\n\t\t\tlive = false;\n\t\t};\n\t}, []);\n\n\tuseEffect(() => {\n\t\tconst trimmed = query.trim();\n\n\t\tif (trimmed.length < 2) {\n\t\t\tsetPeople([]);\n\t\t\treturn;\n\t\t}\n\n\t\tconst controller = new AbortController();\n\t\t// One search per pause in typing: the site's lookup is not free.\n\t\tconst timer = setTimeout(() => {\n\t\t\tsetFetching(true);\n\t\t\thostApi\n\t\t\t\t.findPeople(trimmed, controller.signal)\n\t\t\t\t.then((found) => {\n\t\t\t\t\tif (!controller.signal.aborted) setPeople(found);\n\t\t\t\t})\n\t\t\t\t.catch(() => undefined)\n\t\t\t\t.finally(() => {\n\t\t\t\t\tif (!controller.signal.aborted) setFetching(false);\n\t\t\t\t});\n\t\t}, 300);\n\n\t\treturn () => {\n\t\t\tclearTimeout(timer);\n\t\t\tcontroller.abort();\n\t\t};\n\t}, [query]);\n\n\tconst assign = (person: PanelPerson | null): void => {\n\t\tif (person !== null) {\n\t\t\tremember(person);\n\t\t\tsetKnown([...remembered]);\n\t\t}\n\n\t\tsetQuery(\"\");\n\t\tsetSearchOpen(false);\n\t\trunIssue(actions, (key) =>\n\t\t\thostApi.assignIssue(key, person?.accountId ?? null),\n\t\t);\n\t};\n\n\tconst entries: MenuEntry[] = [\n\t\t...(me === null || me.accountId === issue.assignee?.accountId\n\t\t\t? []\n\t\t\t: [{ id: `person:${me.accountId}`, label: `Assign to me (${me.name})` }]),\n\t\t...known\n\t\t\t.filter((person) => person.accountId !== me?.accountId)\n\t\t\t.map((person) => ({\n\t\t\t\tid: `person:${person.accountId}`,\n\t\t\t\tlabel: person.name,\n\t\t\t})),\n\t\t{ id: \"search\", label: \"Search people\u2026\" },\n\t];\n\n\t/** The person one menu id names, or null when it was not a person. */\n\tconst personFor = (id: string): PanelPerson | null => {\n\t\tif (me !== null && id === `person:${me.accountId}`) return me;\n\n\t\treturn known.find((person) => id === `person:${person.accountId}`) ?? null;\n\t};\n\n\treturn (\n\t\t<Section title=\"Assignee\">\n\t\t\t<div className={styles.row}>\n\t\t\t\t<span className={styles.caption}>\n\t\t\t\t\t{issue.assignee?.name ?? \"Nobody is assigned.\"}\n\t\t\t\t</span>\n\n\t\t\t\t<Menu\n\t\t\t\t\topen={open}\n\t\t\t\t\tonClose={() => {\n\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t}}\n\t\t\t\t\tautoFocus\n\t\t\t\t\tdense\n\t\t\t\t\titems={entries}\n\t\t\t\t\tonSelect={(id) => {\n\t\t\t\t\t\tsetOpen(false);\n\n\t\t\t\t\t\tif (id === \"search\") {\n\t\t\t\t\t\t\tsetSearchOpen(true);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tassign(personFor(id));\n\t\t\t\t\t}}\n\t\t\t\t\tfooter={\n\t\t\t\t\t\tissue.assignee === undefined\n\t\t\t\t\t\t\t? []\n\t\t\t\t\t\t\t: [{ id: \"unassign\", label: \"Unassign\", danger: true }]\n\t\t\t\t\t}\n\t\t\t\t\tanchor={\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={actions.busy}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tif (open) {\n\t\t\t\t\t\t\t\t\tsetOpen(false);\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tsetSearchOpen(false);\n\t\t\t\t\t\t\t\tsetOpen(true);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tChange\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</div>\n\n\t\t\t{searchOpen ? (\n\t\t\t\t<>\n\t\t\t\t\t<div className={styles.actions}>\n\t\t\t\t\t\t<Input\n\t\t\t\t\t\t\tclassName={styles.personSearch}\n\t\t\t\t\t\t\tvalue={query}\n\t\t\t\t\t\t\tplaceholder=\"Search people\u2026\"\n\t\t\t\t\t\t\tdisabled={actions.busy}\n\t\t\t\t\t\t\tonChange={(event) => {\n\t\t\t\t\t\t\t\tsetQuery(event.target.value);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t/>\n\n\t\t\t\t\t\t<Button\n\t\t\t\t\t\t\tsize=\"sm\"\n\t\t\t\t\t\t\tvariant=\"ghost\"\n\t\t\t\t\t\t\tdisabled={actions.busy}\n\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\tsetQuery(\"\");\n\t\t\t\t\t\t\t\tsetSearchOpen(false);\n\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\tCancel\n\t\t\t\t\t\t</Button>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{query.trim().length < 2 ? (\n\t\t\t\t\t\t<span className={styles.caption}>\n\t\t\t\t\t\t\tTwo letters are enough to search the site.\n\t\t\t\t\t\t</span>\n\t\t\t\t\t) : null}\n\n\t\t\t\t\t{fetching ? <span className={styles.caption}>Searching\u2026</span> : null}\n\n\t\t\t\t\t{people.length === 0 ? null : (\n\t\t\t\t\t\t<ul className={styles.people}>\n\t\t\t\t\t\t\t{people.map((person) => (\n\t\t\t\t\t\t\t\t<li key={person.accountId}>\n\t\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\t\tclassName={styles.person}\n\t\t\t\t\t\t\t\t\t\tdisabled={actions.busy}\n\t\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\t\tassign(person);\n\t\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{person.name}\n\t\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t\t</li>\n\t\t\t\t\t\t\t))}\n\t\t\t\t\t\t</ul>\n\t\t\t\t\t)}\n\t\t\t\t</>\n\t\t\t) : null}\n\t\t</Section>\n\t);\n};\n\n/** One issue: what it is, how it is doing, and what may be done to it. */\nconst IssueView = ({\n\tissue,\n\tactions,\n}: {\n\tissue: IssuePanel;\n\tactions: Actions;\n}) => (\n\t<>\n\t\t<header className={styles.panelHead}>\n\t\t\t<div className={styles.panelTitleRow}>\n\t\t\t\t<Chip value={issue.type} tone={issueTypeTone(issue.type)} />\n\t\t\t\t<a\n\t\t\t\t\tclassName={`${styles.link} ${styles.panelKey}`}\n\t\t\t\t\thref={issue.url}\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t>\n\t\t\t\t\t{issue.key}\n\t\t\t\t</a>\n\t\t\t</div>\n\t\t\t<h2 className={styles.panelSummary}>{issue.summary ?? issue.key}</h2>\n\n\t\t\t<Facts\n\t\t\t\titems={[\n\t\t\t\t\t{ label: \"Status\", value: issue.status },\n\t\t\t\t\t{\n\t\t\t\t\t\tlabel: \"Priority\",\n\t\t\t\t\t\tvalue:\n\t\t\t\t\t\t\tissue.priority === undefined ? undefined : (\n\t\t\t\t\t\t\t\t<Chip\n\t\t\t\t\t\t\t\t\tvalue={issue.priority}\n\t\t\t\t\t\t\t\t\ttone={priorityTone(issue.priority)}\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t),\n\t\t\t\t\t},\n\t\t\t\t\t{ label: \"Reporter\", value: issue.reporter },\n\t\t\t\t\t{ label: \"Estimate\", value: issue.estimate },\n\t\t\t\t\t{ label: \"Due\", value: issue.due },\n\t\t\t\t]}\n\t\t\t/>\n\n\t\t\t{issue.labels.length === 0 ? null : (\n\t\t\t\t<div className={styles.badges}>\n\t\t\t\t\t{issue.labels.map((label) => (\n\t\t\t\t\t\t<Chip key={label} value={label} tone=\"neutral\" />\n\t\t\t\t\t))}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</header>\n\n\t\t<Transitions issue={issue} actions={actions} />\n\t\t<Assignee issue={issue} actions={actions} />\n\n\t\t<Section title=\"Description\">\n\t\t\t{issue.description === undefined ? (\n\t\t\t\t<span className={styles.caption}>No description.</span>\n\t\t\t) : (\n\t\t\t\t<Prose text={issue.description} />\n\t\t\t)}\n\t\t</Section>\n\n\t\t<Section title={`Comments (${issue.comments.length})`}>\n\t\t\t<Comments comments={issue.comments} />\n\t\t</Section>\n\n\t\t{issue.updated === undefined ? null : (\n\t\t\t<span className={styles.caption}>Updated {whenText(issue.updated)}</span>\n\t\t)}\n\t</>\n);\n\n/** One Confluence page: its body and its comments. */\nconst PageView = ({ page }: { page: PagePanel }) => (\n\t<>\n\t\t<header className={styles.panelHead}>\n\t\t\t<div className={styles.panelTitleRow}>\n\t\t\t\t<Chip value=\"Page\" tone=\"neutral\" />\n\t\t\t\t{page.space === undefined ? null : (\n\t\t\t\t\t<span className={styles.panelKey}>{page.space}</span>\n\t\t\t\t)}\n\t\t\t</div>\n\t\t\t<h2 className={styles.panelSummary}>{page.title}</h2>\n\t\t\t{page.url === undefined ? null : (\n\t\t\t\t<a\n\t\t\t\t\tclassName={styles.link}\n\t\t\t\t\thref={page.url}\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t>\n\t\t\t\t\tOpen in Confluence\n\t\t\t\t</a>\n\t\t\t)}\n\t\t</header>\n\n\t\t<Section title=\"Content\">\n\t\t\t{page.body === undefined ? (\n\t\t\t\t<span className={styles.caption}>No content.</span>\n\t\t\t) : (\n\t\t\t\t<Prose text={page.body} />\n\t\t\t)}\n\t\t</Section>\n\n\t\t<Section title={`Comments (${page.comments.length})`}>\n\t\t\t<Comments comments={page.comments} />\n\t\t</Section>\n\t</>\n);\n\n/** Everything the shared panel needs from this plugin. */\nconst provider: PanelProvider<PanelData, PanelTarget> = {\n\temptyMessage: \"This panel was opened without an issue or a page.\",\n\tparseParams: (value) => asPanelTarget(value),\n\tidentity: (target) =>\n\t\ttarget.kind === \"issue\" ? `issue:${target.key}` : `page:${target.id}`,\n\ttitle: (target) =>\n\t\ttarget.kind === \"issue\" ? target.key : (target.title ?? \"Page\"),\n\tfetch: async (target, signal) => await hostApi.getPanel(target, signal),\n\tparse: (value) => asPanelData(value),\n\tview: ({ data, actions }) =>\n\t\tdata.kind === \"issue\" ? (\n\t\t\t<IssueView issue={data} actions={actions} />\n\t\t) : (\n\t\t\t<PageView page={data} />\n\t\t),\n};\n\n/** The panel's body seat. */\nexport const AtlassianPanel = createPanelBody(provider);\n\n/** The panel's title seat. */\nexport const AtlassianPanelTitle = createPanelTitle(provider);\n", "/**\n * What the side panel shows, as the two halves agree on it.\n *\n * The host half resolves an issue or a page through the MCP connection and\n * answers the browser half with one of these documents over `/dsh-atlassian`;\n * the panel renders exactly what it is given. Both halves import these types,\n * and the browser half validates before trusting them, because the two halves\n * can be a version apart while a plugin is being developed.\n */\n\n/** What a panel is opened on. */\nexport type PanelTarget =\n\t| { readonly kind: \"issue\"; readonly key: string }\n\t| { readonly kind: \"page\"; readonly id: string; readonly title?: string };\n\n/** One comment on an issue or a page, in the site's own words. */\nexport type PanelComment = {\n\treadonly author?: string;\n\t/** When it was written, as the server stated it. */\n\treadonly created?: string;\n\t/** Markdown, as Jira or Confluence returned it. */\n\treadonly body: string;\n};\n\n/** A person, as Jira identifies them. */\nexport type PanelPerson = {\n\treadonly name: string;\n\treadonly accountId: string;\n};\n\n/** One status transition the workflow currently offers. */\nexport type PanelTransition = {\n\treadonly id: string;\n\t/** The transition's own name, in the site's language (\"Start progress\"). */\n\treadonly name: string;\n\t/** The status it lands in, when the server names one. */\n\treadonly to?: string;\n\t/** False when the workflow will not offer it for this issue right now. */\n\treadonly available: boolean;\n\t/**\n\t * True when the transition opens a screen.\n\t *\n\t * This panel has no form, so it shows such a transition as unavailable\n\t * rather than sending a call the server will reject for missing fields.\n\t */\n\treadonly needsFields: boolean;\n};\n\n/** Everything the panel shows for one Jira issue. */\nexport type IssuePanel = {\n\treadonly kind: \"issue\";\n\treadonly key: string;\n\treadonly summary?: string;\n\treadonly type?: string;\n\treadonly status?: string;\n\treadonly priority?: string;\n\treadonly assignee?: PanelPerson;\n\treadonly reporter?: string;\n\t/** Jira's own estimate words (\"3d 4h\"). */\n\treadonly estimate?: string;\n\treadonly due?: string;\n\treadonly labels: readonly string[];\n\treadonly created?: string;\n\treadonly updated?: string;\n\t/** The description as Markdown, bounded. */\n\treadonly description?: string;\n\t/** The issue in the browser. */\n\treadonly url?: string;\n\treadonly comments: readonly PanelComment[];\n\treadonly transitions: readonly PanelTransition[];\n};\n\n/** Everything the panel shows for one Confluence page. */\nexport type PagePanel = {\n\treadonly kind: \"page\";\n\treadonly id: string;\n\treadonly title: string;\n\treadonly space?: string;\n\treadonly url?: string;\n\t/** The body as Markdown, bounded. */\n\treadonly body?: string;\n\treadonly comments: readonly PanelComment[];\n};\n\n/** One panel's document. */\nexport type PanelData = IssuePanel | PagePanel;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\nfunction asComments(value: unknown): PanelComment[] {\n\tif (!Array.isArray(value)) return [];\n\n\tconst comments: PanelComment[] = [];\n\tfor (const candidate of value) {\n\t\tif (!isRecord(candidate)) continue;\n\n\t\tconst body = asString(candidate.body);\n\t\tif (body === undefined) continue;\n\n\t\tcomments.push({\n\t\t\tbody,\n\t\t\t...(asString(candidate.author) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { author: asString(candidate.author) }),\n\t\t\t...(asString(candidate.created) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { created: asString(candidate.created) }),\n\t\t});\n\t}\n\n\treturn comments;\n}\n\nfunction asTransitions(value: unknown): PanelTransition[] {\n\tif (!Array.isArray(value)) return [];\n\n\tconst transitions: PanelTransition[] = [];\n\tfor (const candidate of value) {\n\t\tif (!isRecord(candidate)) continue;\n\n\t\tconst id = asString(candidate.id);\n\t\tconst name = asString(candidate.name);\n\t\tif (id === undefined || name === undefined) continue;\n\n\t\ttransitions.push({\n\t\t\tid,\n\t\t\tname,\n\t\t\t...(asString(candidate.to) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { to: asString(candidate.to) }),\n\t\t\tavailable: candidate.available !== false,\n\t\t\tneedsFields: candidate.needsFields === true,\n\t\t});\n\t}\n\n\treturn transitions;\n}\n\nfunction asPerson(value: unknown): PanelPerson | undefined {\n\tif (!isRecord(value)) return undefined;\n\n\tconst name = asString(value.name);\n\tconst accountId = asString(value.accountId);\n\tif (name === undefined || accountId === undefined) return undefined;\n\n\treturn { name, accountId };\n}\n\n/**\n * Narrow one response body to a panel target.\n * @param value - an opaque `params` bag from the sidebar.\n * @returns the target, or undefined when it is not one this version understands.\n */\nexport function asPanelTarget(value: unknown): PanelTarget | undefined {\n\tif (!isRecord(value)) return undefined;\n\n\tif (value.kind === \"issue\") {\n\t\tconst key = asString(value.key);\n\t\treturn key === undefined ? undefined : { kind: \"issue\", key };\n\t}\n\n\tif (value.kind === \"page\") {\n\t\tconst id = asString(value.id);\n\t\tif (id === undefined) return undefined;\n\n\t\treturn {\n\t\t\tkind: \"page\",\n\t\t\tid,\n\t\t\t...(asString(value.title) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { title: asString(value.title) }),\n\t\t};\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Narrow one response body to a panel document.\n * @param value - the parsed JSON the host answered with.\n * @returns the document, or undefined when it is not one this version can draw.\n */\nexport function asPanelData(value: unknown): PanelData | undefined {\n\tif (!isRecord(value)) return undefined;\n\n\tif (value.kind === \"issue\") {\n\t\tconst key = asString(value.key);\n\t\tif (key === undefined) return undefined;\n\n\t\tconst assignee = asPerson(value.assignee);\n\n\t\treturn {\n\t\t\tkind: \"issue\",\n\t\t\tkey,\n\t\t\t...(asString(value.summary) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { summary: asString(value.summary) }),\n\t\t\t...(asString(value.type) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { type: asString(value.type) }),\n\t\t\t...(asString(value.status) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { status: asString(value.status) }),\n\t\t\t...(asString(value.priority) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { priority: asString(value.priority) }),\n\t\t\t...(assignee === undefined ? {} : { assignee }),\n\t\t\t...(asString(value.reporter) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { reporter: asString(value.reporter) }),\n\t\t\t...(asString(value.estimate) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { estimate: asString(value.estimate) }),\n\t\t\t...(asString(value.due) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { due: asString(value.due) }),\n\t\t\tlabels: Array.isArray(value.labels)\n\t\t\t\t? value.labels.filter(\n\t\t\t\t\t\t(item): item is string => typeof item === \"string\",\n\t\t\t\t\t)\n\t\t\t\t: [],\n\t\t\t...(asString(value.created) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { created: asString(value.created) }),\n\t\t\t...(asString(value.updated) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { updated: asString(value.updated) }),\n\t\t\t...(asString(value.description) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { description: asString(value.description) }),\n\t\t\t...(asString(value.url) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { url: asString(value.url) }),\n\t\t\tcomments: asComments(value.comments),\n\t\t\ttransitions: asTransitions(value.transitions),\n\t\t};\n\t}\n\n\tif (value.kind === \"page\") {\n\t\tconst id = asString(value.id);\n\t\tconst title = asString(value.title);\n\t\tif (id === undefined || title === undefined) return undefined;\n\n\t\treturn {\n\t\t\tkind: \"page\",\n\t\t\tid,\n\t\t\ttitle,\n\t\t\t...(asString(value.space) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { space: asString(value.space) }),\n\t\t\t...(asString(value.url) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { url: asString(value.url) }),\n\t\t\t...(asString(value.body) === undefined\n\t\t\t\t? {}\n\t\t\t\t: { body: asString(value.body) }),\n\t\t\tcomments: asComments(value.comments),\n\t\t};\n\t}\n\n\treturn undefined;\n}\n", "/**\n * Putting the compiled stylesheet into the page.\n *\n * The mechanism belongs to `dsh-integration-ui`, and the placeholder the build\n * substitutes the compiled CSS for belongs to `dsh-plugin-build`; what stays\n * here is this plugin's own id, which is what the module system matches when the\n * plugin is turned off.\n */\n\nimport { installStyles } from \"dsh-integration-ui\";\nimport { PLUGIN_ID } from \"../plugin-id\";\n\n/** Replaced with the compiled CSS text at build time. */\ndeclare const __DSH_STYLES__: string;\n\n/**\n * Add the plugin's stylesheet to the document.\n * @returns a disposer that removes it again.\n */\nexport const installAtlassianStyles = (): (() => void) =>\n\tinstallStyles(PLUGIN_ID, __DSH_STYLES__);\n"],
5
+ "mappings": "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",
6
+ "names": ["presentations", "presentation", "card", "presentation", "card", "title", "import_jsx_runtime", "item", "import_dsh_client_ui_primitives", "import_react", "import_jsx_runtime", "error", "provider", "actions", "provider", "import_dsh_client_ui_primitives", "import_react", "import_jsx_runtime", "Section", "error", "field", "card", "import_dsh_client_ui_primitives", "import_jsx_runtime", "item", "item", "actions", "caption", "link", "row", "import_jsx_runtime", "title", "link", "import_jsx_runtime", "link", "import_jsx_runtime", "presentation", "item", "found", "toolLabel", "import_dsh_client_ui_primitives", "import_react", "isRecord", "comments", "item", "title", "import_jsx_runtime", "title", "comments", "caption", "comment", "actions", "person", "people", "found", "row", "link"]
7
+ }