@selesai/code 0.2.0 → 0.3.0

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 (59) hide show
  1. package/dist/config.d.ts +4 -15
  2. package/dist/config.d.ts.map +1 -1
  3. package/dist/config.js +5 -45
  4. package/dist/config.js.map +1 -1
  5. package/dist/core/agent-session.d.ts +1 -0
  6. package/dist/core/agent-session.d.ts.map +1 -1
  7. package/dist/core/agent-session.js +8 -0
  8. package/dist/core/agent-session.js.map +1 -1
  9. package/dist/core/model-registry.d.ts +4 -1
  10. package/dist/core/model-registry.d.ts.map +1 -1
  11. package/dist/core/model-registry.js +101 -51
  12. package/dist/core/model-registry.js.map +1 -1
  13. package/dist/defaults/models.json +79 -24
  14. package/dist/extensions/copy-turn.ts +2 -2
  15. package/dist/extensions/pi-powerline-footer/bash-mode/editor.ts +2 -2
  16. package/dist/extensions/pi-powerline-footer/index.ts +31 -31
  17. package/dist/extensions/pi-powerline-footer/package.json +2 -2
  18. package/dist/extensions/pi-powerline-footer/tests/bash-mode.test.ts +10 -10
  19. package/dist/extensions/pi-powerline-footer/tests/jump-shortcuts.test.ts +1 -1
  20. package/dist/extensions/pi-powerline-footer/tests/working-vibes.test.ts +2 -2
  21. package/dist/extensions/pi-powerline-footer/theme.ts +6 -6
  22. package/dist/extensions/pi-powerline-footer/tps.ts +1 -1
  23. package/dist/extensions/pi-powerline-footer/types.ts +7 -7
  24. package/dist/extensions/pi-powerline-footer/working-vibes.ts +51 -51
  25. package/dist/extensions/pi-subagents/agents/architect.md +188 -0
  26. package/dist/extensions/pi-subagents/agents/builder.md +120 -0
  27. package/dist/extensions/pi-subagents/agents/commentator.md +131 -0
  28. package/dist/extensions/pi-subagents/agents/explorer.md +51 -0
  29. package/dist/extensions/pi-subagents/agents/recapper.md +21 -0
  30. package/dist/extensions/pi-subagents/src/shared/utils.ts +9 -3
  31. package/dist/extensions/pi-web-agent/package.json +2 -2
  32. package/dist/extensions/pi-web-agent/src/backends/settings-reader.ts +2 -2
  33. package/dist/extensions/pi-web-agent/src/commands/web-agent-config.ts +1 -1
  34. package/dist/extensions/pi-web-agent/src/extension.ts +1 -1
  35. package/dist/extensions/pi-web-agent/src/presentation/config-store.ts +1 -1
  36. package/dist/extensions/question/helpers.ts +3 -3
  37. package/dist/extensions/question/index.ts +2 -2
  38. package/dist/extensions/question/navigation.ts +2 -2
  39. package/dist/extensions/question/package.json +2 -2
  40. package/dist/extensions/question/question-list.ts +2 -2
  41. package/dist/extensions/question/tests/question-list.test.ts +2 -2
  42. package/dist/extensions/question/tui-adapter.ts +2 -2
  43. package/dist/extensions/question/types.ts +2 -2
  44. package/dist/extensions/question/ui-protocol.ts +2 -2
  45. package/dist/extensions/rtk.ts +2 -2
  46. package/dist/extensions/tokenin-onboarding.ts +2 -2
  47. package/dist/extensions/undo.ts +1 -1
  48. package/dist/extensions/web-agent-onboarding.ts +3 -3
  49. package/dist/extensions/workflow/adapter.ts +16 -8
  50. package/dist/extensions/workflow/extension.ts +1 -1
  51. package/dist/extensions/workflow/package.json +1 -1
  52. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  53. package/dist/modes/interactive/components/assistant-message.js +2 -0
  54. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  55. package/dist/utils/thinking-tags.d.ts +7 -0
  56. package/dist/utils/thinking-tags.d.ts.map +1 -0
  57. package/dist/utils/thinking-tags.js +63 -0
  58. package/dist/utils/thinking-tags.js.map +1 -0
  59. package/package.json +2 -2
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: commentator
3
+ model: tokenin/kimi-k2.7-code
4
+ thinking: high
5
+ description: Versatile review specialist for code diffs, plans, proposed solutions, codebase health, and PR/issue validation
6
+ tools: read, grep, find, ls, bash, edit, write, intercom
7
+ systemPromptMode: replace
8
+ inheritProjectContext: true
9
+ inheritSkills: true
10
+ skill: ponytail-review
11
+ defaultReads: plan.md, progress.md
12
+ defaultContext: fork
13
+ output: review.md
14
+ ---
15
+
16
+ You are a disciplined commentator subagent. Your job is to inspect, evaluate, and report findings with evidence. You do not guess; you verify from the code, tests, docs, or requirements.
17
+
18
+ ## Review types you handle
19
+
20
+ ### 1. Code diffs (changed files)
21
+ Inspect the actual diff or changed files. Verify:
22
+ - Implementation matches intent and requirements.
23
+ - Code is correct, coherent, and handles edge cases.
24
+ - Tests cover the change and still pass.
25
+ - No unintended side effects or regressions.
26
+ - The change is minimal and readable.
27
+
28
+ ### 2. Plans
29
+ Validate a proposed plan for:
30
+ - Feasibility and completeness.
31
+ - Missing steps or hidden risks.
32
+ - Alignment with existing architecture and constraints.
33
+ - Whether the scope is appropriately bounded.
34
+
35
+ ### 3. Proposed solutions
36
+ Evaluate a suggested approach for:
37
+ - Correctness and tradeoffs.
38
+ - Fit with existing codebase patterns.
39
+ - Whether simpler alternatives exist.
40
+ - Edge cases the proposal may miss.
41
+
42
+ ### 4. Current overall state of the codebase
43
+ Assess codebase health by inspecting key files, tests, and structure. Look for:
44
+ - Architecture drift or tech debt.
45
+ - Inconsistent patterns or naming.
46
+ - Areas lacking tests or documentation.
47
+ - Obvious bugs or fragile code.
48
+ - Opportunities to simplify or consolidate.
49
+
50
+ ### 5. Specific PR or issue
51
+ Review a PR or issue by understanding the context, then verifying:
52
+ - The fix or feature addresses the root cause.
53
+ - Changes are minimal and focused.
54
+ - No regressions are introduced.
55
+ - Tests and docs are updated as needed.
56
+
57
+ ## Working rules
58
+ - Read the plan, progress, and relevant files first when available.
59
+ - Repo-local `progress.md` files are allowed scratch/memory files. Do not flag them as repo noise, delete them, or ask to remove them just because they are untracked. If they appear in a coding repo, they should remain untracked and be covered by `.gitignore`.
60
+ - Use `bash` only for read-only inspection (e.g., `git diff`, `git log`, `git show`, test runs).
61
+ - Do not invent issues. Only report problems you can justify from evidence.
62
+ - Prefer small corrective edits over broad rewrites.
63
+ - If everything looks good, say so plainly.
64
+ - If you are asked to maintain progress, record what you checked and what you found.
65
+ - If review-only or no-edit instructions conflict with progress-writing instructions, review-only/no-edit wins. Do not write `progress.md`; mention the conflict in your final review only if it matters.
66
+
67
+ ## Supervisor coordination
68
+ If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Do not ask for clarification when the only conflict is review-only/no-edit versus progress-writing; no-edit wins. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the review plan. Do not send routine completion handoffs; return the completed review normally.
69
+
70
+ Fall back to generic `intercom` only if `contact_supervisor` is unavailable and the runtime bridge instructions identify a safe target. If no safe target is discoverable, do not guess.
71
+
72
+ ## Review output format
73
+ Structure your findings clearly:
74
+
75
+ ```
76
+ ## Review
77
+ - Correct: what is already good (with evidence)
78
+ - Fixed: issue, location, and resolution (if you applied a fix)
79
+ - Blocker: critical issue that must be resolved before proceeding
80
+ - Note: observation, risk, or follow-up item
81
+ ```
82
+
83
+ When reviewing code, cite file paths and line numbers. When reviewing plans, cite specific sections and assumptions.
84
+
85
+ ## Ponytail review prompt
86
+
87
+ Review diffs for unnecessary complexity. One line per finding: location, what
88
+ to cut, what replaces it. The diff's best outcome is getting shorter.
89
+
90
+ ### Format
91
+
92
+ `L<line>: <tag> <what>. <replacement>.`, or `<file>:L<line>: ...` for
93
+ multi-file diffs.
94
+
95
+ Tags:
96
+
97
+ - `delete:` dead code, unused flexibility, speculative feature. Replacement: nothing.
98
+ - `stdlib:` hand-rolled thing the standard library ships. Name the function.
99
+ - `native:` dependency or code doing what the platform already does. Name the feature.
100
+ - `yagni:` abstraction with one implementation, config nobody sets, layer with one caller.
101
+ - `shrink:` same logic, fewer lines. Show the shorter form.
102
+
103
+ ### Examples
104
+
105
+ ❌ "This EmailValidator class might be more complex than necessary, have you
106
+ considered whether all these validation rules are needed at this stage?"
107
+
108
+ ✅ `L12-38: stdlib: 27-line validator class. "@" in email, 1 line, real validation is the confirmation mail.`
109
+
110
+ ✅ `L4: native: moment.js imported for one format call. Intl.DateTimeFormat, 0 deps.`
111
+
112
+ ✅ `repo.py:L88: yagni: AbstractRepository with one implementation. Inline it until a second one exists.`
113
+
114
+ ✅ `L52-71: delete: retry wrapper around an idempotent local call. Nothing replaces it.`
115
+
116
+ ✅ `L30-44: shrink: manual loop builds dict. dict(zip(keys, values)), 1 line.`
117
+
118
+ ### Scoring
119
+
120
+ End with the only metric that matters: `net: -<N> lines possible.`
121
+
122
+ If there is nothing to cut, say `Lean already. Ship.` and stop.
123
+
124
+ ### Boundaries
125
+
126
+ Scope: over-engineering and complexity only. Correctness bugs, security holes,
127
+ and performance are explicitly out of scope. Route them to a normal review
128
+ pass, not this one. A single smoke test or `assert`-based
129
+ self-check is the ponytail minimum, not bloat, never flag it for deletion.
130
+ Does not apply the fixes, only lists them.
131
+ "stop ponytail-review" or "normal mode": revert to verbose review style.
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: explorer
3
+ model: tokenin/deepseek-v4-flash
4
+ thinking: high
5
+ description: Fast codebase recon that returns compressed context for handoff
6
+ tools: read, grep, find, ls, bash, write, intercom
7
+ systemPromptMode: replace
8
+ inheritProjectContext: true
9
+ inheritSkills: true
10
+ skill: caveman
11
+ output: context.md
12
+ ---
13
+
14
+ You are a explorer subagent running inside pi.
15
+
16
+ Use the provided tools directly. Move fast, but do not guess. Prefer targeted search and selective reading over reading whole files unless the task clearly needs broader coverage.
17
+
18
+ Focus on the minimum context another agent needs in order to act:
19
+ - relevant entry points
20
+ - key types, interfaces, and functions
21
+ - data flow and dependencies
22
+ - files that are likely to need changes
23
+ - constraints, risks, and open questions
24
+
25
+ Working rules:
26
+ - Use `grep`, `find`, `ls`, and `read` to map the area before diving deeper.
27
+ - Use `bash` only for non-interactive inspection commands.
28
+ - When you cite code, use exact file paths and line ranges.
29
+ - If you are told to write output, write it to the provided path and keep the final response short.
30
+ - When running solo, summarize what you found after writing the output.
31
+
32
+ Output format (`context.md`):
33
+
34
+ # Code Context
35
+
36
+ ## Files Retrieved
37
+ List exact files and line ranges.
38
+ 1. `path/to/file.ts` (lines 10-50) - why it matters
39
+ 2. `path/to/other.ts` (lines 100-150) - why it matters
40
+
41
+ ## Key Code
42
+ Include the critical types, interfaces, functions, and small code snippets that matter.
43
+
44
+ ## Architecture
45
+ Explain how the pieces connect.
46
+
47
+ ## Start Here
48
+ Name the first file another agent should open and why.
49
+
50
+ ## Supervisor coordination
51
+ If runtime bridge instructions identify a safe supervisor target and you are blocked or need a decision, use `contact_supervisor` with `reason: "need_decision"` and wait for the reply. Use `reason: "progress_update"` only for meaningful progress or unexpected discoveries that change the plan. Do not send routine completion handoffs; return the completed explorer findings normally.
@@ -0,0 +1,21 @@
1
+ ---
2
+ name: recapper
3
+ model: tokenin/glm-5.2
4
+ thinking: high
5
+ description: Summarize what the current conversation is about and prepare a handoff document.
6
+ tools: read, grep, find, ls, bash, edit, write, intercom
7
+ systemPromptMode: replace
8
+ inheritProjectContext: true
9
+ inheritSkills: true
10
+ defaultReads: plan.md, progress.md
11
+ defaultContext: fork
12
+ output: handoff.md
13
+ ---
14
+
15
+ Spit out a handoff document style that summarising the current conversation so a fresh agent can continue the work.
16
+
17
+ Do not duplicate content already captured in other artifacts (PRDs, plans, ADRs, issues, commits, diffs). Reference them by path or URL instead.
18
+
19
+ Redact any sensitive information, such as API keys, passwords, or personally identifiable information.
20
+
21
+ If the user passed arguments, treat them as a description of what the next session will focus on and tailor the doc accordingly.
@@ -7,6 +7,7 @@ import * as os from "node:os";
7
7
  import * as path from "node:path";
8
8
  import * as piCodingAgent from "@selesai/code";
9
9
  import type { Message } from "@earendil-works/pi-ai";
10
+ import { stripThinkingTagsFromText } from "../../../../utils/thinking-tags.ts";
10
11
  import { formatToolCall } from "./formatters.ts";
11
12
  import type { AgentProgress, AsyncStatus, Details, DisplayItem, ErrorInfo, SingleResult, ToolCallSummary } from "./types.ts";
12
13
 
@@ -438,7 +439,7 @@ export function extractToolArgsPreview(args: Record<string, unknown>): string {
438
439
  export function extractTextFromContent(content: unknown): string {
439
440
  if (!content) return "";
440
441
  // Handle string content directly
441
- if (typeof content === "string") return content;
442
+ if (typeof content === "string") return stripThinkingTagsFromText(content);
442
443
  // Handle array content
443
444
  if (!Array.isArray(content)) return "";
444
445
  const texts: string[] = [];
@@ -446,7 +447,11 @@ export function extractTextFromContent(content: unknown): string {
446
447
  if (part && typeof part === "object") {
447
448
  // Handle { type: "text", text: "..." }
448
449
  if ("type" in part && part.type === "text" && "text" in part) {
449
- texts.push(String(part.text));
450
+ const text = stripThinkingTagsFromText(String(part.text));
451
+ if (text) texts.push(text);
452
+ }
453
+ else if ("type" in part && part.type === "thinking") {
454
+ continue;
450
455
  }
451
456
  // Handle { type: "tool_result", content: "..." }
452
457
  else if ("type" in part && part.type === "tool_result" && "content" in part) {
@@ -455,7 +460,8 @@ export function extractTextFromContent(content: unknown): string {
455
460
  }
456
461
  // Handle { text: "..." } without type
457
462
  else if ("text" in part) {
458
- texts.push(String(part.text));
463
+ const text = stripThinkingTagsFromText(String(part.text));
464
+ if (text) texts.push(text);
459
465
  }
460
466
  }
461
467
  }
@@ -25,7 +25,7 @@
25
25
  "typebox": "^1.1.37"
26
26
  },
27
27
  "peerDependencies": {
28
- "@earendil-works/pi-coding-agent": "*",
28
+ "@selesai/code": "*",
29
29
  "@earendil-works/pi-tui": "*"
30
30
  }
31
- }
31
+ }
@@ -4,7 +4,7 @@
4
4
  // minimal settings.json read. Ceiling: if selesai moves web search config elsewhere, this
5
5
  // helper needs updating; upgrade path = upstream pi-web-agent adopting a settings hook.
6
6
  import { existsSync, readFileSync } from 'node:fs';
7
- import { getSettingsPath } from '@earendil-works/pi-coding-agent';
7
+ import { getSettingsPath } from '@selesai/code';
8
8
 
9
9
  /**
10
10
  * Read the Brave API key from selesai settings.json (webAgent.braveApiKey).
@@ -22,4 +22,4 @@ export function readBraveKeyFromSettings(settingsPath: string = getSettingsPath(
22
22
  } catch {
23
23
  return undefined;
24
24
  }
25
- }
25
+ }
@@ -10,7 +10,7 @@ import {
10
10
  DynamicBorder,
11
11
  getSettingsListTheme,
12
12
  type ExtensionAPI
13
- } from '@earendil-works/pi-coding-agent';
13
+ } from '@selesai/code';
14
14
  import { Container, SelectList, SettingsList, Text, type SelectItem, type SettingItem } from '@earendil-works/pi-tui';
15
15
  import {
16
16
  DEFAULT_PRESENTATION_CONFIG,
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from '@earendil-works/pi-coding-agent';
1
+ import type { ExtensionAPI } from '@selesai/code';
2
2
  import { DEFAULT_BACKEND_CONFIG, type BackendConfig } from './backends/config.js';
3
3
  import { Type } from 'typebox';
4
4
  import { registerWebAgentConfigCommands } from './commands/web-agent-config.js';
@@ -1,6 +1,6 @@
1
1
  import { mkdir, readFile, rm, writeFile } from 'node:fs/promises';
2
2
  import path from 'node:path';
3
- import { getAgentDir } from '@earendil-works/pi-coding-agent';
3
+ import { getAgentDir } from '@selesai/code';
4
4
  import {
5
5
  DEFAULT_BACKEND_CONFIG,
6
6
  extractBackendConfigOverride,
@@ -1,6 +1,6 @@
1
1
  // Pure helper functions for the question extension.
2
2
 
3
- import type { MarkdownTheme } from "@earendil-works/pi-coding-agent";
3
+ import type { MarkdownTheme } from "@selesai/code";
4
4
 
5
5
  import type { QuestionOption, QuestionResponse, RawOption } from "./types.ts";
6
6
 
@@ -44,7 +44,7 @@ export function safeMarkdownTheme(): MarkdownTheme | undefined {
44
44
  if (_getMarkdownTheme === undefined) {
45
45
  // Dynamic require avoids breaking module load when package is absent.
46
46
  _getMarkdownTheme = (globalThis as any).require
47
- ? (globalThis as any).require("@earendil-works/pi-coding-agent").getMarkdownTheme
47
+ ? (globalThis as any).require("@selesai/code").getMarkdownTheme
48
48
  : null;
49
49
  }
50
50
  if (!_getMarkdownTheme) return undefined;
@@ -99,4 +99,4 @@ export function parseDialogSelections(input: string): string[] {
99
99
 
100
100
  export function isCancelled(value: unknown): value is null | undefined {
101
101
  return value === null || value === undefined;
102
- }
102
+ }
@@ -2,7 +2,7 @@
2
2
  // Owns: QuestionComponent (mode-switching + editor lifecycle + box borders),
3
3
  // tool registration, execute() orchestration via UIProtocol.
4
4
 
5
- import type { ExtensionAPI, KeybindingsManager, Theme } from "@earendil-works/pi-coding-agent";
5
+ import type { ExtensionAPI, KeybindingsManager, Theme } from "@selesai/code";
6
6
  import {
7
7
  Container,
8
8
  type Component,
@@ -668,4 +668,4 @@ export default function questionExtension(pi: ExtensionAPI) {
668
668
  return new Text(text, 0, 0);
669
669
  },
670
670
  });
671
- }
671
+ }
@@ -1,6 +1,6 @@
1
1
  // Vim-style navigation aliases (ctrl+j/k don't collide with fuzzy-search input).
2
2
 
3
- import type { KeybindingsManager } from "@earendil-works/pi-coding-agent";
3
+ import type { KeybindingsManager } from "@selesai/code";
4
4
  import { matchesKey } from "@earendil-works/pi-tui";
5
5
 
6
6
  import { VIM_DOWN, VIM_UP } from "./constants.ts";
@@ -11,4 +11,4 @@ export function matchesUp(data: string, keybindings: KeybindingsManager): boolea
11
11
 
12
12
  export function matchesDown(data: string, keybindings: KeybindingsManager): boolean {
13
13
  return keybindings.matches(data, "tui.select.down") || matchesKey(data, VIM_DOWN);
14
- }
14
+ }
@@ -8,11 +8,11 @@
8
8
  "extensions": ["./index.ts"]
9
9
  },
10
10
  "peerDependencies": {
11
- "@earendil-works/pi-coding-agent": "*",
11
+ "@selesai/code": "*",
12
12
  "@earendil-works/pi-tui": "*",
13
13
  "typebox": "*"
14
14
  },
15
15
  "scripts": {
16
16
  "test": "node --experimental-strip-types --test tests/**/*.test.ts"
17
17
  }
18
- }
18
+ }
@@ -2,7 +2,7 @@
2
2
  // Single-vs-multi is a SelectionMode flag, not a separate class.
3
3
  // Fuzzy search + split-pane preview are single-select-only (matching original behavior).
4
4
 
5
- import type { KeybindingsManager, Theme } from "@earendil-works/pi-coding-agent";
5
+ import type { KeybindingsManager, Theme } from "@selesai/code";
6
6
  import {
7
7
  type Component,
8
8
  fuzzyFilter,
@@ -495,4 +495,4 @@ export class QuestionList implements Component {
495
495
  return `${left}${separator}${right}`;
496
496
  });
497
497
  }
498
- }
498
+ }
@@ -5,7 +5,7 @@ import { Key, matchesKey } from "@earendil-works/pi-tui";
5
5
 
6
6
  import { QuestionList } from "../question-list.ts";
7
7
  import { MultiSelect, SingleSelect } from "../selection-mode.ts";
8
- import type { KeybindingsManager, Theme } from "@earendil-works/pi-coding-agent";
8
+ import type { KeybindingsManager, Theme } from "@selesai/code";
9
9
  import type { ResolvedShortcut } from "../types.ts";
10
10
 
11
11
  // ---------------------------------------------------------------------------
@@ -227,4 +227,4 @@ test("onSubmit passes commentEnabled=true when comment is enabled", () => {
227
227
  list.handleInput(CTRL_G); // enable comment
228
228
  list.handleInput(ENTER); // confirm
229
229
  assert.deepEqual(submitted, [["a"], true]);
230
- });
230
+ });
@@ -1,6 +1,6 @@
1
1
  // TUI protocol adapter — wraps ctx.ui into UIProtocol.
2
2
 
3
- import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
3
+ import type { ExtensionContext } from "@selesai/code";
4
4
  import type { OverlayHandle } from "@earendil-works/pi-tui";
5
5
 
6
6
  import { OVERLAY_MIN_WIDTH, OVERLAY_OVERLAY_MAX_HEIGHT, OVERLAY_WIDTH } from "./constants.ts";
@@ -30,4 +30,4 @@ export function createTUIProtocol(ctx: ExtensionContext): UIProtocol {
30
30
  setStatus: (key, text) => ctx.ui.setStatus(key, text),
31
31
  notify: (msg, level) => ctx.ui.notify(msg, level),
32
32
  };
33
- }
33
+ }
@@ -1,6 +1,6 @@
1
1
  // Shared type definitions for the question extension.
2
2
 
3
- import type { KeybindingsManager } from "@earendil-works/pi-coding-agent";
3
+ import type { KeybindingsManager } from "@selesai/code";
4
4
 
5
5
  export type RawOption = string | { label: string; description?: string };
6
6
 
@@ -99,4 +99,4 @@ export interface ResolvedQuestionParams {
99
99
  displayMode: DisplayMode;
100
100
  shortcuts: ResolvedShortcuts;
101
101
  timeout: number | undefined;
102
- }
102
+ }
@@ -1,6 +1,6 @@
1
1
  // UIProtocol port — abstracts TUI vs dialog/RPC transport.
2
2
 
3
- import type { KeybindingsManager } from "@earendil-works/pi-coding-agent";
3
+ import type { KeybindingsManager } from "@selesai/code";
4
4
  import type { OverlayHandle, Theme, TUI } from "@earendil-works/pi-tui";
5
5
 
6
6
  import type { QuestionResponse, ResolvedQuestionParams } from "./types.ts";
@@ -43,4 +43,4 @@ export interface UIProtocol {
43
43
 
44
44
  export interface FallbackProtocol {
45
45
  ask(params: ResolvedQuestionParams, protocol: UIProtocol): Promise<QuestionResponse | null>;
46
- }
46
+ }
@@ -10,8 +10,8 @@
10
10
  // 1 No RTK equivalent → pass through unchanged
11
11
  // 3 + stdout Rewrite (advisory) → mutate command
12
12
 
13
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
14
- import { isToolCallEventType } from "@earendil-works/pi-coding-agent"
13
+ import type { ExtensionAPI } from "@selesai/code"
14
+ import { isToolCallEventType } from "@selesai/code"
15
15
 
16
16
  const REWRITE_TIMEOUT_MS = 2_000
17
17
  const MIN_SUPPORTED_RTK_MINOR = 23
@@ -11,8 +11,8 @@
11
11
  */
12
12
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
13
  import { dirname, join } from "node:path";
14
- import { getAgentDir, getModelsPath } from "@earendil-works/pi-coding-agent";
15
- import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, SessionStartEvent } from "@earendil-works/pi-coding-agent";
14
+ import { getAgentDir, getModelsPath } from "@selesai/code";
15
+ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, SessionStartEvent } from "@selesai/code";
16
16
 
17
17
  export const TOKEN_IN_PROVIDER = "tokenin";
18
18
  export const TOKEN_IN_DASHBOARD_URL = "https://token-in.selesai.in/dashboard/tokens";
@@ -1,4 +1,4 @@
1
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
1
+ import type { ExtensionAPI } from "@selesai/code";
2
2
  import { createHash } from "node:crypto";
3
3
  import { mkdir, readFile, rm, writeFile } from "node:fs/promises";
4
4
  import { existsSync } from "node:fs";
@@ -11,8 +11,8 @@
11
11
  */
12
12
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
13
  import { dirname, join } from "node:path";
14
- import { getAgentDir, getSettingsPath } from "@earendil-works/pi-coding-agent";
15
- import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, SessionStartEvent } from "@earendil-works/pi-coding-agent";
14
+ import { getAgentDir, getSettingsPath } from "@selesai/code";
15
+ import type { ExtensionAPI, ExtensionCommandContext, ExtensionContext, SessionStartEvent } from "@selesai/code";
16
16
 
17
17
  export type OnboardingResult =
18
18
  | { kind: "saved" }
@@ -219,4 +219,4 @@ export default function webAgentOnboardingExtension(pi: ExtensionAPI): void {
219
219
  }
220
220
  },
221
221
  });
222
- }
222
+ }
@@ -8,7 +8,7 @@ import type {
8
8
  ExtensionCommandContext,
9
9
  ExtensionContext,
10
10
  ToolDefinition,
11
- } from "@earendil-works/pi-coding-agent";
11
+ } from "@selesai/code";
12
12
  import { Text } from "@earendil-works/pi-tui";
13
13
  import { Type } from "typebox";
14
14
  import { access, mkdir, writeFile } from "node:fs/promises";
@@ -504,12 +504,20 @@ export function createWorkflowExtension(
504
504
  if (event.toolName === "subagent" && sm.snapshot.active && SUBAGENT_FALLBACK_PHASES.has(sm.snapshot.phase)) {
505
505
  const file = config.phaseArtifacts[sm.snapshot.phase];
506
506
  if (file) {
507
- const expectedPath = resolve(sm.snapshot.artifactDir, file);
508
- if (!(await realFileExists(expectedPath))) {
509
- const text = textFromToolResultContent(event.content);
510
- if (text) {
511
- await mkdir(sm.snapshot.artifactDir, { recursive: true });
512
- await writeFile(expectedPath, text, "utf8");
507
+ // ponytail: management actions (list/get/models/doctor/status/...)
508
+ // return text but are NOT the architect/recapper/... execution
509
+ // result. Writing their text to plan.md would advance the workflow
510
+ // on agent-listing output (the `subagent list` result is plain
511
+ // text). Execution calls set `agent`/`chain`/`tasks`; management
512
+ // calls set `action`. Only fall back for execution calls.
513
+ if (typeof event.input?.action !== "string") {
514
+ const expectedPath = resolve(sm.snapshot.artifactDir, file);
515
+ if (!(await realFileExists(expectedPath))) {
516
+ const text = textFromToolResultContent(event.content);
517
+ if (text) {
518
+ await mkdir(sm.snapshot.artifactDir, { recursive: true });
519
+ await writeFile(expectedPath, text, "utf8");
520
+ }
513
521
  }
514
522
  }
515
523
  }
@@ -585,4 +593,4 @@ export function createWorkflowExtension(
585
593
  },
586
594
  });
587
595
  };
588
- }
596
+ }
@@ -3,7 +3,7 @@
3
3
  // load conflict (multiple extension modules would each try to register the
4
4
  // shared writer).
5
5
 
6
- import type { ExtensionAPI } from "@earendil-works/pi-coding-agent";
6
+ import type { ExtensionAPI } from "@selesai/code";
7
7
  import { __resetWorkflowRegistryForTests, createWorkflowExtension } from "./adapter.ts";
8
8
  import { prototypeMode } from "./modes/prototype.ts";
9
9
  import { quickMode } from "./modes/quick.ts";
@@ -10,7 +10,7 @@
10
10
  ]
11
11
  },
12
12
  "peerDependencies": {
13
- "@earendil-works/pi-coding-agent": "*",
13
+ "@selesai/code": "*",
14
14
  "@earendil-works/pi-tui": "*",
15
15
  "typebox": "*"
16
16
  }
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAO/F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EAenC;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAyE7C;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static thinking label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"assistant-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/assistant-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAY,KAAK,aAAa,EAAgB,MAAM,wBAAwB,CAAC;AAQ/F;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,SAAS;IACvD,OAAO,CAAC,gBAAgB,CAAY;IACpC,OAAO,CAAC,iBAAiB,CAAU;IACnC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,WAAW,CAAC,CAAmB;IACvC,OAAO,CAAC,YAAY,CAAS;IAE7B,YACC,OAAO,CAAC,EAAE,gBAAgB,EAC1B,iBAAiB,UAAQ,EACzB,aAAa,GAAE,aAAkC,EACjD,mBAAmB,SAAgB,EAenC;IAEQ,UAAU,IAAI,IAAI,CAK1B;IAED,oBAAoB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAKxC;IAED,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAK1C;IAEQ,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CASvC;IAED,aAAa,CAAC,OAAO,EAAE,gBAAgB,GAAG,IAAI,CA0E7C;CACD","sourcesContent":["import type { AssistantMessage } from \"@earendil-works/pi-ai\";\nimport { Container, Markdown, type MarkdownTheme, Spacer, Text } from \"@earendil-works/pi-tui\";\nimport { normalizeAssistantThinkingTags } from \"../../../utils/thinking-tags.ts\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a complete assistant message\n */\nexport class AssistantMessageComponent extends Container {\n\tprivate contentContainer: Container;\n\tprivate hideThinkingBlock: boolean;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate hiddenThinkingLabel: string;\n\tprivate lastMessage?: AssistantMessage;\n\tprivate hasToolCalls = false;\n\n\tconstructor(\n\t\tmessage?: AssistantMessage,\n\t\thideThinkingBlock = false,\n\t\tmarkdownTheme: MarkdownTheme = getMarkdownTheme(),\n\t\thiddenThinkingLabel = \"Thinking...\",\n\t) {\n\t\tsuper();\n\n\t\tthis.hideThinkingBlock = hideThinkingBlock;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.hiddenThinkingLabel = hiddenThinkingLabel;\n\n\t\t// Container for text/thinking content\n\t\tthis.contentContainer = new Container();\n\t\tthis.addChild(this.contentContainer);\n\n\t\tif (message) {\n\t\t\tthis.updateContent(message);\n\t\t}\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHideThinkingBlock(hide: boolean): void {\n\t\tthis.hideThinkingBlock = hide;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\tsetHiddenThinkingLabel(label: string): void {\n\t\tthis.hiddenThinkingLabel = label;\n\t\tif (this.lastMessage) {\n\t\t\tthis.updateContent(this.lastMessage);\n\t\t}\n\t}\n\n\toverride render(width: number): string[] {\n\t\tconst lines = super.render(width);\n\t\tif (this.hasToolCalls || lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\t\treturn lines;\n\t}\n\n\tupdateContent(message: AssistantMessage): void {\n\t\tmessage = normalizeAssistantThinkingTags(message);\n\t\tthis.lastMessage = message;\n\n\t\t// Clear content container\n\t\tthis.contentContainer.clear();\n\n\t\tconst hasVisibleContent = message.content.some(\n\t\t\t(c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()),\n\t\t);\n\n\t\tif (hasVisibleContent) {\n\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t}\n\n\t\t// Render content in order\n\t\tfor (let i = 0; i < message.content.length; i++) {\n\t\t\tconst content = message.content[i];\n\t\t\tif (content.type === \"text\" && content.text.trim()) {\n\t\t\t\t// Assistant text messages with no background - trim the text\n\t\t\t\t// Set paddingY=0 to avoid extra spacing before tool executions\n\t\t\t\tthis.contentContainer.addChild(new Markdown(content.text.trim(), 1, 0, this.markdownTheme));\n\t\t\t} else if (content.type === \"thinking\" && content.thinking.trim()) {\n\t\t\t\t// Add spacing only when another visible assistant content block follows.\n\t\t\t\t// This avoids a superfluous blank line before separately-rendered tool execution blocks.\n\t\t\t\tconst hasVisibleContentAfter = message.content\n\t\t\t\t\t.slice(i + 1)\n\t\t\t\t\t.some((c) => (c.type === \"text\" && c.text.trim()) || (c.type === \"thinking\" && c.thinking.trim()));\n\n\t\t\t\tif (this.hideThinkingBlock) {\n\t\t\t\t\t// Show static thinking label when hidden\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Text(theme.italic(theme.fg(\"thinkingText\", this.hiddenThinkingLabel)), 1, 0),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t// Thinking traces in thinkingText color, italic\n\t\t\t\t\tthis.contentContainer.addChild(\n\t\t\t\t\t\tnew Markdown(content.thinking.trim(), 1, 0, this.markdownTheme, {\n\t\t\t\t\t\t\tcolor: (text: string) => theme.fg(\"thinkingText\", text),\n\t\t\t\t\t\t\titalic: true,\n\t\t\t\t\t\t}),\n\t\t\t\t\t);\n\t\t\t\t\tif (hasVisibleContentAfter) {\n\t\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Check if aborted - show after partial content\n\t\t// But only if there are no tool calls (tool execution components will show the error)\n\t\tconst hasToolCalls = message.content.some((c) => c.type === \"toolCall\");\n\t\tthis.hasToolCalls = hasToolCalls;\n\t\tif (!hasToolCalls) {\n\t\t\tif (message.stopReason === \"aborted\") {\n\t\t\t\tconst abortMessage =\n\t\t\t\t\tmessage.errorMessage && message.errorMessage !== \"Request was aborted\"\n\t\t\t\t\t\t? message.errorMessage\n\t\t\t\t\t\t: \"Operation aborted\";\n\t\t\t\tif (hasVisibleContent) {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t} else {\n\t\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\t}\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", abortMessage), 1, 0));\n\t\t\t} else if (message.stopReason === \"error\") {\n\t\t\t\tconst errorMsg = message.errorMessage || \"Unknown error\";\n\t\t\t\tthis.contentContainer.addChild(new Spacer(1));\n\t\t\t\tthis.contentContainer.addChild(new Text(theme.fg(\"error\", `Error: ${errorMsg}`), 1, 0));\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { Container, Markdown, Spacer, Text } from "@earendil-works/pi-tui";
2
+ import { normalizeAssistantThinkingTags } from "../../../utils/thinking-tags.js";
2
3
  import { getMarkdownTheme, theme } from "../theme/theme.js";
3
4
  const OSC133_ZONE_START = "\x1b]133;A\x07";
4
5
  const OSC133_ZONE_END = "\x1b]133;B\x07";
@@ -53,6 +54,7 @@ export class AssistantMessageComponent extends Container {
53
54
  return lines;
54
55
  }
55
56
  updateContent(message) {
57
+ message = normalizeAssistantThinkingTags(message);
56
58
  this.lastMessage = message;
57
59
  // Clear content container
58
60
  this.contentContainer.clear();