@timurproko/a1 0.1.8-dev.151 → 0.1.8-dev.182

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.
Files changed (70) hide show
  1. package/README.md +53 -9
  2. package/bin/cli.js +1 -0
  3. package/bin/ui.js +17 -2
  4. package/dist/cli/dispatch.d.ts +6 -0
  5. package/dist/cli/dispatch.js +107 -81
  6. package/dist/cli/version-stats.js +7 -1
  7. package/dist/composition/owned-ui.d.ts +4 -1
  8. package/dist/composition/owned-ui.js +8 -5
  9. package/dist/contracts/agent-engine/capability-ports.d.ts +2 -2
  10. package/dist/contracts/agent-engine/domain-validation.js +22 -4
  11. package/dist/contracts/agent-engine/domain.d.ts +17 -0
  12. package/dist/contracts/owned-ui/model.d.ts +8 -0
  13. package/dist/contracts/owned-ui/validation.js +11 -0
  14. package/dist/features/owned-ui/index.d.ts +1 -0
  15. package/dist/features/owned-ui/index.js +1 -0
  16. package/dist/features/owned-ui/project-trust-prompt.d.ts +20 -0
  17. package/dist/features/owned-ui/project-trust-prompt.js +32 -0
  18. package/dist/features/owned-ui/settings-app.js +37 -9
  19. package/dist/integrations/pi/components/shell-components.d.ts +1 -0
  20. package/dist/integrations/pi/components/shell-components.js +1 -0
  21. package/dist/integrations/pi/components/shell-editor-autocomplete.js +10 -0
  22. package/dist/integrations/pi/components/shell-footer-status.js +14 -9
  23. package/dist/integrations/pi/components/shell-presenters-info.d.ts +36 -0
  24. package/dist/integrations/pi/components/shell-presenters-info.js +78 -0
  25. package/dist/integrations/pi/components/shell-presenters-transcript.d.ts +3 -36
  26. package/dist/integrations/pi/components/shell-presenters-transcript.js +88 -128
  27. package/dist/integrations/pi/components/shell-shared-facade.d.ts +11 -1
  28. package/dist/integrations/pi/engine/adapter.d.ts +15 -4
  29. package/dist/integrations/pi/engine/adapter.js +185 -37
  30. package/dist/integrations/pi/engine/http-dispatcher.d.ts +4 -0
  31. package/dist/integrations/pi/engine/http-dispatcher.js +25 -0
  32. package/dist/integrations/pi/engine/index.d.ts +3 -0
  33. package/dist/integrations/pi/engine/index.js +3 -0
  34. package/dist/integrations/pi/engine/project-trust-preflight.d.ts +22 -0
  35. package/dist/integrations/pi/engine/project-trust-preflight.js +50 -0
  36. package/dist/integrations/pi/engine/runtime-integration.d.ts +16 -1
  37. package/dist/integrations/pi/engine/runtime-integration.js +34 -4
  38. package/dist/integrations/pi/engine/settings-effects.d.ts +55 -0
  39. package/dist/integrations/pi/engine/settings-effects.js +229 -0
  40. package/dist/integrations/pi/engine/settings-integration.d.ts +14 -26
  41. package/dist/integrations/pi/engine/settings-integration.js +102 -108
  42. package/dist/integrations/pi/engine/workflow-controllers.d.ts +1 -1
  43. package/dist/integrations/pi/session-ui/clipboard-image.d.ts +11 -0
  44. package/dist/integrations/pi/session-ui/clipboard-image.js +29 -0
  45. package/dist/integrations/pi/session-ui/prompt-chips.js +5 -1
  46. package/dist/integrations/pi/session-ui/session-shell-root.d.ts +9 -2
  47. package/dist/integrations/pi/session-ui/session-shell-root.js +83 -9
  48. package/dist/integrations/pi/session-ui/session-shell.d.ts +2 -0
  49. package/dist/integrations/pi/session-ui/session-shell.js +151 -15
  50. package/dist/integrations/pi/session-ui/session-viewport-controller.js +34 -2
  51. package/dist/integrations/pi/session-ui/system-clipboard.d.ts +9 -0
  52. package/dist/integrations/pi/session-ui/system-clipboard.js +34 -5
  53. package/dist/integrations/pi/tui-runtime/adapter.d.ts +4 -0
  54. package/dist/integrations/pi/tui-runtime/adapter.js +28 -0
  55. package/dist/native/darwin-arm64/manifest.json +1 -1
  56. package/dist/native/linux-x64/manifest.json +1 -1
  57. package/dist/native/win32-x64/manifest.json +2 -2
  58. package/dist/native/win32-x64/process-guardian.exe +0 -0
  59. package/dist/ui/components/spans.d.ts +2 -0
  60. package/dist/ui/components/spans.js +25 -0
  61. package/dist/ui/components/text.js +24 -2
  62. package/dist/ui/settings/sections.d.ts +8 -19
  63. package/dist/ui/settings/sections.js +12 -4
  64. package/dist/ui/settings/session.d.ts +8 -18
  65. package/dist/ui/settings/session.js +59 -52
  66. package/docs/architecture/project-structure.md +14 -0
  67. package/docs/ci-release-runbook.md +75 -9
  68. package/docs/features/launch-profiles.md +3 -3
  69. package/docs/repository-governance-live-acceptance.md +77 -0
  70. package/package.json +5 -2
@@ -1,147 +1,106 @@
1
1
  import { AssistantMessageComponent, BashExecutionComponent, CompactionSummaryMessageComponent, CustomMessageComponent, DynamicBorder, getMarkdownTheme, parseSkillBlock, ToolExecutionComponent, UserMessageComponent, } from "@earendil-works/pi-coding-agent";
2
2
  import { SkillInvocationMessageComponent } from "./upstream/components/skill-invocation-message.js";
3
- import { Container, Markdown, Spacer, Text, } from "#pi-tui";
3
+ import { createMermaidMarkdownTransformer } from "./upstream/components/mermaid.js";
4
+ import { Container, Image, Spacer, Text, } from "#pi-tui";
4
5
  import { PRODUCT_TEXT } from "../../../product-identity.js";
5
6
  import { createPiSubmittedPromptComponent, } from "./submitted-prompt-adapter.js";
6
- import { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
7
7
  import { PINNED_PI_LAYOUT, piTheme, } from "./theme.js";
8
- import { componentPort, createTuiFacade, ensureTheme, formatSessionTokens, isRecord, } from "./shell-shared-facade.js";
9
- export function renderPiShellStatusText(message, width) {
10
- ensureTheme();
11
- return new Text(piTheme().fg("dim", message), PINNED_PI_LAYOUT.outputPad, 0).render(width);
12
- }
13
- export function createPiShellSessionInfo(presentation) {
14
- ensureTheme();
15
- const { stats, sessionName, cacheWaste, usageBreakdown } = presentation;
16
- let info = `${piTheme().bold("Session Info")}\n\n`;
17
- if (sessionName)
18
- info += `${piTheme().fg("dim", "Name:")} ${sessionName}\n`;
19
- info += `${piTheme().fg("dim", "File:")} ${stats.sessionFile ?? "In-memory"}\n`;
20
- info += `${piTheme().fg("dim", "ID:")} ${stats.sessionId}\n\n`;
21
- info += `${piTheme().bold("Messages")}\n`;
22
- info += `${piTheme().fg("dim", "Total:")} ${stats.totalMessages}\n`;
23
- info += `${piTheme().fg("dim", "User:")} ${stats.userMessages}\n`;
24
- info += `${piTheme().fg("dim", "Assistant:")} ${stats.assistantMessages}\n`;
25
- info += `${piTheme().fg("dim", "Tools:")} ${stats.toolCalls} calls, ${stats.toolResults} results\n\n`;
26
- info += `${piTheme().bold("Tokens")}\n`;
27
- const { input, cacheRead, cacheWrite } = stats.tokens;
28
- const promptTokens = input + cacheRead + cacheWrite;
29
- info += `${piTheme().fg("dim", "Input:")} ${promptTokens.toLocaleString()}\n`;
30
- if (promptTokens > 0 && (cacheRead > 0 || cacheWrite > 0)) {
31
- const hitRate = piTheme().fg("dim", `(${((cacheRead / promptTokens) * 100).toFixed(1)}%)`);
32
- info += ` ${piTheme().fg("dim", "Cached:")} ${cacheRead.toLocaleString()} ${hitRate}\n`;
33
- const written = cacheWrite > 0 ? ` ${piTheme().fg("dim", `(${cacheWrite.toLocaleString()} written to cache)`)}` : "";
34
- info += ` ${piTheme().fg("dim", "Uncached:")} ${(input + cacheWrite).toLocaleString()}${written}\n`;
35
- }
36
- info += `${piTheme().fg("dim", "Output:")} ${stats.tokens.output.toLocaleString()}\n`;
37
- info += `${piTheme().fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
38
- if (stats.cost > 0 || cacheWaste.missedTokens > 0) {
39
- info += `\n${piTheme().bold("Cost")}\n`;
40
- info += `${piTheme().fg("dim", "Total:")} $${stats.cost.toFixed(3)}`;
41
- if (usageBreakdown.length > 1) {
42
- for (const entry of usageBreakdown) {
43
- info += `\n ${piTheme().fg("dim", `${entry.key}:`)} $${entry.cost.toFixed(3)} ${piTheme().fg("dim", `(${formatSessionTokens(entry.tokens)} tokens)`)}`;
44
- }
45
- }
46
- if (cacheWaste.missedTokens > 0) {
47
- const missLabel = cacheWaste.missCount === 1 ? "1 miss" : `${cacheWaste.missCount} misses`;
48
- const detail = `${cacheWaste.missedTokens.toLocaleString()} tokens, ${missLabel}`;
49
- info += cacheWaste.missedCost >= 0.0001
50
- ? `\n${piTheme().fg("dim", "Cache Re-billed:")} $${cacheWaste.missedCost.toFixed(3)} ${piTheme().fg("dim", `(${detail})`)}`
51
- : `\n${piTheme().fg("dim", "Cache Re-billed:")} ${detail}`;
52
- }
53
- }
54
- const container = new Container();
55
- container.addChild(new Spacer(1));
56
- container.addChild(new Text(info, 1, 0));
57
- return componentPort(container);
58
- }
59
- export function createPiShellChangelog(markdown) {
60
- ensureTheme();
61
- const container = new Container();
62
- container.addChild(new Spacer(1));
63
- container.addChild(new DynamicBorder());
64
- container.addChild(new Text(piTheme().bold(piTheme().fg("accent", "What's New")), 1, 0));
65
- container.addChild(new Spacer(1));
66
- container.addChild(new Markdown(markdown.trim() || "No changelog entries found.", 1, 1, getMarkdownTheme()));
67
- container.addChild(new DynamicBorder());
68
- return componentPort(container);
69
- }
70
- export function createPiShellHotkeys() {
71
- ensureTheme();
72
- const keys = new KeybindingsManager();
73
- const display = (action) => keys.getKeys(action)
74
- .map(key => key.split("+").map(part => part.charAt(0).toUpperCase() + part.slice(1)).join("+"))
75
- .join("/");
76
- const row = (actions, description) => `| ${actions.map(action => `\`${display(action)}\``).join(" / ")} | ${description} |`;
77
- const markdown = [
78
- "**Navigation**", "| Key | Action |", "|-----|--------|",
79
- row(["tui.editor.cursorUp", "tui.editor.cursorDown", "tui.editor.cursorLeft", "tui.editor.cursorRight"], "Move cursor / browse history"),
80
- row(["tui.editor.cursorWordLeft", "tui.editor.cursorWordRight"], "Move by word"),
81
- row(["tui.editor.cursorLineStart"], "Start of line"), row(["tui.editor.cursorLineEnd"], "End of line"),
82
- row(["tui.editor.jumpForward"], "Jump forward to character"), row(["tui.editor.jumpBackward"], "Jump backward to character"),
83
- row(["tui.editor.pageUp", "tui.editor.pageDown"], "Scroll by page"), "",
84
- "**Editing**", "| Key | Action |", "|-----|--------|",
85
- row(["tui.input.submit"], "Send message"),
86
- row(["tui.input.newLine"], `New line${process.platform === "win32" ? " (Ctrl+Enter on Windows Terminal)" : ""}`),
87
- row(["tui.editor.deleteWordBackward"], "Delete word backwards"), row(["tui.editor.deleteWordForward"], "Delete word forwards"),
88
- row(["tui.editor.deleteToLineStart"], "Delete to start of line"), row(["tui.editor.deleteToLineEnd"], "Delete to end of line"),
89
- row(["tui.editor.yank"], "Paste the most-recently-deleted text"), row(["tui.editor.yankPop"], "Cycle through the deleted text after pasting"),
90
- row(["tui.editor.undo"], "Undo"), "", "**Other**", "| Key | Action |", "|-----|--------|",
91
- row(["tui.input.tab"], "Path completion / accept autocomplete"), row(["app.interrupt"], "Cancel autocomplete / abort streaming"),
92
- row(["app.clear"], "Clear editor (first) / exit (second)"), row(["app.exit"], "Exit (when editor is empty)"),
93
- row(["app.suspend"], "Suspend to background"), row(["app.thinking.cycle"], "Cycle thinking level"),
94
- row(["app.model.cycleForward", "app.model.cycleBackward"], "Cycle models"), row(["app.model.select"], "Open model selector"),
95
- row(["app.tools.expand"], "Toggle tool output expansion"), row(["app.thinking.toggle"], "Toggle thinking block visibility"),
96
- row(["app.editor.external"], "Edit message in external editor"), row(["app.message.copy"], "Copy last assistant message"),
97
- row(["app.message.followUp"], "Queue follow-up message"), row(["app.message.dequeue"], "Restore queued messages"),
98
- row(["app.clipboard.pasteImage"], "Paste image or text from clipboard"),
99
- "| `/` | Slash commands |", "| `!` | Run bash command |", "| `!!` | Run bash command (excluded from context) |",
100
- ].join("\n");
101
- const container = new Container();
102
- container.addChild(new Spacer(1));
103
- container.addChild(new DynamicBorder());
104
- container.addChild(new Text(piTheme().bold(piTheme().fg("accent", "Keyboard Shortcuts")), 1, 0));
105
- container.addChild(new Spacer(1));
106
- container.addChild(new Markdown(markdown, 1, 1, getMarkdownTheme()));
107
- container.addChild(new DynamicBorder());
108
- return componentPort(container);
109
- }
110
- export function createPiShellTranscriptComponent(initial, cwd, extensions, submittedPrompt) {
8
+ import { componentPort, createTuiFacade, ensureTheme, isRecord, } from "./shell-shared-facade.js";
9
+ export function createPiShellTranscriptComponent(initial, cwd, extensions, submittedPrompt, initialOutputPad = PINNED_PI_LAYOUT.outputPad, initialHideThinkingBlock = false, initialMermaidRenderingMode = "off", initialShowImages = true, initialImageWidthCells = 80, imageAssets) {
111
10
  ensureTheme();
112
11
  let block = initial;
113
12
  let expanded = false;
114
- let component = transcriptComponent(block, cwd, expanded, extensions, submittedPrompt);
13
+ let outputPad = initialOutputPad;
14
+ let hideThinkingBlock = initialHideThinkingBlock;
15
+ let mermaidRenderingMode = initialMermaidRenderingMode;
16
+ let showImages = initialShowImages;
17
+ let imageWidthCells = initialImageWidthCells;
18
+ const rebuild = () => withTranscriptImages(transcriptComponent(block, cwd, expanded, extensions, submittedPrompt, outputPad, hideThinkingBlock, mermaidRenderingMode, showImages, imageWidthCells), block, imageAssets, showImages, imageWidthCells);
19
+ let component = rebuild();
115
20
  return {
116
21
  get id() { return block.id; },
117
22
  get revision() { return block.revision; },
118
- render: width => component.render(width),
23
+ render: width => renderWithOutputPad(component, block.kind, width, outputPad),
119
24
  invalidate: () => component.invalidate(),
120
25
  update(next) {
121
26
  if (next.id !== block.id)
122
27
  throw new TypeError("Pi transcript component identity cannot change");
123
28
  const previous = block;
124
29
  block = next;
125
- if (!updateTranscriptComponent(component, previous, next, expanded)) {
126
- component = transcriptComponent(block, cwd, expanded, extensions, submittedPrompt);
127
- }
30
+ if (!updateTranscriptComponent(component, previous, next, expanded))
31
+ component = rebuild();
128
32
  },
129
33
  setExpanded(next) {
130
34
  if (expanded === next)
131
35
  return;
132
36
  expanded = next;
133
- if ("setExpanded" in component && typeof component.setExpanded === "function") {
37
+ if ("setExpanded" in component && typeof component.setExpanded === "function")
134
38
  component.setExpanded(expanded);
39
+ else
40
+ component = rebuild();
41
+ },
42
+ setOutputPad(padding) {
43
+ if (outputPad === padding)
44
+ return;
45
+ outputPad = padding;
46
+ component = rebuild();
47
+ },
48
+ setHideThinkingBlock(hidden) {
49
+ if (hideThinkingBlock === hidden)
50
+ return;
51
+ hideThinkingBlock = hidden;
52
+ component = rebuild();
53
+ },
54
+ setMermaidRenderingMode(mode) {
55
+ if (mermaidRenderingMode === mode)
56
+ return;
57
+ mermaidRenderingMode = mode;
58
+ component = rebuild();
59
+ },
60
+ setImagePresentation(show, width) {
61
+ showImages = show;
62
+ imageWidthCells = width;
63
+ if (component instanceof ToolExecutionComponent) {
64
+ component.setShowImages(show);
65
+ component.setImageWidthCells(width);
135
66
  }
136
- else {
137
- component = transcriptComponent(block, cwd, expanded, extensions, submittedPrompt);
138
- }
67
+ else
68
+ component = rebuild();
139
69
  },
140
70
  };
141
71
  }
72
+ function withTranscriptImages(component, block, assets, showImages, imageWidthCells) {
73
+ const references = block.imageReferences ?? [];
74
+ if (references.length === 0)
75
+ return component;
76
+ const container = new Container();
77
+ container.addChild(component);
78
+ for (const reference of references) {
79
+ container.addChild(new Spacer(1));
80
+ const asset = assets?.resolve(reference.assetId) ?? null;
81
+ if (!showImages) {
82
+ container.addChild(new Text(piTheme().fg("muted", `[Image hidden: ${reference.mimeType}, ${reference.byteLength} bytes]`), 1, 0));
83
+ }
84
+ else if (asset === null) {
85
+ container.addChild(new Text(piTheme().fg("warning", `[Image unavailable: ${reference.mimeType}]`), 1, 0));
86
+ }
87
+ else {
88
+ container.addChild(new Image(asset.data, asset.mimeType, {
89
+ fallbackColor: text => piTheme().fg("muted", text),
90
+ }, { maxWidthCells: imageWidthCells, filename: reference.assetId }));
91
+ }
92
+ }
93
+ return container;
94
+ }
95
+ function renderWithOutputPad(component, kind, width, outputPad) {
96
+ const rows = component.render(width);
97
+ if (outputPad !== 0 || (kind !== "tool-call" && kind !== "tool-result" && kind !== "bash"))
98
+ return rows;
99
+ return rows.map(row => row.startsWith(" ") ? row.slice(1) : row);
100
+ }
142
101
  export function renderPiShellTranscriptBlock(block, width, cwd) {
143
102
  ensureTheme();
144
- return transcriptComponent(block, cwd, true).render(width);
103
+ return transcriptComponent(block, cwd, true, undefined, undefined, PINNED_PI_LAYOUT.outputPad, false, "off", true, 80).render(width);
145
104
  }
146
105
  /**
147
106
  * Pinned Pi's CLI prints startup diagnostics with `reportDiagnostics` before
@@ -176,7 +135,7 @@ export function renderPiShellPackageUpdateNotice(packages, width) {
176
135
  container.addChild(new DynamicBorder(text => theme.fg("warning", text)));
177
136
  return container.render(width);
178
137
  }
179
- function transcriptComponent(block, cwd, expanded, extensions, submittedPrompt) {
138
+ function transcriptComponent(block, cwd, expanded, extensions, submittedPrompt, outputPad, hideThinkingBlock, mermaidRenderingMode, showImages, imageWidthCells) {
180
139
  switch (block.kind) {
181
140
  case "user": {
182
141
  const skill = parseSkillBlock(block.text);
@@ -194,10 +153,10 @@ function transcriptComponent(block, cwd, expanded, extensions, submittedPrompt)
194
153
  }
195
154
  case "assistant":
196
155
  case "thinking":
197
- return assistantComponent(block);
156
+ return assistantComponent(block, outputPad, hideThinkingBlock, mermaidRenderingMode);
198
157
  case "tool-call":
199
158
  case "tool-result": {
200
- const component = toolComponent(block, cwd, extensions);
159
+ const component = toolComponent(block, cwd, extensions, showImages, imageWidthCells);
201
160
  component.setExpanded(expanded);
202
161
  return component;
203
162
  }
@@ -212,13 +171,13 @@ function transcriptComponent(block, cwd, expanded, extensions, submittedPrompt)
212
171
  return component;
213
172
  }
214
173
  case "retry":
215
- return new Text(piTheme().fg("warning", `Retry: ${block.text}`), PINNED_PI_LAYOUT.outputPad, 0);
174
+ return new Text(piTheme().fg("warning", `Retry: ${block.text}`), outputPad, 0);
216
175
  case "error":
217
- return new Text(piTheme().fg("error", `Error: ${block.text}`), PINNED_PI_LAYOUT.outputPad, 0);
176
+ return new Text(piTheme().fg("error", `Error: ${block.text}`), outputPad, 0);
218
177
  case "system":
219
- return new Text(piTheme().fg("dim", block.text), PINNED_PI_LAYOUT.outputPad, 0);
178
+ return new Text(piTheme().fg("dim", block.text), outputPad, 0);
220
179
  case "custom":
221
- return customMessageComponent(block, expanded, extensions);
180
+ return customMessageComponent(block, expanded, extensions, outputPad);
222
181
  case "bash":
223
182
  return bashExecutionComponent(block, cwd, expanded);
224
183
  }
@@ -267,8 +226,9 @@ function updateTranscriptComponent(component, previous, next, expanded) {
267
226
  }
268
227
  return false;
269
228
  }
270
- function assistantComponent(block) {
271
- const component = new AssistantMessageComponent(undefined, false, getMarkdownTheme(), undefined, PINNED_PI_LAYOUT.outputPad);
229
+ function assistantComponent(block, outputPad, hideThinkingBlock, mermaidRenderingMode) {
230
+ const transformer = createMermaidMarkdownTransformer({ getMode: () => mermaidRenderingMode, theme: piTheme() });
231
+ const component = new AssistantMessageComponent(undefined, hideThinkingBlock, getMarkdownTheme(), undefined, outputPad, [transformer]);
272
232
  component.updateContent(validatedAssistantMessage(block), block.status === "live");
273
233
  return component;
274
234
  }
@@ -336,12 +296,12 @@ function validatedMessageRenderer(value) {
336
296
  function isPiMessageRenderer(value) {
337
297
  return typeof value === "function";
338
298
  }
339
- function toolComponent(block, cwd, extensions) {
299
+ function toolComponent(block, cwd, extensions, showImages, imageWidthCells) {
340
300
  const payload = blockPayload(block);
341
301
  const toolCallId = stringPayload(payload, "toolCallId") ?? block.id;
342
302
  const toolName = stringPayload(payload, "toolName") ?? block.title ?? "tool";
343
303
  const argumentsPayload = toolArguments(payload);
344
- const component = new ToolExecutionComponent(toolName, toolCallId, argumentsPayload, undefined, validatedToolDefinition(extensions?.getToolDefinition(toolName)), createTuiFacade({ getColumns: () => 80, getRows: () => 24, requestRender() { }, onSubmit() { } }), cwd);
304
+ const component = new ToolExecutionComponent(toolName, toolCallId, argumentsPayload, { showImages, imageWidthCells }, validatedToolDefinition(extensions?.getToolDefinition(toolName)), createTuiFacade({ getColumns: () => 80, getRows: () => 24, requestRender() { }, onSubmit() { } }), cwd);
345
305
  if (block.status === "live")
346
306
  component.markExecutionStarted();
347
307
  if (block.status === "finalized" || payload.argsComplete === true)
@@ -357,7 +317,7 @@ function toolComponent(block, cwd, extensions) {
357
317
  }
358
318
  return component;
359
319
  }
360
- function customMessageComponent(block, expanded, extensions) {
320
+ function customMessageComponent(block, expanded, extensions, outputPad) {
361
321
  const payload = blockPayload(block);
362
322
  const message = {
363
323
  role: "custom",
@@ -368,7 +328,7 @@ function customMessageComponent(block, expanded, extensions) {
368
328
  timestamp: numericPayload(block, "timestamp") || 0,
369
329
  };
370
330
  const renderer = validatedMessageRenderer(extensions?.getMessageRenderer(message.customType));
371
- const component = new CustomMessageComponent(message, renderer, getMarkdownTheme(), PINNED_PI_LAYOUT.outputPad);
331
+ const component = new CustomMessageComponent(message, renderer, getMarkdownTheme(), outputPad);
372
332
  component.setExpanded(expanded);
373
333
  return component;
374
334
  }
@@ -1,5 +1,5 @@
1
1
  import { visibleWidth, type AutocompleteProvider, type Component, type TUI } from "#pi-tui";
2
- import type { OwnedUiSessionViewModel, OwnedUiThinkingLevel, OwnedUiTranscriptBlock } from "../../../contracts/owned-ui/index.js";
2
+ import type { OwnedUiImageAttachment, OwnedUiSessionViewModel, OwnedUiThinkingLevel, OwnedUiTranscriptBlock } from "../../../contracts/owned-ui/index.js";
3
3
  import type { PresentationComponentPort } from "../../../contracts/presentation/index.js";
4
4
  /** Terminal-cell width authority used by Pi-rendered component rows. */
5
5
  export declare const piShellVisibleWidth: typeof visibleWidth;
@@ -37,6 +37,8 @@ export interface PiShellEditorPort extends PiShellComponentPort {
37
37
  setSubmitHandler(handler: (text: string) => void): void;
38
38
  setInterruptHandler(handler: () => void): void;
39
39
  setAutocompleteCommands(commands: readonly PiShellAutocompleteCommand[]): void;
40
+ setPaddingX(padding: number): void;
41
+ setAutocompleteMaxVisible(maxVisible: number): void;
40
42
  addAutocompleteProvider(factory: unknown): void;
41
43
  setThinkingLevel(level: OwnedUiThinkingLevel): void;
42
44
  hasSelection(): boolean;
@@ -55,6 +57,7 @@ export interface PiShellViewComponentPort extends PiShellComponentPort {
55
57
  }
56
58
  export interface PiShellStatusPort extends PiShellViewComponentPort {
57
59
  setWorkingOverride(message: string | undefined): void;
60
+ setOutputPad(padding: 0 | 1): void;
58
61
  }
59
62
  export interface PiShellQueuedInputPort extends PiShellComponentPort {
60
63
  update(submissions: readonly string[]): void;
@@ -73,6 +76,9 @@ export interface PiShellResourceEntry {
73
76
  export interface PiShellLoadedResourcesPort extends PiShellComponentPort {
74
77
  setExpanded(expanded: boolean): void;
75
78
  }
79
+ export interface PiShellImageAssetResolver {
80
+ resolve(assetId: string): OwnedUiImageAttachment | null;
81
+ }
76
82
  export interface PiShellExtensionRendererResolver {
77
83
  getMessageRenderer(customType: string): unknown;
78
84
  getToolDefinition(toolName: string): unknown;
@@ -82,6 +88,10 @@ export interface PiShellTranscriptComponentPort extends PiShellComponentPort {
82
88
  readonly revision: number;
83
89
  update(block: OwnedUiTranscriptBlock): void;
84
90
  setExpanded(expanded: boolean): void;
91
+ setOutputPad(padding: 0 | 1): void;
92
+ setHideThinkingBlock(hidden: boolean): void;
93
+ setMermaidRenderingMode(mode: "off" | "final" | "streaming"): void;
94
+ setImagePresentation(showImages: boolean, imageWidthCells: number): void;
85
95
  }
86
96
  export interface PiShellStartupNotice {
87
97
  readonly kind: "info" | "warning" | "error";
@@ -1,11 +1,16 @@
1
1
  import { type AgentSessionRuntime, type AgentSessionServices, type SessionInfo } from "@earendil-works/pi-coding-agent";
2
- import { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, type OwnedUiCommand, type OwnedUiCommandOutcome, type OwnedUiEvent, type OwnedUiSessionViewModel, type OwnedUiSnapshot } from "../../../contracts/owned-ui/index.js";
2
+ import { OWNED_UI_EXTENSION_CONTRACT_VERSION, OWNED_UI_EXTENSION_RENDER_CALLBACKS, OWNED_UI_EXTENSION_UI_CALLBACKS, OWNED_UI_EXTENSION_UI_PROPERTIES, type OwnedUiCommand, type OwnedUiCommandOutcome, type OwnedUiImageAttachment, type OwnedUiEvent, type OwnedUiSessionViewModel, type OwnedUiSnapshot } from "../../../contracts/owned-ui/index.js";
3
3
  import { type PiAuthenticationProviderOption, type PiBashWorkflowResult, type PiPinnedSettingsCallback, type PiPinnedSettingsSnapshot, type PiWorkflowAutocompleteCommand, type PiWorkflowHost, type PiWorkflowInteractionHost, type PiWorkflowOption, type PiWorkflowRequest, type PiWorkflowResult } from "./workflows.js";
4
- import type { AgentSettingsPort } from "../../../contracts/agent-engine/index.js";
4
+ import { PiSettingsIntegration } from "./settings-integration.js";
5
+ import type { PiSettingOwnerHandlers } from "./settings-effects.js";
6
+ import type { PiProjectTrustPreflightPrompt } from "./project-trust-preflight.js";
7
+ import type { AgentSettingOwner } from "../../../contracts/agent-engine/index.js";
5
8
  export interface PiEngineRuntimeFactoryInput {
6
9
  readonly cwd: string;
7
10
  readonly agentDir: string;
8
11
  readonly sessionId: string;
12
+ readonly sessionPath?: string;
13
+ readonly projectTrustPrompt?: PiProjectTrustPreflightPrompt;
9
14
  }
10
15
  export interface PiScopedModelDescriptor {
11
16
  readonly provider: string;
@@ -90,6 +95,7 @@ export interface PiEngineAdapterOptions {
90
95
  readonly cwd?: string;
91
96
  readonly agentDir?: string;
92
97
  readonly sessionId?: string;
98
+ readonly sessionPath?: string;
93
99
  readonly createRuntime?: PiEngineRuntimeFactory;
94
100
  readonly workflowHost?: PiWorkflowHost;
95
101
  /**
@@ -98,6 +104,8 @@ export interface PiEngineAdapterOptions {
98
104
  * offering stay here.
99
105
  */
100
106
  readonly availableThemes?: () => readonly string[];
107
+ readonly settingsProductMode?: "bare" | "comparison";
108
+ readonly projectTrustPrompt?: PiProjectTrustPreflightPrompt;
101
109
  /**
102
110
  * Startup extension-package update probe, mirroring pinned Pi's interactive
103
111
  * mode. Returns display names of packages with updates available.
@@ -115,6 +123,8 @@ export declare class PiEngineAdapter {
115
123
  get sessionId(): string;
116
124
  get sessionGeneration(): number;
117
125
  get agentDir(): string;
126
+ resolveTranscriptImage(assetId: string): OwnedUiImageAttachment | null;
127
+ currentSessionFile(): string | null;
118
128
  get disposed(): boolean;
119
129
  start(): Promise<OwnedUiSessionViewModel>;
120
130
  onEvent(listener: (event: OwnedUiEvent) => void): () => void;
@@ -132,7 +142,8 @@ export declare class PiEngineAdapter {
132
142
  */
133
143
  configuredTheme(): string | undefined;
134
144
  /** Settings port for the live runtime, or null before the runtime is available. */
135
- settingsPort(): AgentSettingsPort | null;
145
+ settingsPort(): PiSettingsIntegration | null;
146
+ bindSettingsOwner(owner: AgentSettingOwner, handlers: PiSettingOwnerHandlers): () => void;
136
147
  pinnedModelSelectorContext(): {
137
148
  readonly currentModel: unknown;
138
149
  readonly settingsManager: unknown;
@@ -160,7 +171,7 @@ export declare class PiEngineAdapter {
160
171
  clearQueuedWorkflows(): readonly string[];
161
172
  abortBashWorkflow(): void;
162
173
  executeBashWorkflow(command: string, excludeFromContext: boolean): Promise<PiBashWorkflowResult>;
163
- applyPinnedSettingValue(callback: PiPinnedSettingsCallback, value: unknown): PiWorkflowResult;
174
+ applyPinnedSettingValue(callback: PiPinnedSettingsCallback, value: unknown): Promise<PiWorkflowResult>;
164
175
  executeWorkflow(request: PiWorkflowRequest): Promise<PiWorkflowResult>;
165
176
  view(): OwnedUiSessionViewModel;
166
177
  snapshot(): OwnedUiSnapshot;