@agimon-ai/doompi-ui 0.0.1-alpha.11 → 0.0.1-alpha.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/pi/extension.cjs +1 -1
- package/dist/adapters/pi/extension.cjs.map +1 -1
- package/dist/adapters/pi/extension.d.cts.map +1 -1
- package/dist/adapters/pi/extension.d.mts.map +1 -1
- package/dist/adapters/pi/extension.mjs +1 -1
- package/dist/adapters/pi/extension.mjs.map +1 -1
- package/dist/adapters/pi/toolOverrides.cjs +2 -0
- package/dist/adapters/pi/toolOverrides.cjs.map +1 -0
- package/dist/adapters/pi/toolOverrides.mjs +2 -0
- package/dist/adapters/pi/toolOverrides.mjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.mjs +1 -1
- package/dist/rendering.cjs +1 -1
- package/dist/rendering.d.cts +2 -2
- package/dist/rendering.d.mts +2 -2
- package/dist/rendering.mjs +1 -1
- package/dist/toolChrome.cjs +1 -0
- package/dist/toolChrome.d.cts +2 -0
- package/dist/toolChrome.d.mts +2 -0
- package/dist/toolChrome.mjs +1 -0
- package/dist/tui/builtinToolRender.cjs +13 -0
- package/dist/tui/builtinToolRender.cjs.map +1 -0
- package/dist/tui/builtinToolRender.mjs +13 -0
- package/dist/tui/builtinToolRender.mjs.map +1 -0
- package/dist/tui/configOverlay.cjs +0 -0
- package/dist/tui/configOverlay.cjs.map +1 -1
- package/dist/tui/configOverlay.d.cts.map +1 -1
- package/dist/tui/configOverlay.d.mts.map +1 -1
- package/dist/tui/configOverlay.mjs +0 -0
- package/dist/tui/configOverlay.mjs.map +1 -1
- package/dist/tui/doomFooter.cjs +1 -1
- package/dist/tui/doomFooter.cjs.map +1 -1
- package/dist/tui/doomFooter.d.cts.map +1 -1
- package/dist/tui/doomFooter.d.mts.map +1 -1
- package/dist/tui/doomFooter.mjs +1 -1
- package/dist/tui/doomFooter.mjs.map +1 -1
- package/dist/tui/leaderHints.cjs +1 -1
- package/dist/tui/leaderHints.cjs.map +1 -1
- package/dist/tui/leaderHints.mjs +1 -1
- package/dist/tui/leaderHints.mjs.map +1 -1
- package/dist/tui/rendering.cjs +1 -1
- package/dist/tui/rendering.cjs.map +1 -1
- package/dist/tui/rendering.d.cts +6 -1
- package/dist/tui/rendering.d.cts.map +1 -1
- package/dist/tui/rendering.d.mts +6 -1
- package/dist/tui/rendering.d.mts.map +1 -1
- package/dist/tui/rendering.mjs +1 -1
- package/dist/tui/rendering.mjs.map +1 -1
- package/dist/tui/theme.cjs +1 -1
- package/dist/tui/theme.cjs.map +1 -1
- package/dist/tui/theme.d.cts +30 -30
- package/dist/tui/theme.d.cts.map +1 -1
- package/dist/tui/theme.d.mts +30 -30
- package/dist/tui/theme.d.mts.map +1 -1
- package/dist/tui/theme.mjs +1 -1
- package/dist/tui/theme.mjs.map +1 -1
- package/dist/tui/toolChrome.cjs +2 -0
- package/dist/tui/toolChrome.cjs.map +1 -0
- package/dist/tui/toolChrome.d.cts +30 -0
- package/dist/tui/toolChrome.d.cts.map +1 -0
- package/dist/tui/toolChrome.d.mts +30 -0
- package/dist/tui/toolChrome.d.mts.map +1 -0
- package/dist/tui/toolChrome.mjs +2 -0
- package/dist/tui/toolChrome.mjs.map +1 -0
- package/dist/tui/toolsOverlay.cjs +1 -1
- package/dist/tui/toolsOverlay.cjs.map +1 -1
- package/dist/tui/toolsOverlay.d.cts.map +1 -1
- package/dist/tui/toolsOverlay.d.mts.map +1 -1
- package/dist/tui/toolsOverlay.mjs +1 -1
- package/dist/tui/toolsOverlay.mjs.map +1 -1
- package/package.json +8 -3
- package/themes/doom-pi-dark.json +30 -30
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../telemetry/logSinkTelemetry.cjs"),n=require("../../config.cjs"),r=require("../../footer.cjs"),i=require("../../services/state/uiState.cjs"),a=require("../../services/leader/leaderRegistry.cjs"),o=require("../../tui/doomEditor.cjs"),s=require("../../tui/doomFooter.cjs"),c=require("../../tui/doomHeader.cjs"),l=require("../../tui/leaderHints.cjs");require("../../tui/theme.cjs");const u=require("../../tui/configOverlay.cjs"),d=require("../../tui/toolsOverlay.cjs"),f=require("../../mode.cjs"),p=require("../../services/tools/toolInventory.cjs");let
|
|
1
|
+
const e=require("../../_virtual/_rolldown/runtime.cjs"),t=require("../telemetry/logSinkTelemetry.cjs"),n=require("../../config.cjs"),r=require("../../footer.cjs"),i=require("../../services/state/uiState.cjs"),a=require("../../services/leader/leaderRegistry.cjs"),o=require("../../tui/doomEditor.cjs"),s=require("../../tui/doomFooter.cjs"),c=require("../../tui/doomHeader.cjs"),l=require("../../tui/leaderHints.cjs");require("../../tui/theme.cjs");const u=require("../../tui/configOverlay.cjs"),d=require("../../tui/toolsOverlay.cjs"),f=require("../../mode.cjs"),p=require("../../services/tools/toolInventory.cjs"),m=require("./toolOverrides.cjs");let h=require("@agimon-ai/doompi-extension-contracts/leader"),g=require("node:path");g=e.__toESM(g,1);let _=require("@agimon-ai/doompi-extension-contracts/mcp-status"),v=require("@agimon-ai/doompi-extension-contracts/protocol");const y=`doom-pi-leader`,b=`belowEditor`,x=`warning`,S=`doom-pi`,C=new Set([`hotkeys`]);function w(e,t){let n=e.trim().replace(/\s+/g,` `);if(!n)return;let r=n.slice(0,64).trimEnd();return`${S} · ${r} · ${g.default.basename(t)||t}`}function T(e,T=t.createUiTelemetry()){m.registerBuiltinToolUi(e,process.cwd());let E=new i.DoomUiState,D=new r.footer_exports.DoomFooterStatusRegistry,O=new f.mode_exports.DoomModeStatusRegistry,k=new n.config_exports.DoomConfigRegistry,A=new a.DoomLeaderRegistry,j=new Set,M=new Map,N,P,F,I,L,R,z,B,V=new Map,H=0,U=0,W=!1,G,K,q=async()=>{if(G)try{return(await G.request(_.McpStatusQueryProtocol,{},{timeoutMs:250})).servers}catch{return}};e.registerCommand(`tools`,{description:`Browse the tools available in this session`,handler:async(t,n)=>{let r=await q(),i=p.buildToolSources({tools:e.getAllTools(),activeTools:e.getActiveTools(),...r?{mcpServers:r}:{}});await d.openToolsOverlay(n,i)}}),e.registerCommand(`config`,{description:`Browse and change the settings extensions contribute`,handler:async(e,t)=>{await u.openConfigOverlay(t,k)}});let J=e=>{for(let n of e){let e=n.bindingId?` (${n.bindingId})`:``,r=`Leader contribution from ${n.source}${e}: ${n.message}`;j.has(r)||(j.add(r),T.recordWarning(t.UI_EVENT.leaderContributionRejected,n.message,{"leader.source":n.source,...n.bindingId?{"leader.binding.id":n.bindingId}:{}}),P?.mode===`tui`&&P.ui.notify(r,x))}},Y=(e,t)=>{let n=Symbol(e.source),r=t?e=>A.registerDeferred(e):e=>A.register(e),i=r(e);if(J(i.diagnostics),!i.accepted)return{update:()=>void 0,dispose:()=>void 0};M.set(e.source,n);let a=!1;return{update(t){a||M.get(e.source)!==n||J(r({source:e.source,bindings:t}).diagnostics)},dispose(){a||(a=!0,M.get(e.source)===n&&(M.delete(e.source),r({source:e.source,bindings:[]})))}}},X=Object.freeze({register(e){let t=Y(e,!1);return()=>t.dispose()}});K=(0,h.installDoomLeaderBootstrapHost)({register:e=>Y(e,!0)}),e.on(`session_start`,(n,r)=>{P=r;let i=++U,a=(0,v.createProtocolRuntime)({bus:e.events,source:`@agimon-ai/doompi-ui`,sessionId:r.sessionManager.getSessionId()});if(G=a,J(A.flush()),F?.(),D.reset(),F=D.bind(a),I?.(),O.reset(),I=O.bind(a),R?.(),k.reset(),R=k.bind(a),z?.(),B?.(),z=a.provide(h.LeaderRegistrationProtocol,({contribution:e,generation:t},n)=>{if(n.source!==e.source)throw Error(`Leader contribution source does not match the registration envelope source.`);let r=`${n.source}:${t}:${++H}`,i={source:e.source,bindings:e.bindings.map(e=>{let[t,...n]=e.path;if(!t)throw Error(`Leader binding '${e.id}' has no path.`);return{...e,path:[t,...n]}})};return V.set(r,X.register(i)),{handleId:r}}),B=a.provide(h.LeaderUnregistrationProtocol,({handleId:e})=>{let t=V.get(e);return t?(V.delete(e),t(),{removed:!0}):{removed:!1}}),W=r.sessionManager.getEntries().some(e=>e.type===`message`),r.mode!==`tui`)return;for(let e of j)r.ui.notify(e,x);let u=process.env.DOOMPI_THEME||`doom-pi-dark`,d=r.ui.setTheme(u);d.success||(r.ui.notify(`Could not apply Doom Pi theme: ${d.error}`,x),T.recordWarning(t.UI_EVENT.themeApplyFailed,d.error??`Unknown theme error`,{"ui.theme":u})),L?.(),L=O.subscribe(()=>E.setModes(O.getStatuses())),E.setModes(O.getStatuses()),r.ui.setTitle(`${S} · ${g.default.basename(r.cwd)||r.cwd} · pi/coding`),r.ui.setHeader((e,t)=>new c.DoomHeader(t,r.cwd,void 0,r,()=>e.terminal.rows)),r.ui.setFooter((e,t,n)=>(N=n,new s.DoomFooter(e,t,r,n,D,E))),r.ui.setEditorComponent((n,s,c)=>new o.DoomEditor(n,s,c,E,e=>{if(!e.active){r.ui.setWidget(y,void 0,{placement:b});return}r.ui.setWidget(y,(t,n)=>new l.LeaderHints(n,e,r,N,E.getModes()),{placement:b})},void 0,r.ui.theme,{registry:A,isCommandAvailable:t=>C.has(t)||e.getCommands().some(e=>e.name===t),onLeaderAction:(e,t)=>{if(P!==r||U!==i){r.ui.notify(`Leader action ${t} is unavailable.`,x);return}a.notify(h.LeaderActionInvoked,{source:e,action:t})},onUnavailableCommand:e=>{T.recordWarning(t.UI_EVENT.leaderCommandUnavailable,`Leader command /${e} is unavailable.`,{"ui.kind":`command`}),r.ui.notify(`Leader command /${e} is unavailable.`,x)},onUnavailableAction:e=>{T.recordWarning(t.UI_EVENT.leaderActionUnavailable,`Leader action ${e} is unavailable.`,{"ui.kind":`action`}),r.ui.notify(`Leader action ${e} is unavailable.`,x)}})),T.recordEvent(t.UI_EVENT.shellInstalled,{"ui.theme":u,"ui.theme.applied":d.success,"ui.leader.group.count":A.getGroup([])?.options.length??0})}),e.on(`input`,(e,t)=>{if(t.mode!==`tui`||e.source!==`interactive`||W)return;W=!0;let n=w(e.text,t.cwd);n&&t.ui.setTitle(n)}),e.on(`session_shutdown`,async(e,t)=>{++U,K?.(),K=void 0;for(let e of V.values())e();V.clear(),P=void 0,N=void 0,F?.(),F=void 0,D.reset(),I?.(),I=void 0,L?.(),L=void 0,O.reset(),R?.(),R=void 0,z?.(),z=void 0,B?.(),B=void 0,k.reset(),E.reset(),G=void 0,t.mode===`tui`&&t.ui.setWidget(y,void 0,{placement:b}),await T.shutdown()})}exports.doomPiUiExtension=T;
|
|
2
2
|
//# sourceMappingURL=extension.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.cjs","names":["path","createUiTelemetry","DoomUiState","DoomLeaderRegistry","McpStatusQueryProtocol","buildToolSources","openToolsOverlay","openConfigOverlay","UI_EVENT","installDoomLeaderBootstrapHost","createProtocolRuntime","LeaderRegistrationProtocol","LeaderUnregistrationProtocol","DoomHeader","DoomFooter","DoomEditor","LeaderHints","LeaderActionInvoked"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import path from 'node:path';\nimport {\n installDoomLeaderBootstrapHost,\n LeaderActionInvoked,\n type LeaderContribution,\n LeaderRegistrationProtocol,\n LeaderUnregistrationProtocol,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport { McpStatusQueryProtocol } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport { createProtocolRuntime, type ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { ExtensionAPI, ExtensionContext, ReadonlyFooterDataProvider } from '@earendil-works/pi-coding-agent';\nimport { DoomConfigRegistry } from '../../config.ts';\nimport { DoomFooterStatusRegistry } from '../../footer.ts';\nimport { DoomModeStatusRegistry } from '../../mode.ts';\nimport { type DoomLeaderDiagnostic, DoomLeaderRegistry } from '../../services/leader/leaderRegistry.ts';\nimport { DoomUiState, type LeaderSnapshot } from '../../services/state/uiState.ts';\nimport { buildToolSources, type McpServerStatus } from '../../services/tools/toolInventory.ts';\nimport { openConfigOverlay } from '../../tui/configOverlay.ts';\nimport { DoomEditor } from '../../tui/doomEditor.ts';\nimport { DoomFooter } from '../../tui/doomFooter.ts';\nimport { DoomHeader } from '../../tui/doomHeader.ts';\nimport { LeaderHints } from '../../tui/leaderHints.ts';\nimport { DEFAULT_THEME_NAME } from '../../tui/theme.ts';\nimport { openToolsOverlay } from '../../tui/toolsOverlay.ts';\nimport { createUiTelemetry, UI_EVENT, type UiTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst LEADER_WIDGET_KEY = 'doom-pi-leader';\nconst TUI_MODE = 'tui';\nconst WIDGET_PLACEMENT = 'belowEditor';\nconst WARNING_STYLE = 'warning';\nconst THEME_ENVIRONMENT_KEY = 'DOOMPI_THEME';\nconst HOTKEYS_COMMAND = 'hotkeys';\nconst TOOLS_COMMAND = 'tools';\nconst CONFIG_COMMAND = 'config';\n/** Short: `/tools` must open promptly whether or not an MCP extension answers. */\nconst MCP_STATUS_TIMEOUT_MS = 250;\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_MESSAGE_ENTRY = 'message';\nconst INPUT_EVENT = 'input';\nconst INTERACTIVE_INPUT_SOURCE = 'interactive';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst TITLE_MESSAGE_MAX_LENGTH = 64;\nconst TITLE_PREFIX = 'doom-pi';\nconst BUILTIN_LEADER_COMMANDS = new Set([HOTKEYS_COMMAND]);\n\nfunction createMessageTitle(message: string, cwd: string): string | undefined {\n const normalizedMessage = message.trim().replace(/\\s+/g, ' ');\n if (!normalizedMessage) return undefined;\n const messageTitle = normalizedMessage.slice(0, TITLE_MESSAGE_MAX_LENGTH).trimEnd();\n return `${TITLE_PREFIX} · ${messageTitle} · ${path.basename(cwd) || cwd}`;\n}\n\nexport function doomPiUiExtension(pi: ExtensionAPI, telemetry: UiTelemetry = createUiTelemetry()): void {\n const uiState = new DoomUiState();\n const footerStatusRegistry = new DoomFooterStatusRegistry();\n const modeStatusRegistry = new DoomModeStatusRegistry();\n const configRegistry = new DoomConfigRegistry();\n const leaderRegistry = new DoomLeaderRegistry();\n const pendingDiagnostics = new Set<string>();\n const contributionGenerations = new Map<string, symbol>();\n let footerData: ReadonlyFooterDataProvider | undefined;\n let activeContext: ExtensionContext | undefined;\n let disposeFooterStatuses: (() => void) | undefined;\n let disposeModeStatuses: (() => void) | undefined;\n let disposeModeSubscription: (() => void) | undefined;\n let disposeConfigContributions: (() => void) | undefined;\n let disposeLeaderRegistration: (() => void) | undefined;\n let disposeLeaderUnregistration: (() => void) | undefined;\n const protocolContributions = new Map<string, () => void>();\n let nextProtocolHandle = 0;\n let sessionGeneration = 0;\n let hasSessionMessage = false;\n let sessionProtocol: ProtocolRuntime | undefined;\n let disposeLeaderBootstrap: (() => void) | undefined;\n\n /**\n * Asks the MCP extension what it is currently connected to.\n *\n * No answer is a normal session: `--no-mcp` leaves nobody providing the query,\n * and the panel simply lists MCP tools under the extension that registered them.\n */\n const readMcpServers = async (): Promise<readonly McpServerStatus[] | undefined> => {\n if (!sessionProtocol) return undefined;\n try {\n const snapshot = await sessionProtocol.request(McpStatusQueryProtocol, {}, { timeoutMs: MCP_STATUS_TIMEOUT_MS });\n return snapshot.servers;\n } catch {\n return undefined;\n }\n };\n\n pi.registerCommand(TOOLS_COMMAND, {\n description: 'Browse the tools available in this session',\n handler: async (_args, ctx) => {\n // Read at open time so a reconnected server or a plan-mode tool swap shows\n // up without restarting the session.\n const mcpServers = await readMcpServers();\n const sources = buildToolSources({\n tools: pi.getAllTools(),\n activeTools: pi.getActiveTools(),\n ...(mcpServers ? { mcpServers } : {}),\n });\n await openToolsOverlay(ctx, sources);\n },\n });\n\n pi.registerCommand(CONFIG_COMMAND, {\n description: 'Browse and change the settings extensions contribute',\n handler: async (_args, ctx) => {\n // The registry is passed live rather than snapshotted: a contributor can be\n // fetching or installing something while the panel is open, and that\n // progress is meant to land in it.\n await openConfigOverlay(ctx, configRegistry);\n },\n });\n\n const reportDiagnostics = (diagnostics: readonly DoomLeaderDiagnostic[]): void => {\n for (const diagnostic of diagnostics) {\n const binding = diagnostic.bindingId ? ` (${diagnostic.bindingId})` : '';\n const message = `Leader contribution from ${diagnostic.source}${binding}: ${diagnostic.message}`;\n if (pendingDiagnostics.has(message)) continue;\n pendingDiagnostics.add(message);\n // A rejected contribution silently drops another extension's keybindings,\n // and the notice below only reaches a run that has a TUI attached.\n void telemetry.recordWarning(UI_EVENT.leaderContributionRejected, diagnostic.message, {\n 'leader.source': diagnostic.source,\n ...(diagnostic.bindingId ? { 'leader.binding.id': diagnostic.bindingId } : {}),\n });\n if (activeContext?.mode === TUI_MODE) activeContext.ui.notify(message, WARNING_STYLE);\n }\n };\n\n const registerLeaderContribution = (contribution: LeaderContribution, deferred: boolean) => {\n const generation = Symbol(contribution.source);\n const register = deferred\n ? (value: LeaderContribution) => leaderRegistry.registerDeferred(value)\n : (value: LeaderContribution) => leaderRegistry.register(value);\n const result = register(contribution);\n reportDiagnostics(result.diagnostics);\n if (!result.accepted) return { update: () => undefined, dispose: () => undefined };\n contributionGenerations.set(contribution.source, generation);\n let disposed = false;\n return {\n update(bindings: LeaderContribution['bindings']) {\n if (disposed || contributionGenerations.get(contribution.source) !== generation) return;\n reportDiagnostics(register({ source: contribution.source, bindings }).diagnostics);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (contributionGenerations.get(contribution.source) !== generation) return;\n contributionGenerations.delete(contribution.source);\n register({ source: contribution.source, bindings: [] });\n },\n };\n };\n\n const leaderContext = Object.freeze({\n register(contribution: LeaderContribution) {\n const handle = registerLeaderContribution(contribution, false);\n return () => handle.dispose();\n },\n });\n // Installed during the UI factory, before the remaining Doom factories run.\n // Their registrations are validated immediately and rebuilt as one batch at\n // session_start, so the first editor always receives the complete keyspace.\n disposeLeaderBootstrap = installDoomLeaderBootstrapHost({\n register: (contribution) => registerLeaderContribution(contribution, true),\n });\n pi.on(SESSION_START_EVENT, (_event, ctx) => {\n activeContext = ctx;\n const activeGeneration = ++sessionGeneration;\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-ui',\n sessionId: ctx.sessionManager.getSessionId(),\n });\n sessionProtocol = protocol;\n reportDiagnostics(leaderRegistry.flush());\n disposeFooterStatuses?.();\n footerStatusRegistry.reset();\n disposeFooterStatuses = footerStatusRegistry.bind(protocol);\n disposeModeStatuses?.();\n modeStatusRegistry.reset();\n disposeModeStatuses = modeStatusRegistry.bind(protocol);\n // Bound above the TUI-mode guard below, like footer and mode: a headless run\n // still accepts contributions, it just never draws them.\n disposeConfigContributions?.();\n configRegistry.reset();\n disposeConfigContributions = configRegistry.bind(protocol);\n disposeLeaderRegistration?.();\n disposeLeaderUnregistration?.();\n disposeLeaderRegistration = protocol.provide(\n LeaderRegistrationProtocol,\n ({ contribution, generation }, identity) => {\n if (identity.source !== contribution.source) {\n throw new Error('Leader contribution source does not match the registration envelope source.');\n }\n const handleId = `${identity.source}:${generation}:${++nextProtocolHandle}`;\n const typedContribution: LeaderContribution = {\n source: contribution.source,\n bindings: contribution.bindings.map((binding) => {\n const [first, ...rest] = binding.path;\n if (!first) throw new Error(`Leader binding '${binding.id}' has no path.`);\n return { ...binding, path: [first, ...rest] };\n }),\n };\n protocolContributions.set(handleId, leaderContext.register(typedContribution));\n return { handleId };\n },\n );\n disposeLeaderUnregistration = protocol.provide(LeaderUnregistrationProtocol, ({ handleId }) => {\n const dispose = protocolContributions.get(handleId);\n if (!dispose) return { removed: false };\n protocolContributions.delete(handleId);\n dispose();\n return { removed: true };\n });\n hasSessionMessage = ctx.sessionManager.getEntries().some((entry) => entry.type === SESSION_MESSAGE_ENTRY);\n if (ctx.mode !== TUI_MODE) return;\n for (const message of pendingDiagnostics) ctx.ui.notify(message, WARNING_STYLE);\n\n const themeName = process.env[THEME_ENVIRONMENT_KEY] || DEFAULT_THEME_NAME;\n const themeResult = ctx.ui.setTheme(themeName);\n if (!themeResult.success) {\n ctx.ui.notify(`Could not apply Doom Pi theme: ${themeResult.error}`, WARNING_STYLE);\n void telemetry.recordWarning(UI_EVENT.themeApplyFailed, themeResult.error ?? 'Unknown theme error', {\n 'ui.theme': themeName,\n });\n }\n\n // The modes go into shared state rather than a widget of their own: the\n // editor prints their names beside its badge and the leader panel prints\n // them with their detail, so there is no third surface to paint.\n disposeModeSubscription?.();\n disposeModeSubscription = modeStatusRegistry.subscribe(() => uiState.setModes(modeStatusRegistry.getStatuses()));\n uiState.setModes(modeStatusRegistry.getStatuses());\n\n ctx.ui.setTitle(`${TITLE_PREFIX} · ${path.basename(ctx.cwd) || ctx.cwd} · pi/coding`);\n ctx.ui.setHeader((tui, theme) => new DoomHeader(theme, ctx.cwd, undefined, ctx, () => tui.terminal.rows));\n ctx.ui.setFooter((tui, theme, data) => {\n footerData = data;\n return new DoomFooter(tui, theme, ctx, data, footerStatusRegistry, uiState);\n });\n ctx.ui.setEditorComponent(\n (tui, editorTheme, keybindings) =>\n new DoomEditor(\n tui,\n editorTheme,\n keybindings,\n uiState,\n (snapshot: LeaderSnapshot) => {\n if (!snapshot.active) {\n ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n return;\n }\n ctx.ui.setWidget(\n LEADER_WIDGET_KEY,\n (_widgetTui, widgetTheme) => new LeaderHints(widgetTheme, snapshot, ctx, footerData, uiState.getModes()),\n { placement: WIDGET_PLACEMENT },\n );\n },\n undefined,\n ctx.ui.theme,\n {\n registry: leaderRegistry,\n isCommandAvailable: (commandName) =>\n BUILTIN_LEADER_COMMANDS.has(commandName) ||\n pi.getCommands().some((command) => command.name === commandName),\n onLeaderAction: (source, action) => {\n if (activeContext !== ctx || sessionGeneration !== activeGeneration) {\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n return;\n }\n protocol.notify(LeaderActionInvoked, { source, action });\n },\n onUnavailableCommand: (commandName) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderCommandUnavailable,\n `Leader command /${commandName} is unavailable.`,\n { 'ui.kind': 'command' },\n );\n ctx.ui.notify(`Leader command /${commandName} is unavailable.`, WARNING_STYLE);\n },\n onUnavailableAction: (action) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderActionUnavailable,\n `Leader action ${action} is unavailable.`,\n {\n 'ui.kind': 'action',\n },\n );\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n },\n },\n ),\n );\n\n void telemetry.recordEvent(UI_EVENT.shellInstalled, {\n 'ui.theme': themeName,\n 'ui.theme.applied': themeResult.success,\n 'ui.leader.group.count': leaderRegistry.getGroup([])?.options.length ?? 0,\n });\n });\n\n pi.on(INPUT_EVENT, (event, ctx) => {\n if (ctx.mode !== TUI_MODE || event.source !== INTERACTIVE_INPUT_SOURCE || hasSessionMessage) return;\n hasSessionMessage = true;\n const title = createMessageTitle(event.text, ctx.cwd);\n if (title) ctx.ui.setTitle(title);\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async (_event, ctx) => {\n ++sessionGeneration;\n disposeLeaderBootstrap?.();\n disposeLeaderBootstrap = undefined;\n for (const dispose of protocolContributions.values()) dispose();\n protocolContributions.clear();\n activeContext = undefined;\n footerData = undefined;\n disposeFooterStatuses?.();\n disposeFooterStatuses = undefined;\n footerStatusRegistry.reset();\n disposeModeStatuses?.();\n disposeModeStatuses = undefined;\n disposeModeSubscription?.();\n disposeModeSubscription = undefined;\n modeStatusRegistry.reset();\n disposeConfigContributions?.();\n disposeConfigContributions = undefined;\n disposeLeaderRegistration?.();\n disposeLeaderRegistration = undefined;\n disposeLeaderUnregistration?.();\n disposeLeaderUnregistration = undefined;\n configRegistry.reset();\n uiState.reset();\n sessionProtocol = undefined;\n if (ctx.mode === TUI_MODE) ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.cjs","names":["path","createUiTelemetry","DoomUiState","DoomLeaderRegistry","McpStatusQueryProtocol","buildToolSources","openToolsOverlay","openConfigOverlay","UI_EVENT","installDoomLeaderBootstrapHost","createProtocolRuntime","LeaderRegistrationProtocol","LeaderUnregistrationProtocol","DoomHeader","DoomFooter","DoomEditor","LeaderHints","LeaderActionInvoked"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import path from 'node:path';\nimport {\n installDoomLeaderBootstrapHost,\n LeaderActionInvoked,\n type LeaderContribution,\n LeaderRegistrationProtocol,\n LeaderUnregistrationProtocol,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport { McpStatusQueryProtocol } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport { createProtocolRuntime, type ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { ExtensionAPI, ExtensionContext, ReadonlyFooterDataProvider } from '@earendil-works/pi-coding-agent';\nimport { DoomConfigRegistry } from '../../config.ts';\nimport { DoomFooterStatusRegistry } from '../../footer.ts';\nimport { DoomModeStatusRegistry } from '../../mode.ts';\nimport { type DoomLeaderDiagnostic, DoomLeaderRegistry } from '../../services/leader/leaderRegistry.ts';\nimport { DoomUiState, type LeaderSnapshot } from '../../services/state/uiState.ts';\nimport { buildToolSources, type McpServerStatus } from '../../services/tools/toolInventory.ts';\nimport { openConfigOverlay } from '../../tui/configOverlay.ts';\nimport { DoomEditor } from '../../tui/doomEditor.ts';\nimport { DoomFooter } from '../../tui/doomFooter.ts';\nimport { DoomHeader } from '../../tui/doomHeader.ts';\nimport { LeaderHints } from '../../tui/leaderHints.ts';\nimport { DEFAULT_THEME_NAME } from '../../tui/theme.ts';\nimport { openToolsOverlay } from '../../tui/toolsOverlay.ts';\nimport { createUiTelemetry, UI_EVENT, type UiTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerBuiltinToolUi } from './toolOverrides.ts';\n\nconst LEADER_WIDGET_KEY = 'doom-pi-leader';\nconst TUI_MODE = 'tui';\nconst WIDGET_PLACEMENT = 'belowEditor';\nconst WARNING_STYLE = 'warning';\nconst THEME_ENVIRONMENT_KEY = 'DOOMPI_THEME';\nconst HOTKEYS_COMMAND = 'hotkeys';\nconst TOOLS_COMMAND = 'tools';\nconst CONFIG_COMMAND = 'config';\n/** Short: `/tools` must open promptly whether or not an MCP extension answers. */\nconst MCP_STATUS_TIMEOUT_MS = 250;\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_MESSAGE_ENTRY = 'message';\nconst INPUT_EVENT = 'input';\nconst INTERACTIVE_INPUT_SOURCE = 'interactive';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst TITLE_MESSAGE_MAX_LENGTH = 64;\nconst TITLE_PREFIX = 'doom-pi';\nconst BUILTIN_LEADER_COMMANDS = new Set([HOTKEYS_COMMAND]);\n\nfunction createMessageTitle(message: string, cwd: string): string | undefined {\n const normalizedMessage = message.trim().replace(/\\s+/g, ' ');\n if (!normalizedMessage) return undefined;\n const messageTitle = normalizedMessage.slice(0, TITLE_MESSAGE_MAX_LENGTH).trimEnd();\n return `${TITLE_PREFIX} · ${messageTitle} · ${path.basename(cwd) || cwd}`;\n}\n\nexport function doomPiUiExtension(pi: ExtensionAPI, telemetry: UiTelemetry = createUiTelemetry()): void {\n registerBuiltinToolUi(pi, process.cwd());\n const uiState = new DoomUiState();\n const footerStatusRegistry = new DoomFooterStatusRegistry();\n const modeStatusRegistry = new DoomModeStatusRegistry();\n const configRegistry = new DoomConfigRegistry();\n const leaderRegistry = new DoomLeaderRegistry();\n const pendingDiagnostics = new Set<string>();\n const contributionGenerations = new Map<string, symbol>();\n let footerData: ReadonlyFooterDataProvider | undefined;\n let activeContext: ExtensionContext | undefined;\n let disposeFooterStatuses: (() => void) | undefined;\n let disposeModeStatuses: (() => void) | undefined;\n let disposeModeSubscription: (() => void) | undefined;\n let disposeConfigContributions: (() => void) | undefined;\n let disposeLeaderRegistration: (() => void) | undefined;\n let disposeLeaderUnregistration: (() => void) | undefined;\n const protocolContributions = new Map<string, () => void>();\n let nextProtocolHandle = 0;\n let sessionGeneration = 0;\n let hasSessionMessage = false;\n let sessionProtocol: ProtocolRuntime | undefined;\n let disposeLeaderBootstrap: (() => void) | undefined;\n\n /**\n * Asks the MCP extension what it is currently connected to.\n *\n * No answer is a normal session: `--no-mcp` leaves nobody providing the query,\n * and the panel simply lists MCP tools under the extension that registered them.\n */\n const readMcpServers = async (): Promise<readonly McpServerStatus[] | undefined> => {\n if (!sessionProtocol) return undefined;\n try {\n const snapshot = await sessionProtocol.request(McpStatusQueryProtocol, {}, { timeoutMs: MCP_STATUS_TIMEOUT_MS });\n return snapshot.servers;\n } catch {\n return undefined;\n }\n };\n\n pi.registerCommand(TOOLS_COMMAND, {\n description: 'Browse the tools available in this session',\n handler: async (_args, ctx) => {\n // Read at open time so a reconnected server or a plan-mode tool swap shows\n // up without restarting the session.\n const mcpServers = await readMcpServers();\n const sources = buildToolSources({\n tools: pi.getAllTools(),\n activeTools: pi.getActiveTools(),\n ...(mcpServers ? { mcpServers } : {}),\n });\n await openToolsOverlay(ctx, sources);\n },\n });\n\n pi.registerCommand(CONFIG_COMMAND, {\n description: 'Browse and change the settings extensions contribute',\n handler: async (_args, ctx) => {\n // The registry is passed live rather than snapshotted: a contributor can be\n // fetching or installing something while the panel is open, and that\n // progress is meant to land in it.\n await openConfigOverlay(ctx, configRegistry);\n },\n });\n\n const reportDiagnostics = (diagnostics: readonly DoomLeaderDiagnostic[]): void => {\n for (const diagnostic of diagnostics) {\n const binding = diagnostic.bindingId ? ` (${diagnostic.bindingId})` : '';\n const message = `Leader contribution from ${diagnostic.source}${binding}: ${diagnostic.message}`;\n if (pendingDiagnostics.has(message)) continue;\n pendingDiagnostics.add(message);\n // A rejected contribution silently drops another extension's keybindings,\n // and the notice below only reaches a run that has a TUI attached.\n void telemetry.recordWarning(UI_EVENT.leaderContributionRejected, diagnostic.message, {\n 'leader.source': diagnostic.source,\n ...(diagnostic.bindingId ? { 'leader.binding.id': diagnostic.bindingId } : {}),\n });\n if (activeContext?.mode === TUI_MODE) activeContext.ui.notify(message, WARNING_STYLE);\n }\n };\n\n const registerLeaderContribution = (contribution: LeaderContribution, deferred: boolean) => {\n const generation = Symbol(contribution.source);\n const register = deferred\n ? (value: LeaderContribution) => leaderRegistry.registerDeferred(value)\n : (value: LeaderContribution) => leaderRegistry.register(value);\n const result = register(contribution);\n reportDiagnostics(result.diagnostics);\n if (!result.accepted) return { update: () => undefined, dispose: () => undefined };\n contributionGenerations.set(contribution.source, generation);\n let disposed = false;\n return {\n update(bindings: LeaderContribution['bindings']) {\n if (disposed || contributionGenerations.get(contribution.source) !== generation) return;\n reportDiagnostics(register({ source: contribution.source, bindings }).diagnostics);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (contributionGenerations.get(contribution.source) !== generation) return;\n contributionGenerations.delete(contribution.source);\n register({ source: contribution.source, bindings: [] });\n },\n };\n };\n\n const leaderContext = Object.freeze({\n register(contribution: LeaderContribution) {\n const handle = registerLeaderContribution(contribution, false);\n return () => handle.dispose();\n },\n });\n // Installed during the UI factory, before the remaining Doom factories run.\n // Their registrations are validated immediately and rebuilt as one batch at\n // session_start, so the first editor always receives the complete keyspace.\n disposeLeaderBootstrap = installDoomLeaderBootstrapHost({\n register: (contribution) => registerLeaderContribution(contribution, true),\n });\n pi.on(SESSION_START_EVENT, (_event, ctx) => {\n activeContext = ctx;\n const activeGeneration = ++sessionGeneration;\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-ui',\n sessionId: ctx.sessionManager.getSessionId(),\n });\n sessionProtocol = protocol;\n reportDiagnostics(leaderRegistry.flush());\n disposeFooterStatuses?.();\n footerStatusRegistry.reset();\n disposeFooterStatuses = footerStatusRegistry.bind(protocol);\n disposeModeStatuses?.();\n modeStatusRegistry.reset();\n disposeModeStatuses = modeStatusRegistry.bind(protocol);\n // Bound above the TUI-mode guard below, like footer and mode: a headless run\n // still accepts contributions, it just never draws them.\n disposeConfigContributions?.();\n configRegistry.reset();\n disposeConfigContributions = configRegistry.bind(protocol);\n disposeLeaderRegistration?.();\n disposeLeaderUnregistration?.();\n disposeLeaderRegistration = protocol.provide(\n LeaderRegistrationProtocol,\n ({ contribution, generation }, identity) => {\n if (identity.source !== contribution.source) {\n throw new Error('Leader contribution source does not match the registration envelope source.');\n }\n const handleId = `${identity.source}:${generation}:${++nextProtocolHandle}`;\n const typedContribution: LeaderContribution = {\n source: contribution.source,\n bindings: contribution.bindings.map((binding) => {\n const [first, ...rest] = binding.path;\n if (!first) throw new Error(`Leader binding '${binding.id}' has no path.`);\n return { ...binding, path: [first, ...rest] };\n }),\n };\n protocolContributions.set(handleId, leaderContext.register(typedContribution));\n return { handleId };\n },\n );\n disposeLeaderUnregistration = protocol.provide(LeaderUnregistrationProtocol, ({ handleId }) => {\n const dispose = protocolContributions.get(handleId);\n if (!dispose) return { removed: false };\n protocolContributions.delete(handleId);\n dispose();\n return { removed: true };\n });\n hasSessionMessage = ctx.sessionManager.getEntries().some((entry) => entry.type === SESSION_MESSAGE_ENTRY);\n if (ctx.mode !== TUI_MODE) return;\n for (const message of pendingDiagnostics) ctx.ui.notify(message, WARNING_STYLE);\n\n const themeName = process.env[THEME_ENVIRONMENT_KEY] || DEFAULT_THEME_NAME;\n const themeResult = ctx.ui.setTheme(themeName);\n if (!themeResult.success) {\n ctx.ui.notify(`Could not apply Doom Pi theme: ${themeResult.error}`, WARNING_STYLE);\n void telemetry.recordWarning(UI_EVENT.themeApplyFailed, themeResult.error ?? 'Unknown theme error', {\n 'ui.theme': themeName,\n });\n }\n\n // The modes go into shared state rather than a widget of their own: the\n // editor prints their names beside its badge and the leader panel prints\n // them with their detail, so there is no third surface to paint.\n disposeModeSubscription?.();\n disposeModeSubscription = modeStatusRegistry.subscribe(() => uiState.setModes(modeStatusRegistry.getStatuses()));\n uiState.setModes(modeStatusRegistry.getStatuses());\n\n ctx.ui.setTitle(`${TITLE_PREFIX} · ${path.basename(ctx.cwd) || ctx.cwd} · pi/coding`);\n ctx.ui.setHeader((tui, theme) => new DoomHeader(theme, ctx.cwd, undefined, ctx, () => tui.terminal.rows));\n ctx.ui.setFooter((tui, theme, data) => {\n footerData = data;\n return new DoomFooter(tui, theme, ctx, data, footerStatusRegistry, uiState);\n });\n ctx.ui.setEditorComponent(\n (tui, editorTheme, keybindings) =>\n new DoomEditor(\n tui,\n editorTheme,\n keybindings,\n uiState,\n (snapshot: LeaderSnapshot) => {\n if (!snapshot.active) {\n ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n return;\n }\n ctx.ui.setWidget(\n LEADER_WIDGET_KEY,\n (_widgetTui, widgetTheme) => new LeaderHints(widgetTheme, snapshot, ctx, footerData, uiState.getModes()),\n { placement: WIDGET_PLACEMENT },\n );\n },\n undefined,\n ctx.ui.theme,\n {\n registry: leaderRegistry,\n isCommandAvailable: (commandName) =>\n BUILTIN_LEADER_COMMANDS.has(commandName) ||\n pi.getCommands().some((command) => command.name === commandName),\n onLeaderAction: (source, action) => {\n if (activeContext !== ctx || sessionGeneration !== activeGeneration) {\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n return;\n }\n protocol.notify(LeaderActionInvoked, { source, action });\n },\n onUnavailableCommand: (commandName) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderCommandUnavailable,\n `Leader command /${commandName} is unavailable.`,\n { 'ui.kind': 'command' },\n );\n ctx.ui.notify(`Leader command /${commandName} is unavailable.`, WARNING_STYLE);\n },\n onUnavailableAction: (action) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderActionUnavailable,\n `Leader action ${action} is unavailable.`,\n {\n 'ui.kind': 'action',\n },\n );\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n },\n },\n ),\n );\n\n void telemetry.recordEvent(UI_EVENT.shellInstalled, {\n 'ui.theme': themeName,\n 'ui.theme.applied': themeResult.success,\n 'ui.leader.group.count': leaderRegistry.getGroup([])?.options.length ?? 0,\n });\n });\n\n pi.on(INPUT_EVENT, (event, ctx) => {\n if (ctx.mode !== TUI_MODE || event.source !== INTERACTIVE_INPUT_SOURCE || hasSessionMessage) return;\n hasSessionMessage = true;\n const title = createMessageTitle(event.text, ctx.cwd);\n if (title) ctx.ui.setTitle(title);\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async (_event, ctx) => {\n ++sessionGeneration;\n disposeLeaderBootstrap?.();\n disposeLeaderBootstrap = undefined;\n for (const dispose of protocolContributions.values()) dispose();\n protocolContributions.clear();\n activeContext = undefined;\n footerData = undefined;\n disposeFooterStatuses?.();\n disposeFooterStatuses = undefined;\n footerStatusRegistry.reset();\n disposeModeStatuses?.();\n disposeModeStatuses = undefined;\n disposeModeSubscription?.();\n disposeModeSubscription = undefined;\n modeStatusRegistry.reset();\n disposeConfigContributions?.();\n disposeConfigContributions = undefined;\n disposeLeaderRegistration?.();\n disposeLeaderRegistration = undefined;\n disposeLeaderUnregistration?.();\n disposeLeaderUnregistration = undefined;\n configRegistry.reset();\n uiState.reset();\n sessionProtocol = undefined;\n if (ctx.mode === TUI_MODE) ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"extension.d.cts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;iBAqDgB,kBAAkB,IAAI,cAAc,YAAW"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"extension.d.mts","names":[],"sources":["../../../src/adapters/pi/extension.ts"],"mappings":";;;iBAqDgB,kBAAkB,IAAI,cAAc,YAAW"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{UI_EVENT as e,createUiTelemetry as t}from"../telemetry/logSinkTelemetry.mjs";import{config_exports as n}from"../../config.mjs";import{footer_exports as r}from"../../footer.mjs";import{DoomUiState as i}from"../../services/state/uiState.mjs";import{DoomLeaderRegistry as a}from"../../services/leader/leaderRegistry.mjs";import{DoomEditor as o}from"../../tui/doomEditor.mjs";import{DoomFooter as s}from"../../tui/doomFooter.mjs";import{DoomHeader as c}from"../../tui/doomHeader.mjs";import{LeaderHints as l}from"../../tui/leaderHints.mjs";import"../../tui/theme.mjs";import{openConfigOverlay as u}from"../../tui/configOverlay.mjs";import{openToolsOverlay as d}from"../../tui/toolsOverlay.mjs";import{mode_exports as f}from"../../mode.mjs";import{buildToolSources as p}from"../../services/tools/toolInventory.mjs";import{LeaderActionInvoked as
|
|
1
|
+
import{UI_EVENT as e,createUiTelemetry as t}from"../telemetry/logSinkTelemetry.mjs";import{config_exports as n}from"../../config.mjs";import{footer_exports as r}from"../../footer.mjs";import{DoomUiState as i}from"../../services/state/uiState.mjs";import{DoomLeaderRegistry as a}from"../../services/leader/leaderRegistry.mjs";import{DoomEditor as o}from"../../tui/doomEditor.mjs";import{DoomFooter as s}from"../../tui/doomFooter.mjs";import{DoomHeader as c}from"../../tui/doomHeader.mjs";import{LeaderHints as l}from"../../tui/leaderHints.mjs";import"../../tui/theme.mjs";import{openConfigOverlay as u}from"../../tui/configOverlay.mjs";import{openToolsOverlay as d}from"../../tui/toolsOverlay.mjs";import{mode_exports as f}from"../../mode.mjs";import{buildToolSources as p}from"../../services/tools/toolInventory.mjs";import{registerBuiltinToolUi as m}from"./toolOverrides.mjs";import{LeaderActionInvoked as h,LeaderRegistrationProtocol as g,LeaderUnregistrationProtocol as _,installDoomLeaderBootstrapHost as v}from"@agimon-ai/doompi-extension-contracts/leader";import y from"node:path";import{McpStatusQueryProtocol as b}from"@agimon-ai/doompi-extension-contracts/mcp-status";import{createProtocolRuntime as x}from"@agimon-ai/doompi-extension-contracts/protocol";const S=`doom-pi-leader`,C=`belowEditor`,w=`warning`,T=`doom-pi`,E=new Set([`hotkeys`]);function D(e,t){let n=e.trim().replace(/\s+/g,` `);if(!n)return;let r=n.slice(0,64).trimEnd();return`${T} · ${r} · ${y.basename(t)||t}`}function O(O,k=t()){m(O,process.cwd());let A=new i,j=new r.DoomFooterStatusRegistry,M=new f.DoomModeStatusRegistry,N=new n.DoomConfigRegistry,P=new a,F=new Set,I=new Map,L,R,z,B,V,H,U,W,G=new Map,K=0,q=0,J=!1,Y,X,Z=async()=>{if(Y)try{return(await Y.request(b,{},{timeoutMs:250})).servers}catch{return}};O.registerCommand(`tools`,{description:`Browse the tools available in this session`,handler:async(e,t)=>{let n=await Z(),r=p({tools:O.getAllTools(),activeTools:O.getActiveTools(),...n?{mcpServers:n}:{}});await d(t,r)}}),O.registerCommand(`config`,{description:`Browse and change the settings extensions contribute`,handler:async(e,t)=>{await u(t,N)}});let Q=t=>{for(let n of t){let t=n.bindingId?` (${n.bindingId})`:``,r=`Leader contribution from ${n.source}${t}: ${n.message}`;F.has(r)||(F.add(r),k.recordWarning(e.leaderContributionRejected,n.message,{"leader.source":n.source,...n.bindingId?{"leader.binding.id":n.bindingId}:{}}),R?.mode===`tui`&&R.ui.notify(r,w))}},$=(e,t)=>{let n=Symbol(e.source),r=t?e=>P.registerDeferred(e):e=>P.register(e),i=r(e);if(Q(i.diagnostics),!i.accepted)return{update:()=>void 0,dispose:()=>void 0};I.set(e.source,n);let a=!1;return{update(t){a||I.get(e.source)!==n||Q(r({source:e.source,bindings:t}).diagnostics)},dispose(){a||(a=!0,I.get(e.source)===n&&(I.delete(e.source),r({source:e.source,bindings:[]})))}}},ee=Object.freeze({register(e){let t=$(e,!1);return()=>t.dispose()}});X=v({register:e=>$(e,!0)}),O.on(`session_start`,(t,n)=>{R=n;let r=++q,i=x({bus:O.events,source:`@agimon-ai/doompi-ui`,sessionId:n.sessionManager.getSessionId()});if(Y=i,Q(P.flush()),z?.(),j.reset(),z=j.bind(i),B?.(),M.reset(),B=M.bind(i),H?.(),N.reset(),H=N.bind(i),U?.(),W?.(),U=i.provide(g,({contribution:e,generation:t},n)=>{if(n.source!==e.source)throw Error(`Leader contribution source does not match the registration envelope source.`);let r=`${n.source}:${t}:${++K}`,i={source:e.source,bindings:e.bindings.map(e=>{let[t,...n]=e.path;if(!t)throw Error(`Leader binding '${e.id}' has no path.`);return{...e,path:[t,...n]}})};return G.set(r,ee.register(i)),{handleId:r}}),W=i.provide(_,({handleId:e})=>{let t=G.get(e);return t?(G.delete(e),t(),{removed:!0}):{removed:!1}}),J=n.sessionManager.getEntries().some(e=>e.type===`message`),n.mode!==`tui`)return;for(let e of F)n.ui.notify(e,w);let a=process.env.DOOMPI_THEME||`doom-pi-dark`,u=n.ui.setTheme(a);u.success||(n.ui.notify(`Could not apply Doom Pi theme: ${u.error}`,w),k.recordWarning(e.themeApplyFailed,u.error??`Unknown theme error`,{"ui.theme":a})),V?.(),V=M.subscribe(()=>A.setModes(M.getStatuses())),A.setModes(M.getStatuses()),n.ui.setTitle(`${T} · ${y.basename(n.cwd)||n.cwd} · pi/coding`),n.ui.setHeader((e,t)=>new c(t,n.cwd,void 0,n,()=>e.terminal.rows)),n.ui.setFooter((e,t,r)=>(L=r,new s(e,t,n,r,j,A))),n.ui.setEditorComponent((t,a,s)=>new o(t,a,s,A,e=>{if(!e.active){n.ui.setWidget(S,void 0,{placement:C});return}n.ui.setWidget(S,(t,r)=>new l(r,e,n,L,A.getModes()),{placement:C})},void 0,n.ui.theme,{registry:P,isCommandAvailable:e=>E.has(e)||O.getCommands().some(t=>t.name===e),onLeaderAction:(e,t)=>{if(R!==n||q!==r){n.ui.notify(`Leader action ${t} is unavailable.`,w);return}i.notify(h,{source:e,action:t})},onUnavailableCommand:t=>{k.recordWarning(e.leaderCommandUnavailable,`Leader command /${t} is unavailable.`,{"ui.kind":`command`}),n.ui.notify(`Leader command /${t} is unavailable.`,w)},onUnavailableAction:t=>{k.recordWarning(e.leaderActionUnavailable,`Leader action ${t} is unavailable.`,{"ui.kind":`action`}),n.ui.notify(`Leader action ${t} is unavailable.`,w)}})),k.recordEvent(e.shellInstalled,{"ui.theme":a,"ui.theme.applied":u.success,"ui.leader.group.count":P.getGroup([])?.options.length??0})}),O.on(`input`,(e,t)=>{if(t.mode!==`tui`||e.source!==`interactive`||J)return;J=!0;let n=D(e.text,t.cwd);n&&t.ui.setTitle(n)}),O.on(`session_shutdown`,async(e,t)=>{++q,X?.(),X=void 0;for(let e of G.values())e();G.clear(),R=void 0,L=void 0,z?.(),z=void 0,j.reset(),B?.(),B=void 0,V?.(),V=void 0,M.reset(),H?.(),H=void 0,U?.(),U=void 0,W?.(),W=void 0,N.reset(),A.reset(),Y=void 0,t.mode===`tui`&&t.ui.setWidget(S,void 0,{placement:C}),await k.shutdown()})}export{O as doomPiUiExtension};
|
|
2
2
|
//# sourceMappingURL=extension.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extension.mjs","names":["DoomFooterStatusRegistry","DoomModeStatusRegistry","DoomConfigRegistry"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import path from 'node:path';\nimport {\n installDoomLeaderBootstrapHost,\n LeaderActionInvoked,\n type LeaderContribution,\n LeaderRegistrationProtocol,\n LeaderUnregistrationProtocol,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport { McpStatusQueryProtocol } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport { createProtocolRuntime, type ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { ExtensionAPI, ExtensionContext, ReadonlyFooterDataProvider } from '@earendil-works/pi-coding-agent';\nimport { DoomConfigRegistry } from '../../config.ts';\nimport { DoomFooterStatusRegistry } from '../../footer.ts';\nimport { DoomModeStatusRegistry } from '../../mode.ts';\nimport { type DoomLeaderDiagnostic, DoomLeaderRegistry } from '../../services/leader/leaderRegistry.ts';\nimport { DoomUiState, type LeaderSnapshot } from '../../services/state/uiState.ts';\nimport { buildToolSources, type McpServerStatus } from '../../services/tools/toolInventory.ts';\nimport { openConfigOverlay } from '../../tui/configOverlay.ts';\nimport { DoomEditor } from '../../tui/doomEditor.ts';\nimport { DoomFooter } from '../../tui/doomFooter.ts';\nimport { DoomHeader } from '../../tui/doomHeader.ts';\nimport { LeaderHints } from '../../tui/leaderHints.ts';\nimport { DEFAULT_THEME_NAME } from '../../tui/theme.ts';\nimport { openToolsOverlay } from '../../tui/toolsOverlay.ts';\nimport { createUiTelemetry, UI_EVENT, type UiTelemetry } from '../telemetry/logSinkTelemetry.ts';\n\nconst LEADER_WIDGET_KEY = 'doom-pi-leader';\nconst TUI_MODE = 'tui';\nconst WIDGET_PLACEMENT = 'belowEditor';\nconst WARNING_STYLE = 'warning';\nconst THEME_ENVIRONMENT_KEY = 'DOOMPI_THEME';\nconst HOTKEYS_COMMAND = 'hotkeys';\nconst TOOLS_COMMAND = 'tools';\nconst CONFIG_COMMAND = 'config';\n/** Short: `/tools` must open promptly whether or not an MCP extension answers. */\nconst MCP_STATUS_TIMEOUT_MS = 250;\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_MESSAGE_ENTRY = 'message';\nconst INPUT_EVENT = 'input';\nconst INTERACTIVE_INPUT_SOURCE = 'interactive';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst TITLE_MESSAGE_MAX_LENGTH = 64;\nconst TITLE_PREFIX = 'doom-pi';\nconst BUILTIN_LEADER_COMMANDS = new Set([HOTKEYS_COMMAND]);\n\nfunction createMessageTitle(message: string, cwd: string): string | undefined {\n const normalizedMessage = message.trim().replace(/\\s+/g, ' ');\n if (!normalizedMessage) return undefined;\n const messageTitle = normalizedMessage.slice(0, TITLE_MESSAGE_MAX_LENGTH).trimEnd();\n return `${TITLE_PREFIX} · ${messageTitle} · ${path.basename(cwd) || cwd}`;\n}\n\nexport function doomPiUiExtension(pi: ExtensionAPI, telemetry: UiTelemetry = createUiTelemetry()): void {\n const uiState = new DoomUiState();\n const footerStatusRegistry = new DoomFooterStatusRegistry();\n const modeStatusRegistry = new DoomModeStatusRegistry();\n const configRegistry = new DoomConfigRegistry();\n const leaderRegistry = new DoomLeaderRegistry();\n const pendingDiagnostics = new Set<string>();\n const contributionGenerations = new Map<string, symbol>();\n let footerData: ReadonlyFooterDataProvider | undefined;\n let activeContext: ExtensionContext | undefined;\n let disposeFooterStatuses: (() => void) | undefined;\n let disposeModeStatuses: (() => void) | undefined;\n let disposeModeSubscription: (() => void) | undefined;\n let disposeConfigContributions: (() => void) | undefined;\n let disposeLeaderRegistration: (() => void) | undefined;\n let disposeLeaderUnregistration: (() => void) | undefined;\n const protocolContributions = new Map<string, () => void>();\n let nextProtocolHandle = 0;\n let sessionGeneration = 0;\n let hasSessionMessage = false;\n let sessionProtocol: ProtocolRuntime | undefined;\n let disposeLeaderBootstrap: (() => void) | undefined;\n\n /**\n * Asks the MCP extension what it is currently connected to.\n *\n * No answer is a normal session: `--no-mcp` leaves nobody providing the query,\n * and the panel simply lists MCP tools under the extension that registered them.\n */\n const readMcpServers = async (): Promise<readonly McpServerStatus[] | undefined> => {\n if (!sessionProtocol) return undefined;\n try {\n const snapshot = await sessionProtocol.request(McpStatusQueryProtocol, {}, { timeoutMs: MCP_STATUS_TIMEOUT_MS });\n return snapshot.servers;\n } catch {\n return undefined;\n }\n };\n\n pi.registerCommand(TOOLS_COMMAND, {\n description: 'Browse the tools available in this session',\n handler: async (_args, ctx) => {\n // Read at open time so a reconnected server or a plan-mode tool swap shows\n // up without restarting the session.\n const mcpServers = await readMcpServers();\n const sources = buildToolSources({\n tools: pi.getAllTools(),\n activeTools: pi.getActiveTools(),\n ...(mcpServers ? { mcpServers } : {}),\n });\n await openToolsOverlay(ctx, sources);\n },\n });\n\n pi.registerCommand(CONFIG_COMMAND, {\n description: 'Browse and change the settings extensions contribute',\n handler: async (_args, ctx) => {\n // The registry is passed live rather than snapshotted: a contributor can be\n // fetching or installing something while the panel is open, and that\n // progress is meant to land in it.\n await openConfigOverlay(ctx, configRegistry);\n },\n });\n\n const reportDiagnostics = (diagnostics: readonly DoomLeaderDiagnostic[]): void => {\n for (const diagnostic of diagnostics) {\n const binding = diagnostic.bindingId ? ` (${diagnostic.bindingId})` : '';\n const message = `Leader contribution from ${diagnostic.source}${binding}: ${diagnostic.message}`;\n if (pendingDiagnostics.has(message)) continue;\n pendingDiagnostics.add(message);\n // A rejected contribution silently drops another extension's keybindings,\n // and the notice below only reaches a run that has a TUI attached.\n void telemetry.recordWarning(UI_EVENT.leaderContributionRejected, diagnostic.message, {\n 'leader.source': diagnostic.source,\n ...(diagnostic.bindingId ? { 'leader.binding.id': diagnostic.bindingId } : {}),\n });\n if (activeContext?.mode === TUI_MODE) activeContext.ui.notify(message, WARNING_STYLE);\n }\n };\n\n const registerLeaderContribution = (contribution: LeaderContribution, deferred: boolean) => {\n const generation = Symbol(contribution.source);\n const register = deferred\n ? (value: LeaderContribution) => leaderRegistry.registerDeferred(value)\n : (value: LeaderContribution) => leaderRegistry.register(value);\n const result = register(contribution);\n reportDiagnostics(result.diagnostics);\n if (!result.accepted) return { update: () => undefined, dispose: () => undefined };\n contributionGenerations.set(contribution.source, generation);\n let disposed = false;\n return {\n update(bindings: LeaderContribution['bindings']) {\n if (disposed || contributionGenerations.get(contribution.source) !== generation) return;\n reportDiagnostics(register({ source: contribution.source, bindings }).diagnostics);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (contributionGenerations.get(contribution.source) !== generation) return;\n contributionGenerations.delete(contribution.source);\n register({ source: contribution.source, bindings: [] });\n },\n };\n };\n\n const leaderContext = Object.freeze({\n register(contribution: LeaderContribution) {\n const handle = registerLeaderContribution(contribution, false);\n return () => handle.dispose();\n },\n });\n // Installed during the UI factory, before the remaining Doom factories run.\n // Their registrations are validated immediately and rebuilt as one batch at\n // session_start, so the first editor always receives the complete keyspace.\n disposeLeaderBootstrap = installDoomLeaderBootstrapHost({\n register: (contribution) => registerLeaderContribution(contribution, true),\n });\n pi.on(SESSION_START_EVENT, (_event, ctx) => {\n activeContext = ctx;\n const activeGeneration = ++sessionGeneration;\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-ui',\n sessionId: ctx.sessionManager.getSessionId(),\n });\n sessionProtocol = protocol;\n reportDiagnostics(leaderRegistry.flush());\n disposeFooterStatuses?.();\n footerStatusRegistry.reset();\n disposeFooterStatuses = footerStatusRegistry.bind(protocol);\n disposeModeStatuses?.();\n modeStatusRegistry.reset();\n disposeModeStatuses = modeStatusRegistry.bind(protocol);\n // Bound above the TUI-mode guard below, like footer and mode: a headless run\n // still accepts contributions, it just never draws them.\n disposeConfigContributions?.();\n configRegistry.reset();\n disposeConfigContributions = configRegistry.bind(protocol);\n disposeLeaderRegistration?.();\n disposeLeaderUnregistration?.();\n disposeLeaderRegistration = protocol.provide(\n LeaderRegistrationProtocol,\n ({ contribution, generation }, identity) => {\n if (identity.source !== contribution.source) {\n throw new Error('Leader contribution source does not match the registration envelope source.');\n }\n const handleId = `${identity.source}:${generation}:${++nextProtocolHandle}`;\n const typedContribution: LeaderContribution = {\n source: contribution.source,\n bindings: contribution.bindings.map((binding) => {\n const [first, ...rest] = binding.path;\n if (!first) throw new Error(`Leader binding '${binding.id}' has no path.`);\n return { ...binding, path: [first, ...rest] };\n }),\n };\n protocolContributions.set(handleId, leaderContext.register(typedContribution));\n return { handleId };\n },\n );\n disposeLeaderUnregistration = protocol.provide(LeaderUnregistrationProtocol, ({ handleId }) => {\n const dispose = protocolContributions.get(handleId);\n if (!dispose) return { removed: false };\n protocolContributions.delete(handleId);\n dispose();\n return { removed: true };\n });\n hasSessionMessage = ctx.sessionManager.getEntries().some((entry) => entry.type === SESSION_MESSAGE_ENTRY);\n if (ctx.mode !== TUI_MODE) return;\n for (const message of pendingDiagnostics) ctx.ui.notify(message, WARNING_STYLE);\n\n const themeName = process.env[THEME_ENVIRONMENT_KEY] || DEFAULT_THEME_NAME;\n const themeResult = ctx.ui.setTheme(themeName);\n if (!themeResult.success) {\n ctx.ui.notify(`Could not apply Doom Pi theme: ${themeResult.error}`, WARNING_STYLE);\n void telemetry.recordWarning(UI_EVENT.themeApplyFailed, themeResult.error ?? 'Unknown theme error', {\n 'ui.theme': themeName,\n });\n }\n\n // The modes go into shared state rather than a widget of their own: the\n // editor prints their names beside its badge and the leader panel prints\n // them with their detail, so there is no third surface to paint.\n disposeModeSubscription?.();\n disposeModeSubscription = modeStatusRegistry.subscribe(() => uiState.setModes(modeStatusRegistry.getStatuses()));\n uiState.setModes(modeStatusRegistry.getStatuses());\n\n ctx.ui.setTitle(`${TITLE_PREFIX} · ${path.basename(ctx.cwd) || ctx.cwd} · pi/coding`);\n ctx.ui.setHeader((tui, theme) => new DoomHeader(theme, ctx.cwd, undefined, ctx, () => tui.terminal.rows));\n ctx.ui.setFooter((tui, theme, data) => {\n footerData = data;\n return new DoomFooter(tui, theme, ctx, data, footerStatusRegistry, uiState);\n });\n ctx.ui.setEditorComponent(\n (tui, editorTheme, keybindings) =>\n new DoomEditor(\n tui,\n editorTheme,\n keybindings,\n uiState,\n (snapshot: LeaderSnapshot) => {\n if (!snapshot.active) {\n ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n return;\n }\n ctx.ui.setWidget(\n LEADER_WIDGET_KEY,\n (_widgetTui, widgetTheme) => new LeaderHints(widgetTheme, snapshot, ctx, footerData, uiState.getModes()),\n { placement: WIDGET_PLACEMENT },\n );\n },\n undefined,\n ctx.ui.theme,\n {\n registry: leaderRegistry,\n isCommandAvailable: (commandName) =>\n BUILTIN_LEADER_COMMANDS.has(commandName) ||\n pi.getCommands().some((command) => command.name === commandName),\n onLeaderAction: (source, action) => {\n if (activeContext !== ctx || sessionGeneration !== activeGeneration) {\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n return;\n }\n protocol.notify(LeaderActionInvoked, { source, action });\n },\n onUnavailableCommand: (commandName) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderCommandUnavailable,\n `Leader command /${commandName} is unavailable.`,\n { 'ui.kind': 'command' },\n );\n ctx.ui.notify(`Leader command /${commandName} is unavailable.`, WARNING_STYLE);\n },\n onUnavailableAction: (action) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderActionUnavailable,\n `Leader action ${action} is unavailable.`,\n {\n 'ui.kind': 'action',\n },\n );\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n },\n },\n ),\n );\n\n void telemetry.recordEvent(UI_EVENT.shellInstalled, {\n 'ui.theme': themeName,\n 'ui.theme.applied': themeResult.success,\n 'ui.leader.group.count': leaderRegistry.getGroup([])?.options.length ?? 0,\n });\n });\n\n pi.on(INPUT_EVENT, (event, ctx) => {\n if (ctx.mode !== TUI_MODE || event.source !== INTERACTIVE_INPUT_SOURCE || hasSessionMessage) return;\n hasSessionMessage = true;\n const title = createMessageTitle(event.text, ctx.cwd);\n if (title) ctx.ui.setTitle(title);\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async (_event, ctx) => {\n ++sessionGeneration;\n disposeLeaderBootstrap?.();\n disposeLeaderBootstrap = undefined;\n for (const dispose of protocolContributions.values()) dispose();\n protocolContributions.clear();\n activeContext = undefined;\n footerData = undefined;\n disposeFooterStatuses?.();\n disposeFooterStatuses = undefined;\n footerStatusRegistry.reset();\n disposeModeStatuses?.();\n disposeModeStatuses = undefined;\n disposeModeSubscription?.();\n disposeModeSubscription = undefined;\n modeStatusRegistry.reset();\n disposeConfigContributions?.();\n disposeConfigContributions = undefined;\n disposeLeaderRegistration?.();\n disposeLeaderRegistration = undefined;\n disposeLeaderUnregistration?.();\n disposeLeaderUnregistration = undefined;\n configRegistry.reset();\n uiState.reset();\n sessionProtocol = undefined;\n if (ctx.mode === TUI_MODE) ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"extension.mjs","names":["DoomFooterStatusRegistry","DoomModeStatusRegistry","DoomConfigRegistry"],"sources":["../../../src/adapters/pi/extension.ts"],"sourcesContent":["import path from 'node:path';\nimport {\n installDoomLeaderBootstrapHost,\n LeaderActionInvoked,\n type LeaderContribution,\n LeaderRegistrationProtocol,\n LeaderUnregistrationProtocol,\n} from '@agimon-ai/doompi-extension-contracts/leader';\nimport { McpStatusQueryProtocol } from '@agimon-ai/doompi-extension-contracts/mcp-status';\nimport { createProtocolRuntime, type ProtocolRuntime } from '@agimon-ai/doompi-extension-contracts/protocol';\nimport type { ExtensionAPI, ExtensionContext, ReadonlyFooterDataProvider } from '@earendil-works/pi-coding-agent';\nimport { DoomConfigRegistry } from '../../config.ts';\nimport { DoomFooterStatusRegistry } from '../../footer.ts';\nimport { DoomModeStatusRegistry } from '../../mode.ts';\nimport { type DoomLeaderDiagnostic, DoomLeaderRegistry } from '../../services/leader/leaderRegistry.ts';\nimport { DoomUiState, type LeaderSnapshot } from '../../services/state/uiState.ts';\nimport { buildToolSources, type McpServerStatus } from '../../services/tools/toolInventory.ts';\nimport { openConfigOverlay } from '../../tui/configOverlay.ts';\nimport { DoomEditor } from '../../tui/doomEditor.ts';\nimport { DoomFooter } from '../../tui/doomFooter.ts';\nimport { DoomHeader } from '../../tui/doomHeader.ts';\nimport { LeaderHints } from '../../tui/leaderHints.ts';\nimport { DEFAULT_THEME_NAME } from '../../tui/theme.ts';\nimport { openToolsOverlay } from '../../tui/toolsOverlay.ts';\nimport { createUiTelemetry, UI_EVENT, type UiTelemetry } from '../telemetry/logSinkTelemetry.ts';\nimport { registerBuiltinToolUi } from './toolOverrides.ts';\n\nconst LEADER_WIDGET_KEY = 'doom-pi-leader';\nconst TUI_MODE = 'tui';\nconst WIDGET_PLACEMENT = 'belowEditor';\nconst WARNING_STYLE = 'warning';\nconst THEME_ENVIRONMENT_KEY = 'DOOMPI_THEME';\nconst HOTKEYS_COMMAND = 'hotkeys';\nconst TOOLS_COMMAND = 'tools';\nconst CONFIG_COMMAND = 'config';\n/** Short: `/tools` must open promptly whether or not an MCP extension answers. */\nconst MCP_STATUS_TIMEOUT_MS = 250;\nconst SESSION_START_EVENT = 'session_start';\nconst SESSION_MESSAGE_ENTRY = 'message';\nconst INPUT_EVENT = 'input';\nconst INTERACTIVE_INPUT_SOURCE = 'interactive';\nconst SESSION_SHUTDOWN_EVENT = 'session_shutdown';\nconst TITLE_MESSAGE_MAX_LENGTH = 64;\nconst TITLE_PREFIX = 'doom-pi';\nconst BUILTIN_LEADER_COMMANDS = new Set([HOTKEYS_COMMAND]);\n\nfunction createMessageTitle(message: string, cwd: string): string | undefined {\n const normalizedMessage = message.trim().replace(/\\s+/g, ' ');\n if (!normalizedMessage) return undefined;\n const messageTitle = normalizedMessage.slice(0, TITLE_MESSAGE_MAX_LENGTH).trimEnd();\n return `${TITLE_PREFIX} · ${messageTitle} · ${path.basename(cwd) || cwd}`;\n}\n\nexport function doomPiUiExtension(pi: ExtensionAPI, telemetry: UiTelemetry = createUiTelemetry()): void {\n registerBuiltinToolUi(pi, process.cwd());\n const uiState = new DoomUiState();\n const footerStatusRegistry = new DoomFooterStatusRegistry();\n const modeStatusRegistry = new DoomModeStatusRegistry();\n const configRegistry = new DoomConfigRegistry();\n const leaderRegistry = new DoomLeaderRegistry();\n const pendingDiagnostics = new Set<string>();\n const contributionGenerations = new Map<string, symbol>();\n let footerData: ReadonlyFooterDataProvider | undefined;\n let activeContext: ExtensionContext | undefined;\n let disposeFooterStatuses: (() => void) | undefined;\n let disposeModeStatuses: (() => void) | undefined;\n let disposeModeSubscription: (() => void) | undefined;\n let disposeConfigContributions: (() => void) | undefined;\n let disposeLeaderRegistration: (() => void) | undefined;\n let disposeLeaderUnregistration: (() => void) | undefined;\n const protocolContributions = new Map<string, () => void>();\n let nextProtocolHandle = 0;\n let sessionGeneration = 0;\n let hasSessionMessage = false;\n let sessionProtocol: ProtocolRuntime | undefined;\n let disposeLeaderBootstrap: (() => void) | undefined;\n\n /**\n * Asks the MCP extension what it is currently connected to.\n *\n * No answer is a normal session: `--no-mcp` leaves nobody providing the query,\n * and the panel simply lists MCP tools under the extension that registered them.\n */\n const readMcpServers = async (): Promise<readonly McpServerStatus[] | undefined> => {\n if (!sessionProtocol) return undefined;\n try {\n const snapshot = await sessionProtocol.request(McpStatusQueryProtocol, {}, { timeoutMs: MCP_STATUS_TIMEOUT_MS });\n return snapshot.servers;\n } catch {\n return undefined;\n }\n };\n\n pi.registerCommand(TOOLS_COMMAND, {\n description: 'Browse the tools available in this session',\n handler: async (_args, ctx) => {\n // Read at open time so a reconnected server or a plan-mode tool swap shows\n // up without restarting the session.\n const mcpServers = await readMcpServers();\n const sources = buildToolSources({\n tools: pi.getAllTools(),\n activeTools: pi.getActiveTools(),\n ...(mcpServers ? { mcpServers } : {}),\n });\n await openToolsOverlay(ctx, sources);\n },\n });\n\n pi.registerCommand(CONFIG_COMMAND, {\n description: 'Browse and change the settings extensions contribute',\n handler: async (_args, ctx) => {\n // The registry is passed live rather than snapshotted: a contributor can be\n // fetching or installing something while the panel is open, and that\n // progress is meant to land in it.\n await openConfigOverlay(ctx, configRegistry);\n },\n });\n\n const reportDiagnostics = (diagnostics: readonly DoomLeaderDiagnostic[]): void => {\n for (const diagnostic of diagnostics) {\n const binding = diagnostic.bindingId ? ` (${diagnostic.bindingId})` : '';\n const message = `Leader contribution from ${diagnostic.source}${binding}: ${diagnostic.message}`;\n if (pendingDiagnostics.has(message)) continue;\n pendingDiagnostics.add(message);\n // A rejected contribution silently drops another extension's keybindings,\n // and the notice below only reaches a run that has a TUI attached.\n void telemetry.recordWarning(UI_EVENT.leaderContributionRejected, diagnostic.message, {\n 'leader.source': diagnostic.source,\n ...(diagnostic.bindingId ? { 'leader.binding.id': diagnostic.bindingId } : {}),\n });\n if (activeContext?.mode === TUI_MODE) activeContext.ui.notify(message, WARNING_STYLE);\n }\n };\n\n const registerLeaderContribution = (contribution: LeaderContribution, deferred: boolean) => {\n const generation = Symbol(contribution.source);\n const register = deferred\n ? (value: LeaderContribution) => leaderRegistry.registerDeferred(value)\n : (value: LeaderContribution) => leaderRegistry.register(value);\n const result = register(contribution);\n reportDiagnostics(result.diagnostics);\n if (!result.accepted) return { update: () => undefined, dispose: () => undefined };\n contributionGenerations.set(contribution.source, generation);\n let disposed = false;\n return {\n update(bindings: LeaderContribution['bindings']) {\n if (disposed || contributionGenerations.get(contribution.source) !== generation) return;\n reportDiagnostics(register({ source: contribution.source, bindings }).diagnostics);\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n if (contributionGenerations.get(contribution.source) !== generation) return;\n contributionGenerations.delete(contribution.source);\n register({ source: contribution.source, bindings: [] });\n },\n };\n };\n\n const leaderContext = Object.freeze({\n register(contribution: LeaderContribution) {\n const handle = registerLeaderContribution(contribution, false);\n return () => handle.dispose();\n },\n });\n // Installed during the UI factory, before the remaining Doom factories run.\n // Their registrations are validated immediately and rebuilt as one batch at\n // session_start, so the first editor always receives the complete keyspace.\n disposeLeaderBootstrap = installDoomLeaderBootstrapHost({\n register: (contribution) => registerLeaderContribution(contribution, true),\n });\n pi.on(SESSION_START_EVENT, (_event, ctx) => {\n activeContext = ctx;\n const activeGeneration = ++sessionGeneration;\n const protocol = createProtocolRuntime({\n bus: pi.events,\n source: '@agimon-ai/doompi-ui',\n sessionId: ctx.sessionManager.getSessionId(),\n });\n sessionProtocol = protocol;\n reportDiagnostics(leaderRegistry.flush());\n disposeFooterStatuses?.();\n footerStatusRegistry.reset();\n disposeFooterStatuses = footerStatusRegistry.bind(protocol);\n disposeModeStatuses?.();\n modeStatusRegistry.reset();\n disposeModeStatuses = modeStatusRegistry.bind(protocol);\n // Bound above the TUI-mode guard below, like footer and mode: a headless run\n // still accepts contributions, it just never draws them.\n disposeConfigContributions?.();\n configRegistry.reset();\n disposeConfigContributions = configRegistry.bind(protocol);\n disposeLeaderRegistration?.();\n disposeLeaderUnregistration?.();\n disposeLeaderRegistration = protocol.provide(\n LeaderRegistrationProtocol,\n ({ contribution, generation }, identity) => {\n if (identity.source !== contribution.source) {\n throw new Error('Leader contribution source does not match the registration envelope source.');\n }\n const handleId = `${identity.source}:${generation}:${++nextProtocolHandle}`;\n const typedContribution: LeaderContribution = {\n source: contribution.source,\n bindings: contribution.bindings.map((binding) => {\n const [first, ...rest] = binding.path;\n if (!first) throw new Error(`Leader binding '${binding.id}' has no path.`);\n return { ...binding, path: [first, ...rest] };\n }),\n };\n protocolContributions.set(handleId, leaderContext.register(typedContribution));\n return { handleId };\n },\n );\n disposeLeaderUnregistration = protocol.provide(LeaderUnregistrationProtocol, ({ handleId }) => {\n const dispose = protocolContributions.get(handleId);\n if (!dispose) return { removed: false };\n protocolContributions.delete(handleId);\n dispose();\n return { removed: true };\n });\n hasSessionMessage = ctx.sessionManager.getEntries().some((entry) => entry.type === SESSION_MESSAGE_ENTRY);\n if (ctx.mode !== TUI_MODE) return;\n for (const message of pendingDiagnostics) ctx.ui.notify(message, WARNING_STYLE);\n\n const themeName = process.env[THEME_ENVIRONMENT_KEY] || DEFAULT_THEME_NAME;\n const themeResult = ctx.ui.setTheme(themeName);\n if (!themeResult.success) {\n ctx.ui.notify(`Could not apply Doom Pi theme: ${themeResult.error}`, WARNING_STYLE);\n void telemetry.recordWarning(UI_EVENT.themeApplyFailed, themeResult.error ?? 'Unknown theme error', {\n 'ui.theme': themeName,\n });\n }\n\n // The modes go into shared state rather than a widget of their own: the\n // editor prints their names beside its badge and the leader panel prints\n // them with their detail, so there is no third surface to paint.\n disposeModeSubscription?.();\n disposeModeSubscription = modeStatusRegistry.subscribe(() => uiState.setModes(modeStatusRegistry.getStatuses()));\n uiState.setModes(modeStatusRegistry.getStatuses());\n\n ctx.ui.setTitle(`${TITLE_PREFIX} · ${path.basename(ctx.cwd) || ctx.cwd} · pi/coding`);\n ctx.ui.setHeader((tui, theme) => new DoomHeader(theme, ctx.cwd, undefined, ctx, () => tui.terminal.rows));\n ctx.ui.setFooter((tui, theme, data) => {\n footerData = data;\n return new DoomFooter(tui, theme, ctx, data, footerStatusRegistry, uiState);\n });\n ctx.ui.setEditorComponent(\n (tui, editorTheme, keybindings) =>\n new DoomEditor(\n tui,\n editorTheme,\n keybindings,\n uiState,\n (snapshot: LeaderSnapshot) => {\n if (!snapshot.active) {\n ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n return;\n }\n ctx.ui.setWidget(\n LEADER_WIDGET_KEY,\n (_widgetTui, widgetTheme) => new LeaderHints(widgetTheme, snapshot, ctx, footerData, uiState.getModes()),\n { placement: WIDGET_PLACEMENT },\n );\n },\n undefined,\n ctx.ui.theme,\n {\n registry: leaderRegistry,\n isCommandAvailable: (commandName) =>\n BUILTIN_LEADER_COMMANDS.has(commandName) ||\n pi.getCommands().some((command) => command.name === commandName),\n onLeaderAction: (source, action) => {\n if (activeContext !== ctx || sessionGeneration !== activeGeneration) {\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n return;\n }\n protocol.notify(LeaderActionInvoked, { source, action });\n },\n onUnavailableCommand: (commandName) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderCommandUnavailable,\n `Leader command /${commandName} is unavailable.`,\n { 'ui.kind': 'command' },\n );\n ctx.ui.notify(`Leader command /${commandName} is unavailable.`, WARNING_STYLE);\n },\n onUnavailableAction: (action) => {\n void telemetry.recordWarning(\n UI_EVENT.leaderActionUnavailable,\n `Leader action ${action} is unavailable.`,\n {\n 'ui.kind': 'action',\n },\n );\n ctx.ui.notify(`Leader action ${action} is unavailable.`, WARNING_STYLE);\n },\n },\n ),\n );\n\n void telemetry.recordEvent(UI_EVENT.shellInstalled, {\n 'ui.theme': themeName,\n 'ui.theme.applied': themeResult.success,\n 'ui.leader.group.count': leaderRegistry.getGroup([])?.options.length ?? 0,\n });\n });\n\n pi.on(INPUT_EVENT, (event, ctx) => {\n if (ctx.mode !== TUI_MODE || event.source !== INTERACTIVE_INPUT_SOURCE || hasSessionMessage) return;\n hasSessionMessage = true;\n const title = createMessageTitle(event.text, ctx.cwd);\n if (title) ctx.ui.setTitle(title);\n });\n\n pi.on(SESSION_SHUTDOWN_EVENT, async (_event, ctx) => {\n ++sessionGeneration;\n disposeLeaderBootstrap?.();\n disposeLeaderBootstrap = undefined;\n for (const dispose of protocolContributions.values()) dispose();\n protocolContributions.clear();\n activeContext = undefined;\n footerData = undefined;\n disposeFooterStatuses?.();\n disposeFooterStatuses = undefined;\n footerStatusRegistry.reset();\n disposeModeStatuses?.();\n disposeModeStatuses = undefined;\n disposeModeSubscription?.();\n disposeModeSubscription = undefined;\n modeStatusRegistry.reset();\n disposeConfigContributions?.();\n disposeConfigContributions = undefined;\n disposeLeaderRegistration?.();\n disposeLeaderRegistration = undefined;\n disposeLeaderUnregistration?.();\n disposeLeaderUnregistration = undefined;\n configRegistry.reset();\n uiState.reset();\n sessionProtocol = undefined;\n if (ctx.mode === TUI_MODE) ctx.ui.setWidget(LEADER_WIDGET_KEY, undefined, { placement: WIDGET_PLACEMENT });\n await telemetry.shutdown();\n });\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require("../../tui/builtinToolRender.cjs");let t=require("@earendil-works/pi-coding-agent");function n(n,r){let i=(0,t.createReadToolDefinition)(r);n.registerTool({...i,renderShell:`self`,renderCall:(t,n)=>e.renderReadCall(t,n),renderResult:(t,n,r,i)=>{let a=e.renderReadResult(i.args,t,{expanded:n.expanded,isError:i.isError},r);return e.frameBuiltinResult(a,r,i.lastComponent)}});let a=(0,t.createEditToolDefinition)(r),o=a.renderResult;n.registerTool({...a,renderShell:`self`,renderCall:(t,n)=>e.renderEditCall(t,n),renderResult:(t,n,r,i)=>{let a=o(t,n,r,{...i,lastComponent:e.previousBuiltinResult(i.lastComponent)});return e.frameBuiltinResult(a,r,i.lastComponent)}});let s=(0,t.createWriteToolDefinition)(r),c=s.renderResult;n.registerTool({...s,renderShell:`self`,renderCall:(t,n,r)=>e.renderWriteCall(t,n,{expanded:r.expanded}),renderResult:(t,n,r,i)=>{let a=c(t,n,r,{...i,lastComponent:e.previousBuiltinResult(i.lastComponent)});return e.frameBuiltinResult(a,r,i.lastComponent)}});let l=(0,t.createGrepToolDefinition)(r),u=l.renderResult;n.registerTool({...l,renderShell:`self`,renderCall:(t,n)=>e.renderGrepCall(t,n),renderResult:(t,n,r,i)=>{let a=u(t,n,r,{...i,lastComponent:e.previousBuiltinResult(i.lastComponent)});return e.frameBuiltinResult(a,r,i.lastComponent)}});let d=(0,t.createFindToolDefinition)(r),f=d.renderResult;n.registerTool({...d,renderShell:`self`,renderCall:(t,n)=>e.renderFindCall(t,n),renderResult:(t,n,r,i)=>{let a=f(t,n,r,{...i,lastComponent:e.previousBuiltinResult(i.lastComponent)});return e.frameBuiltinResult(a,r,i.lastComponent)}});let p=(0,t.createLsToolDefinition)(r),m=p.renderResult;n.registerTool({...p,renderShell:`self`,renderCall:(t,n)=>e.renderLsCall(t,n),renderResult:(t,n,r,i)=>{let a=m(t,n,r,{...i,lastComponent:e.previousBuiltinResult(i.lastComponent)});return e.frameBuiltinResult(a,r,i.lastComponent)}})}exports.registerBuiltinToolUi=n;
|
|
2
|
+
//# sourceMappingURL=toolOverrides.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolOverrides.cjs","names":["createReadToolDefinition","renderReadCall","renderReadResult","frameBuiltinResult","createEditToolDefinition","renderEditCall","previousBuiltinResult","createWriteToolDefinition","renderWriteCall","createGrepToolDefinition","renderGrepCall","createFindToolDefinition","renderFindCall","createLsToolDefinition","renderLsCall"],"sources":["../../../src/adapters/pi/toolOverrides.ts"],"sourcesContent":["import {\n createEditToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createLsToolDefinition,\n createReadToolDefinition,\n createWriteToolDefinition,\n type ExtensionAPI,\n} from '@earendil-works/pi-coding-agent';\nimport {\n frameBuiltinResult,\n previousBuiltinResult,\n renderEditCall,\n renderFindCall,\n renderGrepCall,\n renderLsCall,\n renderReadCall,\n renderReadResult,\n renderWriteCall,\n} from '../../tui/builtinToolRender.ts';\n\n/**\n * Keep Pi's native schemas, prompt metadata, execution, and result formatting;\n * replace only the broad status-background shell and call heading.\n */\nexport function registerBuiltinToolUi(pi: ExtensionAPI, cwd: string): void {\n const read = createReadToolDefinition(cwd);\n pi.registerTool({\n ...read,\n renderShell: 'self',\n renderCall: (args, theme) => renderReadCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = renderReadResult(\n context.args,\n result,\n { expanded: options.expanded, isError: context.isError },\n theme,\n );\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const edit = createEditToolDefinition(cwd);\n const editResult = edit.renderResult!;\n pi.registerTool({\n ...edit,\n renderShell: 'self',\n renderCall: (args, theme) => renderEditCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = editResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const write = createWriteToolDefinition(cwd);\n const writeResult = write.renderResult!;\n pi.registerTool({\n ...write,\n renderShell: 'self',\n renderCall: (args, theme, context) => renderWriteCall(args, theme, { expanded: context.expanded }),\n renderResult: (result, options, theme, context) => {\n const content = writeResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const grep = createGrepToolDefinition(cwd);\n const grepResult = grep.renderResult!;\n pi.registerTool({\n ...grep,\n renderShell: 'self',\n renderCall: (args, theme) => renderGrepCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = grepResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const find = createFindToolDefinition(cwd);\n const findResult = find.renderResult!;\n pi.registerTool({\n ...find,\n renderShell: 'self',\n renderCall: (args, theme) => renderFindCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = findResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const ls = createLsToolDefinition(cwd);\n const lsResult = ls.renderResult!;\n pi.registerTool({\n ...ls,\n renderShell: 'self',\n renderCall: (args, theme) => renderLsCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = lsResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n}\n"],"mappings":"oGAyBA,SAAgB,EAAsB,EAAkB,EAAmB,CACzE,IAAM,GAAA,EAAOA,EAAAA,yBAAAA,CAAyB,CAAG,EACzC,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAUC,EAAAA,eAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAUC,EAAAA,iBACd,EAAQ,KACR,EACA,CAAE,SAAU,EAAQ,SAAU,QAAS,EAAQ,OAAQ,EACvD,CACF,EACA,OAAOC,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,GAAA,EAAOC,EAAAA,yBAAAA,CAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAUC,EAAAA,eAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAeC,EAAAA,sBAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAOH,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,GAAA,EAAQI,EAAAA,0BAAAA,CAA0B,CAAG,EACrC,EAAc,EAAM,aAC1B,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,EAAO,IAAYC,EAAAA,gBAAgB,EAAM,EAAO,CAAE,SAAU,EAAQ,QAAS,CAAC,EACjG,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAY,EAAQ,EAAS,EAAO,CAClD,GAAG,EACH,cAAeF,EAAAA,sBAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAOH,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,GAAA,EAAOM,EAAAA,yBAAAA,CAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAUC,EAAAA,eAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAeJ,EAAAA,sBAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAOH,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,GAAA,EAAOQ,EAAAA,yBAAAA,CAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAUC,EAAAA,eAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAeN,EAAAA,sBAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAOH,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,GAAA,EAAKU,EAAAA,uBAAAA,CAAuB,CAAG,EAC/B,EAAW,EAAG,aACpB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAUC,EAAAA,aAAa,EAAM,CAAK,EACrD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAS,EAAQ,EAAS,EAAO,CAC/C,GAAG,EACH,cAAeR,EAAAA,sBAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAOH,EAAAA,mBAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,CACH"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{frameBuiltinResult as e,previousBuiltinResult as t,renderEditCall as n,renderFindCall as r,renderGrepCall as i,renderLsCall as a,renderReadCall as o,renderReadResult as s,renderWriteCall as c}from"../../tui/builtinToolRender.mjs";import{createEditToolDefinition as l,createFindToolDefinition as u,createGrepToolDefinition as d,createLsToolDefinition as f,createReadToolDefinition as p,createWriteToolDefinition as m}from"@earendil-works/pi-coding-agent";function h(h,g){let _=p(g);h.registerTool({..._,renderShell:`self`,renderCall:(e,t)=>o(e,t),renderResult:(t,n,r,i)=>{let a=s(i.args,t,{expanded:n.expanded,isError:i.isError},r);return e(a,r,i.lastComponent)}});let v=l(g),y=v.renderResult;h.registerTool({...v,renderShell:`self`,renderCall:(e,t)=>n(e,t),renderResult:(n,r,i,a)=>{let o=y(n,r,i,{...a,lastComponent:t(a.lastComponent)});return e(o,i,a.lastComponent)}});let b=m(g),x=b.renderResult;h.registerTool({...b,renderShell:`self`,renderCall:(e,t,n)=>c(e,t,{expanded:n.expanded}),renderResult:(n,r,i,a)=>{let o=x(n,r,i,{...a,lastComponent:t(a.lastComponent)});return e(o,i,a.lastComponent)}});let S=d(g),C=S.renderResult;h.registerTool({...S,renderShell:`self`,renderCall:(e,t)=>i(e,t),renderResult:(n,r,i,a)=>{let o=C(n,r,i,{...a,lastComponent:t(a.lastComponent)});return e(o,i,a.lastComponent)}});let w=u(g),T=w.renderResult;h.registerTool({...w,renderShell:`self`,renderCall:(e,t)=>r(e,t),renderResult:(n,r,i,a)=>{let o=T(n,r,i,{...a,lastComponent:t(a.lastComponent)});return e(o,i,a.lastComponent)}});let E=f(g),D=E.renderResult;h.registerTool({...E,renderShell:`self`,renderCall:(e,t)=>a(e,t),renderResult:(n,r,i,a)=>{let o=D(n,r,i,{...a,lastComponent:t(a.lastComponent)});return e(o,i,a.lastComponent)}})}export{h as registerBuiltinToolUi};
|
|
2
|
+
//# sourceMappingURL=toolOverrides.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"toolOverrides.mjs","names":[],"sources":["../../../src/adapters/pi/toolOverrides.ts"],"sourcesContent":["import {\n createEditToolDefinition,\n createFindToolDefinition,\n createGrepToolDefinition,\n createLsToolDefinition,\n createReadToolDefinition,\n createWriteToolDefinition,\n type ExtensionAPI,\n} from '@earendil-works/pi-coding-agent';\nimport {\n frameBuiltinResult,\n previousBuiltinResult,\n renderEditCall,\n renderFindCall,\n renderGrepCall,\n renderLsCall,\n renderReadCall,\n renderReadResult,\n renderWriteCall,\n} from '../../tui/builtinToolRender.ts';\n\n/**\n * Keep Pi's native schemas, prompt metadata, execution, and result formatting;\n * replace only the broad status-background shell and call heading.\n */\nexport function registerBuiltinToolUi(pi: ExtensionAPI, cwd: string): void {\n const read = createReadToolDefinition(cwd);\n pi.registerTool({\n ...read,\n renderShell: 'self',\n renderCall: (args, theme) => renderReadCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = renderReadResult(\n context.args,\n result,\n { expanded: options.expanded, isError: context.isError },\n theme,\n );\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const edit = createEditToolDefinition(cwd);\n const editResult = edit.renderResult!;\n pi.registerTool({\n ...edit,\n renderShell: 'self',\n renderCall: (args, theme) => renderEditCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = editResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const write = createWriteToolDefinition(cwd);\n const writeResult = write.renderResult!;\n pi.registerTool({\n ...write,\n renderShell: 'self',\n renderCall: (args, theme, context) => renderWriteCall(args, theme, { expanded: context.expanded }),\n renderResult: (result, options, theme, context) => {\n const content = writeResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const grep = createGrepToolDefinition(cwd);\n const grepResult = grep.renderResult!;\n pi.registerTool({\n ...grep,\n renderShell: 'self',\n renderCall: (args, theme) => renderGrepCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = grepResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const find = createFindToolDefinition(cwd);\n const findResult = find.renderResult!;\n pi.registerTool({\n ...find,\n renderShell: 'self',\n renderCall: (args, theme) => renderFindCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = findResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n\n const ls = createLsToolDefinition(cwd);\n const lsResult = ls.renderResult!;\n pi.registerTool({\n ...ls,\n renderShell: 'self',\n renderCall: (args, theme) => renderLsCall(args, theme),\n renderResult: (result, options, theme, context) => {\n const content = lsResult(result, options, theme, {\n ...context,\n lastComponent: previousBuiltinResult(context.lastComponent),\n });\n return frameBuiltinResult(content, theme, context.lastComponent);\n },\n });\n}\n"],"mappings":"6cAyBA,SAAgB,EAAsB,EAAkB,EAAmB,CACzE,IAAM,EAAO,EAAyB,CAAG,EACzC,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAU,EAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EACd,EAAQ,KACR,EACA,CAAE,SAAU,EAAQ,SAAU,QAAS,EAAQ,OAAQ,EACvD,CACF,EACA,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,EAAO,EAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAU,EAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAe,EAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,EAAQ,EAA0B,CAAG,EACrC,EAAc,EAAM,aAC1B,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,EAAO,IAAY,EAAgB,EAAM,EAAO,CAAE,SAAU,EAAQ,QAAS,CAAC,EACjG,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAY,EAAQ,EAAS,EAAO,CAClD,GAAG,EACH,cAAe,EAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,EAAO,EAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAU,EAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAe,EAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,EAAO,EAAyB,CAAG,EACnC,EAAa,EAAK,aACxB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAU,EAAe,EAAM,CAAK,EACvD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAW,EAAQ,EAAS,EAAO,CACjD,GAAG,EACH,cAAe,EAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,EAED,IAAM,EAAK,EAAuB,CAAG,EAC/B,EAAW,EAAG,aACpB,EAAG,aAAa,CACd,GAAG,EACH,YAAa,OACb,YAAa,EAAM,IAAU,EAAa,EAAM,CAAK,EACrD,cAAe,EAAQ,EAAS,EAAO,IAAY,CACjD,IAAM,EAAU,EAAS,EAAQ,EAAS,EAAO,CAC/C,GAAG,EACH,cAAe,EAAsB,EAAQ,aAAa,CAC5D,CAAC,EACD,OAAO,EAAmB,EAAS,EAAO,EAAQ,aAAa,CACjE,CACF,CAAC,CACH"}
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/telemetry/logSinkTelemetry.cjs");require("./config.cjs"),require("./footer.cjs"),require("./leader.cjs");const t=require("./services/state/uiState.cjs"),n=require("./types/harnessMetadata.cjs"),r=require("./tui/doomEditor.cjs"),i=require("./tui/doomFooter.cjs"),a=require("./tui/doomHeader.cjs"),o=require("./tui/doomOverlay.cjs"),s=require("./tui/leaderHints.cjs"),c=require("./tui/theme.cjs");let
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./adapters/telemetry/logSinkTelemetry.cjs");require("./config.cjs"),require("./footer.cjs"),require("./leader.cjs");const t=require("./services/state/uiState.cjs"),n=require("./types/harnessMetadata.cjs"),r=require("./tui/doomEditor.cjs"),i=require("./tui/doomFooter.cjs"),a=require("./tui/doomHeader.cjs"),o=require("./tui/doomOverlay.cjs"),s=require("./tui/leaderHints.cjs"),c=require("./tui/theme.cjs"),l=require("./tui/toolChrome.cjs");let u=require("@agimon-ai/doompi-extension-contracts/leader");exports.DEFAULT_THEME=c.DEFAULT_THEME,exports.DEFAULT_THEME_NAME=c.DEFAULT_THEME_NAME,exports.DOOM_FULLSCREEN_UI_OPTIONS=o.DOOM_FULLSCREEN_UI_OPTIONS,exports.DoomEditor=r.DoomEditor,exports.DoomFooter=i.DoomFooter,exports.DoomHeader=a.DoomHeader,exports.DoomOverlay=o.DoomOverlay,exports.DoomToolCall=l.DoomToolCall,exports.DoomToolResult=l.DoomToolResult,exports.DoomUiState=t.DoomUiState,exports.LeaderHints=s.LeaderHints,exports.UI_EVENT=e.UI_EVENT,Object.defineProperty(exports,"createDoomLeaderContribution",{enumerable:!0,get:function(){return u.createDoomLeaderContribution}}),exports.createUiTelemetry=e.createUiTelemetry,exports.readDoomHarnessMetadata=n.readDoomHarnessMetadata,Object.defineProperty(exports,"registerDoomConfigContribution",{enumerable:!0,get:function(){return config_exports.registerDoomConfigContribution}}),Object.defineProperty(exports,"registerDoomFooterContribution",{enumerable:!0,get:function(){return footer_exports.registerDoomFooterContribution}}),Object.defineProperty(exports,"registerDoomLeaderContribution",{enumerable:!0,get:function(){return u.registerDoomLeaderContribution}}),exports.renderToolBadge=l.renderToolBadge,exports.renderToolHeading=l.renderToolHeading,exports.writeDefaultTheme=c.writeDefaultTheme;
|
package/dist/index.d.cts
CHANGED
|
@@ -10,6 +10,7 @@ import { DoomHeader } from "./tui/doomHeader.cjs";
|
|
|
10
10
|
import { LeaderHints } from "./tui/leaderHints.cjs";
|
|
11
11
|
import { UI_EVENT, UiEventAttributes, UiEventName, UiTelemetry, UiTelemetryOptions, createUiTelemetry } from "./adapters/telemetry/logSinkTelemetry.cjs";
|
|
12
12
|
import { DEFAULT_THEME, DEFAULT_THEME_NAME, writeDefaultTheme } from "./tui/theme.cjs";
|
|
13
|
+
import { DoomToolCall, DoomToolResult, DoomToolResultOptions, renderToolBadge, renderToolHeading } from "./tui/toolChrome.cjs";
|
|
13
14
|
type ConfigChoice = config_d_exports.ConfigChoice;
|
|
14
15
|
type ConfigField = config_d_exports.ConfigField;
|
|
15
16
|
type ConfigSection = config_d_exports.ConfigSection;
|
|
@@ -22,4 +23,4 @@ type DoomFooterContributionHandle = footer_d_exports.DoomFooterContributionHandl
|
|
|
22
23
|
type DoomFooterContributionValue = footer_d_exports.DoomFooterContributionValue;
|
|
23
24
|
type registerDoomConfigContribution = config_d_exports.registerDoomConfigContribution;
|
|
24
25
|
type registerDoomFooterContribution = footer_d_exports.registerDoomFooterContribution;
|
|
25
|
-
export { type ConfigChoice, type ConfigField, type ConfigSection, type ConfigStep, DEFAULT_THEME, DEFAULT_THEME_NAME, DOOM_FULLSCREEN_UI_OPTIONS, type DoomConfigActionInput, type DoomConfigContributionHandle, type DoomConfigContributionOptions, DoomEditor, DoomFooter, type DoomFooterContributionDefinition, type DoomFooterContributionHandle, type DoomFooterContributionValue, type DoomHarnessMetadata, DoomHeader, type DoomLeaderBinding, type DoomLeaderCommand, type DoomLeaderContribution, type DoomLeaderContributionHandle, type DoomLeaderSegment, DoomOverlay, type DoomOverlayChrome, type DoomOverlayTui, DoomUiState, LeaderHints, type LeaderOption, type LeaderSnapshot, UI_EVENT, type UiEventAttributes, type UiEventName, type UiTelemetry, type UiTelemetryOptions, createDoomLeaderContribution, createUiTelemetry, readDoomHarnessMetadata, registerDoomConfigContribution, registerDoomFooterContribution, registerDoomLeaderContribution, writeDefaultTheme };
|
|
26
|
+
export { type ConfigChoice, type ConfigField, type ConfigSection, type ConfigStep, DEFAULT_THEME, DEFAULT_THEME_NAME, DOOM_FULLSCREEN_UI_OPTIONS, type DoomConfigActionInput, type DoomConfigContributionHandle, type DoomConfigContributionOptions, DoomEditor, DoomFooter, type DoomFooterContributionDefinition, type DoomFooterContributionHandle, type DoomFooterContributionValue, type DoomHarnessMetadata, DoomHeader, type DoomLeaderBinding, type DoomLeaderCommand, type DoomLeaderContribution, type DoomLeaderContributionHandle, type DoomLeaderSegment, DoomOverlay, type DoomOverlayChrome, type DoomOverlayTui, DoomToolCall, DoomToolResult, type DoomToolResultOptions, DoomUiState, LeaderHints, type LeaderOption, type LeaderSnapshot, UI_EVENT, type UiEventAttributes, type UiEventName, type UiTelemetry, type UiTelemetryOptions, createDoomLeaderContribution, createUiTelemetry, readDoomHarnessMetadata, registerDoomConfigContribution, registerDoomFooterContribution, registerDoomLeaderContribution, renderToolBadge, renderToolHeading, writeDefaultTheme };
|
package/dist/index.d.mts
CHANGED
|
@@ -10,6 +10,7 @@ import { DoomHeader } from "./tui/doomHeader.mjs";
|
|
|
10
10
|
import { LeaderHints } from "./tui/leaderHints.mjs";
|
|
11
11
|
import { UI_EVENT, UiEventAttributes, UiEventName, UiTelemetry, UiTelemetryOptions, createUiTelemetry } from "./adapters/telemetry/logSinkTelemetry.mjs";
|
|
12
12
|
import { DEFAULT_THEME, DEFAULT_THEME_NAME, writeDefaultTheme } from "./tui/theme.mjs";
|
|
13
|
+
import { DoomToolCall, DoomToolResult, DoomToolResultOptions, renderToolBadge, renderToolHeading } from "./tui/toolChrome.mjs";
|
|
13
14
|
type ConfigChoice = config_d_exports.ConfigChoice;
|
|
14
15
|
type ConfigField = config_d_exports.ConfigField;
|
|
15
16
|
type ConfigSection = config_d_exports.ConfigSection;
|
|
@@ -22,4 +23,4 @@ type DoomFooterContributionHandle = footer_d_exports.DoomFooterContributionHandl
|
|
|
22
23
|
type DoomFooterContributionValue = footer_d_exports.DoomFooterContributionValue;
|
|
23
24
|
type registerDoomConfigContribution = config_d_exports.registerDoomConfigContribution;
|
|
24
25
|
type registerDoomFooterContribution = footer_d_exports.registerDoomFooterContribution;
|
|
25
|
-
export { type ConfigChoice, type ConfigField, type ConfigSection, type ConfigStep, DEFAULT_THEME, DEFAULT_THEME_NAME, DOOM_FULLSCREEN_UI_OPTIONS, type DoomConfigActionInput, type DoomConfigContributionHandle, type DoomConfigContributionOptions, DoomEditor, DoomFooter, type DoomFooterContributionDefinition, type DoomFooterContributionHandle, type DoomFooterContributionValue, type DoomHarnessMetadata, DoomHeader, type DoomLeaderBinding, type DoomLeaderCommand, type DoomLeaderContribution, type DoomLeaderContributionHandle, type DoomLeaderSegment, DoomOverlay, type DoomOverlayChrome, type DoomOverlayTui, DoomUiState, LeaderHints, type LeaderOption, type LeaderSnapshot, UI_EVENT, type UiEventAttributes, type UiEventName, type UiTelemetry, type UiTelemetryOptions, createDoomLeaderContribution, createUiTelemetry, readDoomHarnessMetadata, registerDoomConfigContribution, registerDoomFooterContribution, registerDoomLeaderContribution, writeDefaultTheme };
|
|
26
|
+
export { type ConfigChoice, type ConfigField, type ConfigSection, type ConfigStep, DEFAULT_THEME, DEFAULT_THEME_NAME, DOOM_FULLSCREEN_UI_OPTIONS, type DoomConfigActionInput, type DoomConfigContributionHandle, type DoomConfigContributionOptions, DoomEditor, DoomFooter, type DoomFooterContributionDefinition, type DoomFooterContributionHandle, type DoomFooterContributionValue, type DoomHarnessMetadata, DoomHeader, type DoomLeaderBinding, type DoomLeaderCommand, type DoomLeaderContribution, type DoomLeaderContributionHandle, type DoomLeaderSegment, DoomOverlay, type DoomOverlayChrome, type DoomOverlayTui, DoomToolCall, DoomToolResult, type DoomToolResultOptions, DoomUiState, LeaderHints, type LeaderOption, type LeaderSnapshot, UI_EVENT, type UiEventAttributes, type UiEventName, type UiTelemetry, type UiTelemetryOptions, createDoomLeaderContribution, createUiTelemetry, readDoomHarnessMetadata, registerDoomConfigContribution, registerDoomFooterContribution, registerDoomLeaderContribution, renderToolBadge, renderToolHeading, writeDefaultTheme };
|
package/dist/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{UI_EVENT as e,createUiTelemetry as t}from"./adapters/telemetry/logSinkTelemetry.mjs";import{config_exports as n}from"./config.mjs";import{footer_exports as r}from"./footer.mjs";import{createDoomLeaderContribution as i,registerDoomLeaderContribution as a}from"./leader.mjs";import{DoomUiState as o}from"./services/state/uiState.mjs";import{readDoomHarnessMetadata as s}from"./types/harnessMetadata.mjs";import{DoomEditor as c}from"./tui/doomEditor.mjs";import{DoomFooter as l}from"./tui/doomFooter.mjs";import{DoomHeader as u}from"./tui/doomHeader.mjs";import{DOOM_FULLSCREEN_UI_OPTIONS as d,DoomOverlay as f}from"./tui/doomOverlay.mjs";import{LeaderHints as p}from"./tui/leaderHints.mjs";import{DEFAULT_THEME as m,DEFAULT_THEME_NAME as h,writeDefaultTheme as g}from"./tui/theme.mjs";var
|
|
1
|
+
import{UI_EVENT as e,createUiTelemetry as t}from"./adapters/telemetry/logSinkTelemetry.mjs";import{config_exports as n}from"./config.mjs";import{footer_exports as r}from"./footer.mjs";import{createDoomLeaderContribution as i,registerDoomLeaderContribution as a}from"./leader.mjs";import{DoomUiState as o}from"./services/state/uiState.mjs";import{readDoomHarnessMetadata as s}from"./types/harnessMetadata.mjs";import{DoomEditor as c}from"./tui/doomEditor.mjs";import{DoomFooter as l}from"./tui/doomFooter.mjs";import{DoomHeader as u}from"./tui/doomHeader.mjs";import{DOOM_FULLSCREEN_UI_OPTIONS as d,DoomOverlay as f}from"./tui/doomOverlay.mjs";import{LeaderHints as p}from"./tui/leaderHints.mjs";import{DEFAULT_THEME as m,DEFAULT_THEME_NAME as h,writeDefaultTheme as g}from"./tui/theme.mjs";import{DoomToolCall as _,DoomToolResult as v,renderToolBadge as y,renderToolHeading as b}from"./tui/toolChrome.mjs";var x=n.registerDoomConfigContribution,S=r.registerDoomFooterContribution;export{m as DEFAULT_THEME,h as DEFAULT_THEME_NAME,d as DOOM_FULLSCREEN_UI_OPTIONS,c as DoomEditor,l as DoomFooter,u as DoomHeader,f as DoomOverlay,_ as DoomToolCall,v as DoomToolResult,o as DoomUiState,p as LeaderHints,e as UI_EVENT,i as createDoomLeaderContribution,t as createUiTelemetry,s as readDoomHarnessMetadata,x as registerDoomConfigContribution,S as registerDoomFooterContribution,a as registerDoomLeaderContribution,y as renderToolBadge,b as renderToolHeading,g as writeDefaultTheme};
|
package/dist/rendering.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./tui/rendering.cjs");exports.alignLine=e.alignLine,exports.fitLine=e.fitLine,exports.formatTokens=e.formatTokens,exports.frameLine=e.frameLine,exports.packSegments=e.packSegments,exports.padLine=e.padLine;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./tui/rendering.cjs");exports.alignLine=e.alignLine,exports.fitLine=e.fitLine,exports.fitStyledLine=e.fitStyledLine,exports.formatTokens=e.formatTokens,exports.frameLine=e.frameLine,exports.packSegments=e.packSegments,exports.padLine=e.padLine;
|
package/dist/rendering.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { alignLine, fitLine, formatTokens, frameLine, packSegments, padLine } from "./tui/rendering.cjs";
|
|
2
|
-
export { alignLine, fitLine, formatTokens, frameLine, packSegments, padLine };
|
|
1
|
+
import { alignLine, fitLine, fitStyledLine, formatTokens, frameLine, packSegments, padLine } from "./tui/rendering.cjs";
|
|
2
|
+
export { alignLine, fitLine, fitStyledLine, formatTokens, frameLine, packSegments, padLine };
|
package/dist/rendering.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { alignLine, fitLine, formatTokens, frameLine, packSegments, padLine } from "./tui/rendering.mjs";
|
|
2
|
-
export { alignLine, fitLine, formatTokens, frameLine, packSegments, padLine };
|
|
1
|
+
import { alignLine, fitLine, fitStyledLine, formatTokens, frameLine, packSegments, padLine } from "./tui/rendering.mjs";
|
|
2
|
+
export { alignLine, fitLine, fitStyledLine, formatTokens, frameLine, packSegments, padLine };
|
package/dist/rendering.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{alignLine as e,fitLine as t,
|
|
1
|
+
import{alignLine as e,fitLine as t,fitStyledLine as n,formatTokens as r,frameLine as i,packSegments as a,padLine as o}from"./tui/rendering.mjs";export{e as alignLine,t as fitLine,n as fitStyledLine,r as formatTokens,i as frameLine,a as packSegments,o as padLine};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./tui/toolChrome.cjs");exports.DoomToolCall=e.DoomToolCall,exports.DoomToolResult=e.DoomToolResult,exports.renderToolBadge=e.renderToolBadge,exports.renderToolHeading=e.renderToolHeading;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{DoomToolCall as e,DoomToolResult as t,renderToolBadge as n,renderToolHeading as r}from"./tui/toolChrome.mjs";export{e as DoomToolCall,t as DoomToolResult,n as renderToolBadge,r as renderToolHeading};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const e=require("./toolChrome.cjs");let t=require("@earendil-works/pi-coding-agent"),n=require("@earendil-works/pi-tui");var r=class{text;constructor(e){this.text=e}render(e){return e<=0?[]:(0,n.wrapTextWithAnsi)(this.text,e)}invalidate(){}},i=class{content;theme;constructor(e,t){this.content=e,this.theme=t}setContent(e){this.content=e}getContent(){return this.content}render(e){if(e<=0)return[];if(e<3)return this.content.render(e);let t=e-2,n=this.theme.fg(`borderMuted`,`─`.repeat(t)),r=this.content.render(t).map(e=>` ${e}`);return[` ${n}`,...r,``]}invalidate(){this.content.invalidate()}};function a(e){return e instanceof i?e.getContent():void 0}function o(e,t,n){return n instanceof i?(n.setContent(e),n):new i(e,t)}function s(t,n,r,i){let a=e.renderToolHeading(t,n,i);return r.length>0&&(a+=` ${i.fg(`muted`,`· ${r.join(` · `)}`)}`),new e.DoomToolCall(a)}function c(e,t){return e===void 0?void 0:`${e} ${t}`}function l(e){return e.filter(e=>e!==void 0&&e.length>0)}function u(e,t){return s(`read`,e.path,l([e.offset===void 0?void 0:`from ${e.offset}`,c(e.limit,`lines`)]),t)}function d(e,t){let n=e.edits.length;return s(`edit`,e.path,[`${n} edit${n===1?``:`s`}`],t)}function f(n,r,i={},a=t.highlightCode,o=t.getLanguageFromPath){let s=e.renderToolHeading(`write`,n.path,r),c=r.fg(`muted`,`· ${n.content.length.toLocaleString(`en-US`)} chars`);if(n.content.length===0)return new e.DoomToolCall(`${s} ${c}`);let l=n.content.replaceAll(` `,` `).replaceAll(`\r
|
|
2
|
+
`,`
|
|
3
|
+
`).split(`
|
|
4
|
+
`);for(;l.at(-1)===``;)l.pop();let u=i.expanded?l:l.slice(0,10),d=o(n.path),f=d?a(u.join(`
|
|
5
|
+
`),d):u.map(e=>r.fg(`toolOutput`,e)),p=l.length-u.length,m=p>0?r.fg(`muted`,`… ${p} more lines · ctrl+o expand`):void 0;return new e.DoomToolCall([`${s} ${c}`,``,...f,...m?[m]:[]].join(`
|
|
6
|
+
`))}function p(e,n,i,a,o=t.highlightCode,s=t.getLanguageFromPath){let c=(n.content??[]).filter(e=>e.type===`text`).map(e=>e.text??``).join(`
|
|
7
|
+
`).replaceAll(` `,` `).replaceAll(`\r
|
|
8
|
+
`,`
|
|
9
|
+
`).split(`
|
|
10
|
+
`);for(;c.at(-1)===``;)c.pop();let l=i.expanded?c:c.slice(0,10),u=i.isError?void 0:s(e.path),d=i.isError?l.map(e=>a.fg(`error`,e)):u?o(l.join(`
|
|
11
|
+
`),u):l.map(e=>a.fg(`toolOutput`,e)),f=c.length-l.length;return f>0&&d.push(a.fg(`muted`,`… ${f} more lines · ctrl+o expand`)),new r(d.join(`
|
|
12
|
+
`))}function m(e,t){return s(`grep`,e.pattern,l([e.path??`.`,e.glob,e.ignoreCase===!0?`ignore case`:void 0,c(e.limit,`matches`)]),t)}function h(e,t){return s(`find`,e.pattern,l([e.path??`.`,c(e.limit,`results`)]),t)}function g(e,t){return s(`ls`,e.path??`.`,l([c(e.limit,`entries`)]),t)}exports.frameBuiltinResult=o,exports.previousBuiltinResult=a,exports.renderEditCall=d,exports.renderFindCall=h,exports.renderGrepCall=m,exports.renderLsCall=g,exports.renderReadCall=u,exports.renderReadResult=p,exports.renderWriteCall=f;
|
|
13
|
+
//# sourceMappingURL=builtinToolRender.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtinToolRender.cjs","names":["wrapTextWithAnsi","renderToolHeading","DoomToolCall","highlightCode","getLanguageFromPath"],"sources":["../../src/tui/builtinToolRender.ts"],"sourcesContent":["import {\n type EditToolInput,\n type FindToolInput,\n type GrepToolInput,\n getLanguageFromPath,\n highlightCode,\n type LsToolInput,\n type ReadToolInput,\n type Theme,\n type WriteToolInput,\n} from '@earendil-works/pi-coding-agent';\nimport { type Component, wrapTextWithAnsi } from '@earendil-works/pi-tui';\nimport { DoomToolCall, renderToolHeading } from './toolChrome.ts';\n\nconst COLLAPSED_FILE_LINES = 10;\n\ntype Highlighter = (code: string, language?: string) => string[];\ntype LanguageResolver = (path: string) => string | undefined;\n\nexport interface ToolPreviewOptions {\n expanded?: boolean;\n isError?: boolean;\n}\n\nexport interface TextToolResult {\n content?: ReadonlyArray<{ type: string; text?: string }>;\n}\n\n/** Self-owned result shell shared by Pi's native file and search tools. */\nclass BuiltinToolContent implements Component {\n constructor(private readonly text: string) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n return wrapTextWithAnsi(this.text, width);\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nclass BuiltinToolResultFrame implements Component {\n constructor(\n private content: Component,\n private readonly theme: Theme,\n ) {}\n\n setContent(content: Component): void {\n this.content = content;\n }\n\n getContent(): Component {\n return this.content;\n }\n\n render(width: number): string[] {\n if (width <= 0) return [];\n if (width < 3) return this.content.render(width);\n\n const contentWidth = width - 2;\n const divider = this.theme.fg('borderMuted', '─'.repeat(contentWidth));\n const lines = this.content.render(contentWidth).map((line) => ` ${line}`);\n return [` ${divider}`, ...lines, ''];\n }\n\n invalidate(): void {\n this.content.invalidate();\n }\n}\n\n/** Recover the native renderer's component from the shell returned on its previous pass. */\nexport function previousBuiltinResult(component: Component | undefined): Component | undefined {\n return component instanceof BuiltinToolResultFrame ? component.getContent() : undefined;\n}\n\n/** Reuse the shell while allowing Pi's native renderer to reuse its own inner component. */\nexport function frameBuiltinResult(content: Component, theme: Theme, previous: Component | undefined): Component {\n if (previous instanceof BuiltinToolResultFrame) {\n previous.setContent(content);\n return previous;\n }\n return new BuiltinToolResultFrame(content, theme);\n}\n\nfunction renderCall(label: string, primary: string, details: readonly string[], theme: Theme): Component {\n let text = renderToolHeading(label, primary, theme);\n if (details.length > 0) text += ` ${theme.fg('muted', `· ${details.join(' · ')}`)}`;\n return new DoomToolCall(text);\n}\n\nfunction optionalCount(value: number | undefined, unit: string): string | undefined {\n return value === undefined ? undefined : `${value} ${unit}`;\n}\n\nfunction compactDetails(values: ReadonlyArray<string | undefined>): string[] {\n return values.filter((value): value is string => value !== undefined && value.length > 0);\n}\n\nexport function renderReadCall(args: ReadToolInput, theme: Theme): Component {\n return renderCall(\n 'read',\n args.path,\n compactDetails([args.offset === undefined ? undefined : `from ${args.offset}`, optionalCount(args.limit, 'lines')]),\n theme,\n );\n}\n\nexport function renderEditCall(args: EditToolInput, theme: Theme): Component {\n const count = args.edits.length;\n return renderCall('edit', args.path, [`${count} edit${count === 1 ? '' : 's'}`], theme);\n}\n\nexport function renderWriteCall(\n args: WriteToolInput,\n theme: Theme,\n options: ToolPreviewOptions = {},\n highlight: Highlighter = highlightCode,\n resolveLanguage: LanguageResolver = getLanguageFromPath,\n): Component {\n const heading = renderToolHeading('write', args.path, theme);\n const details = theme.fg('muted', `· ${args.content.length.toLocaleString('en-US')} chars`);\n if (args.content.length === 0) return new DoomToolCall(`${heading} ${details}`);\n\n const normalizedLines = args.content.replaceAll('\\t', ' ').replaceAll('\\r\\n', '\\n').split('\\n');\n while (normalizedLines.at(-1) === '') normalizedLines.pop();\n const visibleLines = options.expanded ? normalizedLines : normalizedLines.slice(0, COLLAPSED_FILE_LINES);\n const language = resolveLanguage(args.path);\n const preview = language\n ? highlight(visibleLines.join('\\n'), language)\n : visibleLines.map((line) => theme.fg('toolOutput', line));\n const remaining = normalizedLines.length - visibleLines.length;\n const expansionHint = remaining > 0 ? theme.fg('muted', `… ${remaining} more lines · ctrl+o expand`) : undefined;\n return new DoomToolCall(\n [`${heading} ${details}`, '', ...preview, ...(expansionHint ? [expansionHint] : [])].join('\\n'),\n );\n}\n\nexport function renderReadResult(\n args: ReadToolInput,\n result: TextToolResult,\n options: ToolPreviewOptions,\n theme: Theme,\n highlight: Highlighter = highlightCode,\n resolveLanguage: LanguageResolver = getLanguageFromPath,\n): Component {\n const output = (result.content ?? [])\n .filter((block) => block.type === 'text')\n .map((block) => block.text ?? '')\n .join('\\n')\n .replaceAll('\\t', ' ')\n .replaceAll('\\r\\n', '\\n');\n const normalizedLines = output.split('\\n');\n while (normalizedLines.at(-1) === '') normalizedLines.pop();\n const visibleLines = options.expanded ? normalizedLines : normalizedLines.slice(0, COLLAPSED_FILE_LINES);\n const language = options.isError ? undefined : resolveLanguage(args.path);\n const preview = options.isError\n ? visibleLines.map((line) => theme.fg('error', line))\n : language\n ? highlight(visibleLines.join('\\n'), language)\n : visibleLines.map((line) => theme.fg('toolOutput', line));\n const remaining = normalizedLines.length - visibleLines.length;\n if (remaining > 0) preview.push(theme.fg('muted', `… ${remaining} more lines · ctrl+o expand`));\n return new BuiltinToolContent(preview.join('\\n'));\n}\n\nexport function renderGrepCall(args: GrepToolInput, theme: Theme): Component {\n return renderCall(\n 'grep',\n args.pattern,\n compactDetails([\n args.path ?? '.',\n args.glob,\n args.ignoreCase === true ? 'ignore case' : undefined,\n optionalCount(args.limit, 'matches'),\n ]),\n theme,\n );\n}\n\nexport function renderFindCall(args: FindToolInput, theme: Theme): Component {\n return renderCall(\n 'find',\n args.pattern,\n compactDetails([args.path ?? '.', optionalCount(args.limit, 'results')]),\n theme,\n );\n}\n\nexport function renderLsCall(args: LsToolInput, theme: Theme): Component {\n return renderCall('ls', args.path ?? '.', compactDetails([optionalCount(args.limit, 'entries')]), theme);\n}\n"],"mappings":"yHA6BA,IAAM,EAAN,KAA8C,CACf,KAA7B,YAAY,EAA+B,CAAd,KAAA,KAAA,CAAe,CAE5C,OAAO,EAAyB,CAE9B,OADI,GAAS,EAAU,CAAC,GACxB,EAAOA,EAAAA,iBAAAA,CAAiB,KAAK,KAAM,CAAK,CAC1C,CAEA,YAAmB,CAEnB,CACF,EAEM,EAAN,KAAkD,CAEtC,QACS,MAFnB,YACE,EACA,EACA,CAFQ,KAAA,QAAA,EACS,KAAA,MAAA,CAChB,CAEH,WAAW,EAA0B,CACnC,KAAK,QAAU,CACjB,CAEA,YAAwB,CACtB,OAAO,KAAK,OACd,CAEA,OAAO,EAAyB,CAC9B,GAAI,GAAS,EAAG,MAAO,CAAC,EACxB,GAAI,EAAQ,EAAG,OAAO,KAAK,QAAQ,OAAO,CAAK,EAE/C,IAAM,EAAe,EAAQ,EACvB,EAAU,KAAK,MAAM,GAAG,cAAe,IAAI,OAAO,CAAY,CAAC,EAC/D,EAAQ,KAAK,QAAQ,OAAO,CAAY,CAAC,CAAC,IAAK,GAAS,IAAI,GAAM,EACxE,MAAO,CAAC,IAAI,IAAW,GAAG,EAAO,EAAE,CACrC,CAEA,YAAmB,CACjB,KAAK,QAAQ,WAAW,CAC1B,CACF,EAGA,SAAgB,EAAsB,EAAyD,CAC7F,OAAO,aAAqB,EAAyB,EAAU,WAAW,EAAI,IAAA,EAChF,CAGA,SAAgB,EAAmB,EAAoB,EAAc,EAA4C,CAK/G,OAJI,aAAoB,GACtB,EAAS,WAAW,CAAO,EACpB,GAEF,IAAI,EAAuB,EAAS,CAAK,CAClD,CAEA,SAAS,EAAW,EAAe,EAAiB,EAA4B,EAAyB,CACvG,IAAI,EAAOC,EAAAA,kBAAkB,EAAO,EAAS,CAAK,EAElD,OADI,EAAQ,OAAS,IAAG,GAAQ,IAAI,EAAM,GAAG,QAAS,KAAK,EAAQ,KAAK,KAAK,GAAG,KACzE,IAAIC,EAAAA,aAAa,CAAI,CAC9B,CAEA,SAAS,EAAc,EAA2B,EAAkC,CAClF,OAAO,IAAU,IAAA,GAAY,IAAA,GAAY,GAAG,EAAM,GAAG,GACvD,CAEA,SAAS,EAAe,EAAqD,CAC3E,OAAO,EAAO,OAAQ,GAA2B,IAAU,IAAA,IAAa,EAAM,OAAS,CAAC,CAC1F,CAEA,SAAgB,EAAe,EAAqB,EAAyB,CAC3E,OAAO,EACL,OACA,EAAK,KACL,EAAe,CAAC,EAAK,SAAW,IAAA,GAAY,IAAA,GAAY,QAAQ,EAAK,SAAU,EAAc,EAAK,MAAO,OAAO,CAAC,CAAC,EAClH,CACF,CACF,CAEA,SAAgB,EAAe,EAAqB,EAAyB,CAC3E,IAAM,EAAQ,EAAK,MAAM,OACzB,OAAO,EAAW,OAAQ,EAAK,KAAM,CAAC,GAAG,EAAM,OAAO,IAAU,EAAI,GAAK,KAAK,EAAG,CAAK,CACxF,CAEA,SAAgB,EACd,EACA,EACA,EAA8B,CAAC,EAC/B,EAAyBC,EAAAA,cACzB,EAAoCC,EAAAA,oBACzB,CACX,IAAM,EAAUH,EAAAA,kBAAkB,QAAS,EAAK,KAAM,CAAK,EACrD,EAAU,EAAM,GAAG,QAAS,KAAK,EAAK,QAAQ,OAAO,eAAe,OAAO,EAAE,OAAO,EAC1F,GAAI,EAAK,QAAQ,SAAW,EAAG,OAAO,IAAIC,EAAAA,aAAa,GAAG,EAAQ,GAAG,GAAS,EAE9E,IAAM,EAAkB,EAAK,QAAQ,WAAW,IAAM,IAAI,CAAC,CAAC,WAAW;EAAQ;CAAI,CAAC,CAAC,MAAM;CAAI,EAC/F,KAAO,EAAgB,GAAG,EAAE,IAAM,IAAI,EAAgB,IAAI,EAC1D,IAAM,EAAe,EAAQ,SAAW,EAAkB,EAAgB,MAAM,EAAG,EAAoB,EACjG,EAAW,EAAgB,EAAK,IAAI,EACpC,EAAU,EACZ,EAAU,EAAa,KAAK;CAAI,EAAG,CAAQ,EAC3C,EAAa,IAAK,GAAS,EAAM,GAAG,aAAc,CAAI,CAAC,EACrD,EAAY,EAAgB,OAAS,EAAa,OAClD,EAAgB,EAAY,EAAI,EAAM,GAAG,QAAS,KAAK,EAAU,4BAA4B,EAAI,IAAA,GACvG,OAAO,IAAIA,EAAAA,aACT,CAAC,GAAG,EAAQ,GAAG,IAAW,GAAI,GAAG,EAAS,GAAI,EAAgB,CAAC,CAAa,EAAI,CAAC,CAAE,CAAC,CAAC,KAAK;CAAI,CAChG,CACF,CAEA,SAAgB,EACd,EACA,EACA,EACA,EACA,EAAyBC,EAAAA,cACzB,EAAoCC,EAAAA,oBACzB,CAOX,IAAM,GANU,EAAO,SAAW,CAAC,EAAA,CAChC,OAAQ,GAAU,EAAM,OAAS,MAAM,CAAC,CACxC,IAAK,GAAU,EAAM,MAAQ,EAAE,CAAC,CAChC,KAAK;CAAI,CAAC,CACV,WAAW,IAAM,IAAI,CAAC,CACtB,WAAW;EAAQ;CACO,CAAC,CAAC,MAAM;CAAI,EACzC,KAAO,EAAgB,GAAG,EAAE,IAAM,IAAI,EAAgB,IAAI,EAC1D,IAAM,EAAe,EAAQ,SAAW,EAAkB,EAAgB,MAAM,EAAG,EAAoB,EACjG,EAAW,EAAQ,QAAU,IAAA,GAAY,EAAgB,EAAK,IAAI,EAClE,EAAU,EAAQ,QACpB,EAAa,IAAK,GAAS,EAAM,GAAG,QAAS,CAAI,CAAC,EAClD,EACE,EAAU,EAAa,KAAK;CAAI,EAAG,CAAQ,EAC3C,EAAa,IAAK,GAAS,EAAM,GAAG,aAAc,CAAI,CAAC,EACvD,EAAY,EAAgB,OAAS,EAAa,OAExD,OADI,EAAY,GAAG,EAAQ,KAAK,EAAM,GAAG,QAAS,KAAK,EAAU,4BAA4B,CAAC,EACvF,IAAI,EAAmB,EAAQ,KAAK;CAAI,CAAC,CAClD,CAEA,SAAgB,EAAe,EAAqB,EAAyB,CAC3E,OAAO,EACL,OACA,EAAK,QACL,EAAe,CACb,EAAK,MAAQ,IACb,EAAK,KACL,EAAK,aAAe,GAAO,cAAgB,IAAA,GAC3C,EAAc,EAAK,MAAO,SAAS,CACrC,CAAC,EACD,CACF,CACF,CAEA,SAAgB,EAAe,EAAqB,EAAyB,CAC3E,OAAO,EACL,OACA,EAAK,QACL,EAAe,CAAC,EAAK,MAAQ,IAAK,EAAc,EAAK,MAAO,SAAS,CAAC,CAAC,EACvE,CACF,CACF,CAEA,SAAgB,EAAa,EAAmB,EAAyB,CACvE,OAAO,EAAW,KAAM,EAAK,MAAQ,IAAK,EAAe,CAAC,EAAc,EAAK,MAAO,SAAS,CAAC,CAAC,EAAG,CAAK,CACzG"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import{DoomToolCall as e,renderToolHeading as t}from"./toolChrome.mjs";import{getLanguageFromPath as n,highlightCode as r}from"@earendil-works/pi-coding-agent";import{wrapTextWithAnsi as i}from"@earendil-works/pi-tui";var a=class{text;constructor(e){this.text=e}render(e){return e<=0?[]:i(this.text,e)}invalidate(){}},o=class{content;theme;constructor(e,t){this.content=e,this.theme=t}setContent(e){this.content=e}getContent(){return this.content}render(e){if(e<=0)return[];if(e<3)return this.content.render(e);let t=e-2,n=this.theme.fg(`borderMuted`,`─`.repeat(t)),r=this.content.render(t).map(e=>` ${e}`);return[` ${n}`,...r,``]}invalidate(){this.content.invalidate()}};function s(e){return e instanceof o?e.getContent():void 0}function c(e,t,n){return n instanceof o?(n.setContent(e),n):new o(e,t)}function l(n,r,i,a){let o=t(n,r,a);return i.length>0&&(o+=` ${a.fg(`muted`,`· ${i.join(` · `)}`)}`),new e(o)}function u(e,t){return e===void 0?void 0:`${e} ${t}`}function d(e){return e.filter(e=>e!==void 0&&e.length>0)}function f(e,t){return l(`read`,e.path,d([e.offset===void 0?void 0:`from ${e.offset}`,u(e.limit,`lines`)]),t)}function p(e,t){let n=e.edits.length;return l(`edit`,e.path,[`${n} edit${n===1?``:`s`}`],t)}function m(i,a,o={},s=r,c=n){let l=t(`write`,i.path,a),u=a.fg(`muted`,`· ${i.content.length.toLocaleString(`en-US`)} chars`);if(i.content.length===0)return new e(`${l} ${u}`);let d=i.content.replaceAll(` `,` `).replaceAll(`\r
|
|
2
|
+
`,`
|
|
3
|
+
`).split(`
|
|
4
|
+
`);for(;d.at(-1)===``;)d.pop();let f=o.expanded?d:d.slice(0,10),p=c(i.path),m=p?s(f.join(`
|
|
5
|
+
`),p):f.map(e=>a.fg(`toolOutput`,e)),h=d.length-f.length,g=h>0?a.fg(`muted`,`… ${h} more lines · ctrl+o expand`):void 0;return new e([`${l} ${u}`,``,...m,...g?[g]:[]].join(`
|
|
6
|
+
`))}function h(e,t,i,o,s=r,c=n){let l=(t.content??[]).filter(e=>e.type===`text`).map(e=>e.text??``).join(`
|
|
7
|
+
`).replaceAll(` `,` `).replaceAll(`\r
|
|
8
|
+
`,`
|
|
9
|
+
`).split(`
|
|
10
|
+
`);for(;l.at(-1)===``;)l.pop();let u=i.expanded?l:l.slice(0,10),d=i.isError?void 0:c(e.path),f=i.isError?u.map(e=>o.fg(`error`,e)):d?s(u.join(`
|
|
11
|
+
`),d):u.map(e=>o.fg(`toolOutput`,e)),p=l.length-u.length;return p>0&&f.push(o.fg(`muted`,`… ${p} more lines · ctrl+o expand`)),new a(f.join(`
|
|
12
|
+
`))}function g(e,t){return l(`grep`,e.pattern,d([e.path??`.`,e.glob,e.ignoreCase===!0?`ignore case`:void 0,u(e.limit,`matches`)]),t)}function _(e,t){return l(`find`,e.pattern,d([e.path??`.`,u(e.limit,`results`)]),t)}function v(e,t){return l(`ls`,e.path??`.`,d([u(e.limit,`entries`)]),t)}export{c as frameBuiltinResult,s as previousBuiltinResult,p as renderEditCall,_ as renderFindCall,g as renderGrepCall,v as renderLsCall,f as renderReadCall,h as renderReadResult,m as renderWriteCall};
|
|
13
|
+
//# sourceMappingURL=builtinToolRender.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtinToolRender.mjs","names":[],"sources":["../../src/tui/builtinToolRender.ts"],"sourcesContent":["import {\n type EditToolInput,\n type FindToolInput,\n type GrepToolInput,\n getLanguageFromPath,\n highlightCode,\n type LsToolInput,\n type ReadToolInput,\n type Theme,\n type WriteToolInput,\n} from '@earendil-works/pi-coding-agent';\nimport { type Component, wrapTextWithAnsi } from '@earendil-works/pi-tui';\nimport { DoomToolCall, renderToolHeading } from './toolChrome.ts';\n\nconst COLLAPSED_FILE_LINES = 10;\n\ntype Highlighter = (code: string, language?: string) => string[];\ntype LanguageResolver = (path: string) => string | undefined;\n\nexport interface ToolPreviewOptions {\n expanded?: boolean;\n isError?: boolean;\n}\n\nexport interface TextToolResult {\n content?: ReadonlyArray<{ type: string; text?: string }>;\n}\n\n/** Self-owned result shell shared by Pi's native file and search tools. */\nclass BuiltinToolContent implements Component {\n constructor(private readonly text: string) {}\n\n render(width: number): string[] {\n if (width <= 0) return [];\n return wrapTextWithAnsi(this.text, width);\n }\n\n invalidate(): void {\n // Content is immutable and reflows from the current width on every render.\n }\n}\n\nclass BuiltinToolResultFrame implements Component {\n constructor(\n private content: Component,\n private readonly theme: Theme,\n ) {}\n\n setContent(content: Component): void {\n this.content = content;\n }\n\n getContent(): Component {\n return this.content;\n }\n\n render(width: number): string[] {\n if (width <= 0) return [];\n if (width < 3) return this.content.render(width);\n\n const contentWidth = width - 2;\n const divider = this.theme.fg('borderMuted', '─'.repeat(contentWidth));\n const lines = this.content.render(contentWidth).map((line) => ` ${line}`);\n return [` ${divider}`, ...lines, ''];\n }\n\n invalidate(): void {\n this.content.invalidate();\n }\n}\n\n/** Recover the native renderer's component from the shell returned on its previous pass. */\nexport function previousBuiltinResult(component: Component | undefined): Component | undefined {\n return component instanceof BuiltinToolResultFrame ? component.getContent() : undefined;\n}\n\n/** Reuse the shell while allowing Pi's native renderer to reuse its own inner component. */\nexport function frameBuiltinResult(content: Component, theme: Theme, previous: Component | undefined): Component {\n if (previous instanceof BuiltinToolResultFrame) {\n previous.setContent(content);\n return previous;\n }\n return new BuiltinToolResultFrame(content, theme);\n}\n\nfunction renderCall(label: string, primary: string, details: readonly string[], theme: Theme): Component {\n let text = renderToolHeading(label, primary, theme);\n if (details.length > 0) text += ` ${theme.fg('muted', `· ${details.join(' · ')}`)}`;\n return new DoomToolCall(text);\n}\n\nfunction optionalCount(value: number | undefined, unit: string): string | undefined {\n return value === undefined ? undefined : `${value} ${unit}`;\n}\n\nfunction compactDetails(values: ReadonlyArray<string | undefined>): string[] {\n return values.filter((value): value is string => value !== undefined && value.length > 0);\n}\n\nexport function renderReadCall(args: ReadToolInput, theme: Theme): Component {\n return renderCall(\n 'read',\n args.path,\n compactDetails([args.offset === undefined ? undefined : `from ${args.offset}`, optionalCount(args.limit, 'lines')]),\n theme,\n );\n}\n\nexport function renderEditCall(args: EditToolInput, theme: Theme): Component {\n const count = args.edits.length;\n return renderCall('edit', args.path, [`${count} edit${count === 1 ? '' : 's'}`], theme);\n}\n\nexport function renderWriteCall(\n args: WriteToolInput,\n theme: Theme,\n options: ToolPreviewOptions = {},\n highlight: Highlighter = highlightCode,\n resolveLanguage: LanguageResolver = getLanguageFromPath,\n): Component {\n const heading = renderToolHeading('write', args.path, theme);\n const details = theme.fg('muted', `· ${args.content.length.toLocaleString('en-US')} chars`);\n if (args.content.length === 0) return new DoomToolCall(`${heading} ${details}`);\n\n const normalizedLines = args.content.replaceAll('\\t', ' ').replaceAll('\\r\\n', '\\n').split('\\n');\n while (normalizedLines.at(-1) === '') normalizedLines.pop();\n const visibleLines = options.expanded ? normalizedLines : normalizedLines.slice(0, COLLAPSED_FILE_LINES);\n const language = resolveLanguage(args.path);\n const preview = language\n ? highlight(visibleLines.join('\\n'), language)\n : visibleLines.map((line) => theme.fg('toolOutput', line));\n const remaining = normalizedLines.length - visibleLines.length;\n const expansionHint = remaining > 0 ? theme.fg('muted', `… ${remaining} more lines · ctrl+o expand`) : undefined;\n return new DoomToolCall(\n [`${heading} ${details}`, '', ...preview, ...(expansionHint ? [expansionHint] : [])].join('\\n'),\n );\n}\n\nexport function renderReadResult(\n args: ReadToolInput,\n result: TextToolResult,\n options: ToolPreviewOptions,\n theme: Theme,\n highlight: Highlighter = highlightCode,\n resolveLanguage: LanguageResolver = getLanguageFromPath,\n): Component {\n const output = (result.content ?? [])\n .filter((block) => block.type === 'text')\n .map((block) => block.text ?? '')\n .join('\\n')\n .replaceAll('\\t', ' ')\n .replaceAll('\\r\\n', '\\n');\n const normalizedLines = output.split('\\n');\n while (normalizedLines.at(-1) === '') normalizedLines.pop();\n const visibleLines = options.expanded ? normalizedLines : normalizedLines.slice(0, COLLAPSED_FILE_LINES);\n const language = options.isError ? undefined : resolveLanguage(args.path);\n const preview = options.isError\n ? visibleLines.map((line) => theme.fg('error', line))\n : language\n ? highlight(visibleLines.join('\\n'), language)\n : visibleLines.map((line) => theme.fg('toolOutput', line));\n const remaining = normalizedLines.length - visibleLines.length;\n if (remaining > 0) preview.push(theme.fg('muted', `… ${remaining} more lines · ctrl+o expand`));\n return new BuiltinToolContent(preview.join('\\n'));\n}\n\nexport function renderGrepCall(args: GrepToolInput, theme: Theme): Component {\n return renderCall(\n 'grep',\n args.pattern,\n compactDetails([\n args.path ?? '.',\n args.glob,\n args.ignoreCase === true ? 'ignore case' : undefined,\n optionalCount(args.limit, 'matches'),\n ]),\n theme,\n );\n}\n\nexport function renderFindCall(args: FindToolInput, theme: Theme): Component {\n return renderCall(\n 'find',\n args.pattern,\n compactDetails([args.path ?? '.', optionalCount(args.limit, 'results')]),\n theme,\n );\n}\n\nexport function renderLsCall(args: LsToolInput, theme: Theme): Component {\n return renderCall('ls', args.path ?? '.', compactDetails([optionalCount(args.limit, 'entries')]), theme);\n}\n"],"mappings":"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"}
|
|
Binary file
|