@oh-my-pi/pi-coding-agent 8.3.0 → 8.4.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.
- package/CHANGELOG.md +17 -0
- package/package.json +6 -6
- package/src/config/model-registry.ts +8 -0
- package/src/discovery/helpers.ts +12 -2
- package/src/extensibility/extensions/runner.ts +1 -0
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/ipy/executor.ts +4 -0
- package/src/modes/controllers/event-controller.ts +1 -0
- package/src/modes/controllers/extension-ui-controller.ts +2 -0
- package/src/modes/controllers/input-controller.ts +2 -2
- package/src/modes/interactive-mode.ts +30 -0
- package/src/modes/rpc/rpc-mode.ts +4 -0
- package/src/modes/theme/theme.ts +10 -107
- package/src/modes/types.ts +2 -0
- package/src/patch/applicator.ts +202 -38
- package/src/patch/fuzzy.ts +135 -25
- package/src/patch/index.ts +25 -2
- package/src/patch/parser.ts +5 -0
- package/src/patch/types.ts +25 -0
- package/src/sdk.ts +6 -0
- package/src/session/agent-session.ts +1 -0
- package/src/session/session-manager.ts +3 -0
- package/src/task/agents.ts +1 -1
- package/src/task/executor.ts +49 -17
- package/src/task/index.ts +16 -3
- package/src/task/types.ts +3 -3
- package/src/task/worker-protocol.ts +8 -0
- package/src/task/worker.ts +11 -0
- package/src/tools/index.ts +19 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [8.4.0] - 2026-01-25
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Added extension API to set working/loading messages during streaming
|
|
9
|
+
- Added task worker propagation of context files, skills, and prompt templates
|
|
10
|
+
- Added subagent option to skip Python preflight checks when Python tooling is unused
|
|
11
|
+
- Model field now accepts string arrays for fallback model prioritization
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Merged patch application warnings into edit tool diagnostics output
|
|
15
|
+
- Cached Python prelude docs for subagent workers to avoid repeated warmups
|
|
16
|
+
- Simplified image placeholders inserted on paste to match Claude-style markers
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- Rewrote empty or corrupted session files to restore valid headers
|
|
20
|
+
- Improved patch applicator ambiguity errors with match previews and overlap detection
|
|
21
|
+
- Fixed Task tool agent model resolution to honor comma-separated model lists
|
|
5
22
|
## [8.3.0] - 2026-01-25
|
|
6
23
|
|
|
7
24
|
### Changed
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-coding-agent",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.0",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"ompConfig": {
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"test": "bun test"
|
|
76
76
|
},
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@oh-my-pi/omp-stats": "8.
|
|
79
|
-
"@oh-my-pi/pi-agent-core": "8.
|
|
80
|
-
"@oh-my-pi/pi-ai": "8.
|
|
81
|
-
"@oh-my-pi/pi-tui": "8.
|
|
82
|
-
"@oh-my-pi/pi-utils": "8.
|
|
78
|
+
"@oh-my-pi/omp-stats": "8.4.0",
|
|
79
|
+
"@oh-my-pi/pi-agent-core": "8.4.0",
|
|
80
|
+
"@oh-my-pi/pi-ai": "8.4.0",
|
|
81
|
+
"@oh-my-pi/pi-tui": "8.4.0",
|
|
82
|
+
"@oh-my-pi/pi-utils": "8.4.0",
|
|
83
83
|
"@openai/agents": "^0.4.3",
|
|
84
84
|
"@sinclair/typebox": "^0.34.46",
|
|
85
85
|
"ajv": "^8.17.1",
|
|
@@ -19,12 +19,18 @@ import type { AuthStorage } from "../session/auth-storage";
|
|
|
19
19
|
|
|
20
20
|
const Ajv = (AjvModule as any).default || AjvModule;
|
|
21
21
|
|
|
22
|
+
const OpenRouterRoutingSchema = Type.Object({
|
|
23
|
+
only: Type.Optional(Type.Array(Type.String())),
|
|
24
|
+
order: Type.Optional(Type.Array(Type.String())),
|
|
25
|
+
});
|
|
26
|
+
|
|
22
27
|
// Schema for OpenAI compatibility settings
|
|
23
28
|
const OpenAICompatSchema = Type.Object({
|
|
24
29
|
supportsStore: Type.Optional(Type.Boolean()),
|
|
25
30
|
supportsDeveloperRole: Type.Optional(Type.Boolean()),
|
|
26
31
|
supportsReasoningEffort: Type.Optional(Type.Boolean()),
|
|
27
32
|
maxTokensField: Type.Optional(Type.Union([Type.Literal("max_completion_tokens"), Type.Literal("max_tokens")])),
|
|
33
|
+
openRouterRouting: Type.Optional(OpenRouterRoutingSchema),
|
|
28
34
|
});
|
|
29
35
|
|
|
30
36
|
// Schema for custom model definition
|
|
@@ -36,6 +42,7 @@ const ModelDefinitionSchema = Type.Object({
|
|
|
36
42
|
Type.Literal("openai-completions"),
|
|
37
43
|
Type.Literal("openai-responses"),
|
|
38
44
|
Type.Literal("openai-codex-responses"),
|
|
45
|
+
Type.Literal("azure-openai-responses"),
|
|
39
46
|
Type.Literal("anthropic-messages"),
|
|
40
47
|
Type.Literal("google-generative-ai"),
|
|
41
48
|
Type.Literal("google-vertex"),
|
|
@@ -63,6 +70,7 @@ const ProviderConfigSchema = Type.Object({
|
|
|
63
70
|
Type.Literal("openai-completions"),
|
|
64
71
|
Type.Literal("openai-responses"),
|
|
65
72
|
Type.Literal("openai-codex-responses"),
|
|
73
|
+
Type.Literal("azure-openai-responses"),
|
|
66
74
|
Type.Literal("anthropic-messages"),
|
|
67
75
|
Type.Literal("google-generative-ai"),
|
|
68
76
|
Type.Literal("google-vertex"),
|
package/src/discovery/helpers.ts
CHANGED
|
@@ -156,13 +156,23 @@ export function parseArrayOrCSV(value: unknown): string[] | undefined {
|
|
|
156
156
|
return undefined;
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
+
/**
|
|
160
|
+
* Parse model field into a prioritized list.
|
|
161
|
+
*/
|
|
162
|
+
export function parseModelList(value: unknown): string[] | undefined {
|
|
163
|
+
const parsed = parseArrayOrCSV(value);
|
|
164
|
+
if (!parsed) return undefined;
|
|
165
|
+
const normalized = parsed.map(entry => entry.trim()).filter(Boolean);
|
|
166
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
167
|
+
}
|
|
168
|
+
|
|
159
169
|
/** Parsed agent fields from frontmatter (excludes source/filePath/systemPrompt) */
|
|
160
170
|
export interface ParsedAgentFields {
|
|
161
171
|
name: string;
|
|
162
172
|
description: string;
|
|
163
173
|
tools?: string[];
|
|
164
174
|
spawns?: string[] | "*";
|
|
165
|
-
model?: string;
|
|
175
|
+
model?: string[];
|
|
166
176
|
output?: unknown;
|
|
167
177
|
thinkingLevel?: ThinkingLevel;
|
|
168
178
|
}
|
|
@@ -202,7 +212,7 @@ export function parseAgentFields(frontmatter: Record<string, unknown>): ParsedAg
|
|
|
202
212
|
}
|
|
203
213
|
|
|
204
214
|
const output = frontmatter.output !== undefined ? frontmatter.output : undefined;
|
|
205
|
-
const model =
|
|
215
|
+
const model = parseModelList(frontmatter.model);
|
|
206
216
|
const thinkingLevel = parseThinkingLevel(frontmatter);
|
|
207
217
|
|
|
208
218
|
return { name, description, tools, spawns, model, output, thinkingLevel };
|
|
@@ -69,6 +69,9 @@ export interface ExtensionUIContext {
|
|
|
69
69
|
/** Set status text in the footer/status bar. Pass undefined to clear. */
|
|
70
70
|
setStatus(key: string, text: string | undefined): void;
|
|
71
71
|
|
|
72
|
+
/** Set the working/loading message shown during streaming. Call with no argument to restore default. */
|
|
73
|
+
setWorkingMessage(message?: string): void;
|
|
74
|
+
|
|
72
75
|
/** Set a widget to display above the editor. Accepts string array or component factory. */
|
|
73
76
|
setWidget(key: string, content: string[] | undefined): void;
|
|
74
77
|
setWidget(key: string, content: ((tui: TUI, theme: Theme) => Component & { dispose?(): void }) | undefined): void;
|
package/src/ipy/executor.ts
CHANGED
|
@@ -187,6 +187,10 @@ export function getPreludeDocs(): PreludeHelper[] {
|
|
|
187
187
|
return cachedPreludeDocs ?? [];
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
export function setPreludeDocsCache(docs: PreludeHelper[]): void {
|
|
191
|
+
cachedPreludeDocs = docs;
|
|
192
|
+
}
|
|
193
|
+
|
|
190
194
|
export function resetPreludeDocsCache(): void {
|
|
191
195
|
cachedPreludeDocs = null;
|
|
192
196
|
}
|
|
@@ -30,6 +30,7 @@ export class ExtensionUiController {
|
|
|
30
30
|
input: (title, placeholder, _dialogOptions) => this.showHookInput(title, placeholder),
|
|
31
31
|
notify: (message, type) => this.showHookNotify(message, type),
|
|
32
32
|
setStatus: (key, text) => this.setHookStatus(key, text),
|
|
33
|
+
setWorkingMessage: message => this.ctx.setWorkingMessage(message),
|
|
33
34
|
setWidget: (key, content) => this.setHookWidget(key, content),
|
|
34
35
|
setTitle: title => setTerminalTitle(title),
|
|
35
36
|
custom: (factory, _options) => this.showHookCustom(factory),
|
|
@@ -389,6 +390,7 @@ export class ExtensionUiController {
|
|
|
389
390
|
input: async (_title: string, _placeholder?: string, _dialogOptions?: unknown) => undefined,
|
|
390
391
|
notify: () => {},
|
|
391
392
|
setStatus: () => {},
|
|
393
|
+
setWorkingMessage: () => {},
|
|
392
394
|
setWidget: () => {},
|
|
393
395
|
setTitle: () => {},
|
|
394
396
|
custom: async () => undefined as never,
|
|
@@ -541,9 +541,9 @@ export class InputController {
|
|
|
541
541
|
data: imageData.data,
|
|
542
542
|
mimeType: imageData.mimeType,
|
|
543
543
|
});
|
|
544
|
-
// Insert
|
|
544
|
+
// Insert placeholder at cursor like Claude does
|
|
545
545
|
const imageNum = this.ctx.pendingImages.length;
|
|
546
|
-
const placeholder =
|
|
546
|
+
const placeholder = `[Image #${imageNum}]`;
|
|
547
547
|
this.ctx.editor.insertText(`${placeholder} `);
|
|
548
548
|
this.ctx.ui.requestRender();
|
|
549
549
|
return true;
|
|
@@ -102,6 +102,8 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
102
102
|
public loadingAnimation: Loader | undefined = undefined;
|
|
103
103
|
public autoCompactionLoader: Loader | undefined = undefined;
|
|
104
104
|
public retryLoader: Loader | undefined = undefined;
|
|
105
|
+
private pendingWorkingMessage: string | undefined;
|
|
106
|
+
private readonly defaultWorkingMessage = `Working${theme.format.ellipsis} (esc to interrupt)`;
|
|
105
107
|
public autoCompactionEscapeHandler?: () => void;
|
|
106
108
|
public retryEscapeHandler?: () => void;
|
|
107
109
|
public unsubscribe?: () => void;
|
|
@@ -160,6 +162,7 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
160
162
|
this.statusContainer = new Container();
|
|
161
163
|
this.todoContainer = new Container();
|
|
162
164
|
this.editor = new CustomEditor(getEditorTheme());
|
|
165
|
+
this.editor.setUseTerminalCursor(this.ui.getShowHardwareCursor());
|
|
163
166
|
this.editor.onAutocompleteCancel = () => {
|
|
164
167
|
this.ui.requestRender(true);
|
|
165
168
|
};
|
|
@@ -538,6 +541,33 @@ export class InteractiveMode implements InteractiveModeContext {
|
|
|
538
541
|
this.uiHelpers.showWarning(message);
|
|
539
542
|
}
|
|
540
543
|
|
|
544
|
+
setWorkingMessage(message?: string): void {
|
|
545
|
+
if (message === undefined) {
|
|
546
|
+
this.pendingWorkingMessage = undefined;
|
|
547
|
+
if (this.loadingAnimation) {
|
|
548
|
+
this.loadingAnimation.setMessage(this.defaultWorkingMessage);
|
|
549
|
+
}
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
if (this.loadingAnimation) {
|
|
554
|
+
this.loadingAnimation.setMessage(message);
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
this.pendingWorkingMessage = message;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
applyPendingWorkingMessage(): void {
|
|
562
|
+
if (this.pendingWorkingMessage === undefined) {
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const message = this.pendingWorkingMessage;
|
|
567
|
+
this.pendingWorkingMessage = undefined;
|
|
568
|
+
this.setWorkingMessage(message);
|
|
569
|
+
}
|
|
570
|
+
|
|
541
571
|
showNewVersionNotification(newVersion: string): void {
|
|
542
572
|
this.uiHelpers.showNewVersionNotification(newVersion);
|
|
543
573
|
}
|
|
@@ -187,6 +187,10 @@ export async function runRpcMode(session: AgentSession): Promise<never> {
|
|
|
187
187
|
} as RpcExtensionUIRequest);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
|
+
setWorkingMessage(_message?: string): void {
|
|
191
|
+
// Not supported in RPC mode
|
|
192
|
+
}
|
|
193
|
+
|
|
190
194
|
setWidget(key: string, content: unknown): void {
|
|
191
195
|
// Only support string arrays in RPC mode - factory functions are ignored
|
|
192
196
|
if (content === undefined || Array.isArray(content)) {
|
package/src/modes/theme/theme.ts
CHANGED
|
@@ -1025,109 +1025,20 @@ function detectColorMode(): ColorMode {
|
|
|
1025
1025
|
return "truecolor";
|
|
1026
1026
|
}
|
|
1027
1027
|
|
|
1028
|
-
function
|
|
1029
|
-
const
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
const r = parseInt(cleaned.substring(0, 2), 16);
|
|
1034
|
-
const g = parseInt(cleaned.substring(2, 4), 16);
|
|
1035
|
-
const b = parseInt(cleaned.substring(4, 6), 16);
|
|
1036
|
-
if (Number.isNaN(r) || Number.isNaN(g) || Number.isNaN(b)) {
|
|
1037
|
-
throw new Error(`Invalid hex color: ${hex}`);
|
|
1038
|
-
}
|
|
1039
|
-
return { r, g, b };
|
|
1040
|
-
}
|
|
1041
|
-
|
|
1042
|
-
// The 6x6x6 color cube channel values (indices 0-5)
|
|
1043
|
-
const CUBE_VALUES = [0, 95, 135, 175, 215, 255];
|
|
1044
|
-
|
|
1045
|
-
// Grayscale ramp values (indices 232-255, 24 grays from 8 to 238)
|
|
1046
|
-
const GRAY_VALUES = Array.from({ length: 24 }, (_, i) => 8 + i * 10);
|
|
1047
|
-
|
|
1048
|
-
function findClosestCubeIndex(value: number): number {
|
|
1049
|
-
let minDist = Infinity;
|
|
1050
|
-
let minIdx = 0;
|
|
1051
|
-
for (let i = 0; i < CUBE_VALUES.length; i++) {
|
|
1052
|
-
const dist = Math.abs(value - CUBE_VALUES[i]);
|
|
1053
|
-
if (dist < minDist) {
|
|
1054
|
-
minDist = dist;
|
|
1055
|
-
minIdx = i;
|
|
1056
|
-
}
|
|
1028
|
+
function colorToAnsi(color: string, mode: ColorMode): string {
|
|
1029
|
+
const format = mode === "truecolor" ? "ansi-16m" : "ansi-256";
|
|
1030
|
+
const ansi = Bun.color(color, format);
|
|
1031
|
+
if (ansi === null) {
|
|
1032
|
+
throw new Error(`Invalid color value: ${color}`);
|
|
1057
1033
|
}
|
|
1058
|
-
return
|
|
1059
|
-
}
|
|
1060
|
-
|
|
1061
|
-
function findClosestGrayIndex(gray: number): number {
|
|
1062
|
-
let minDist = Infinity;
|
|
1063
|
-
let minIdx = 0;
|
|
1064
|
-
for (let i = 0; i < GRAY_VALUES.length; i++) {
|
|
1065
|
-
const dist = Math.abs(gray - GRAY_VALUES[i]);
|
|
1066
|
-
if (dist < minDist) {
|
|
1067
|
-
minDist = dist;
|
|
1068
|
-
minIdx = i;
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
return minIdx;
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
function colorDistance(r1: number, g1: number, b1: number, r2: number, g2: number, b2: number): number {
|
|
1075
|
-
// Weighted Euclidean distance (human eye is more sensitive to green)
|
|
1076
|
-
const dr = r1 - r2;
|
|
1077
|
-
const dg = g1 - g2;
|
|
1078
|
-
const db = b1 - b2;
|
|
1079
|
-
return dr * dr * 0.299 + dg * dg * 0.587 + db * db * 0.114;
|
|
1080
|
-
}
|
|
1081
|
-
|
|
1082
|
-
function rgbTo256(r: number, g: number, b: number): number {
|
|
1083
|
-
// Find closest color in the 6x6x6 cube
|
|
1084
|
-
const rIdx = findClosestCubeIndex(r);
|
|
1085
|
-
const gIdx = findClosestCubeIndex(g);
|
|
1086
|
-
const bIdx = findClosestCubeIndex(b);
|
|
1087
|
-
const cubeR = CUBE_VALUES[rIdx];
|
|
1088
|
-
const cubeG = CUBE_VALUES[gIdx];
|
|
1089
|
-
const cubeB = CUBE_VALUES[bIdx];
|
|
1090
|
-
const cubeIndex = 16 + 36 * rIdx + 6 * gIdx + bIdx;
|
|
1091
|
-
const cubeDist = colorDistance(r, g, b, cubeR, cubeG, cubeB);
|
|
1092
|
-
|
|
1093
|
-
// Find closest grayscale
|
|
1094
|
-
const gray = Math.round(0.299 * r + 0.587 * g + 0.114 * b);
|
|
1095
|
-
const grayIdx = findClosestGrayIndex(gray);
|
|
1096
|
-
const grayValue = GRAY_VALUES[grayIdx];
|
|
1097
|
-
const grayIndex = 232 + grayIdx;
|
|
1098
|
-
const grayDist = colorDistance(r, g, b, grayValue, grayValue, grayValue);
|
|
1099
|
-
|
|
1100
|
-
// Check if color has noticeable saturation (hue matters)
|
|
1101
|
-
// If max-min spread is significant, prefer cube to preserve tint
|
|
1102
|
-
const maxC = Math.max(r, g, b);
|
|
1103
|
-
const minC = Math.min(r, g, b);
|
|
1104
|
-
const spread = maxC - minC;
|
|
1105
|
-
|
|
1106
|
-
// Only consider grayscale if color is nearly neutral (spread < 10)
|
|
1107
|
-
// AND grayscale is actually closer
|
|
1108
|
-
if (spread < 10 && grayDist < cubeDist) {
|
|
1109
|
-
return grayIndex;
|
|
1110
|
-
}
|
|
1111
|
-
|
|
1112
|
-
return cubeIndex;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
function hexTo256(hex: string): number {
|
|
1116
|
-
const { r, g, b } = hexToRgb(hex);
|
|
1117
|
-
return rgbTo256(r, g, b);
|
|
1034
|
+
return ansi;
|
|
1118
1035
|
}
|
|
1119
1036
|
|
|
1120
1037
|
function fgAnsi(color: string | number, mode: ColorMode): string {
|
|
1121
1038
|
if (color === "") return "\x1b[39m";
|
|
1122
1039
|
if (typeof color === "number") return `\x1b[38;5;${color}m`;
|
|
1123
|
-
if (color
|
|
1124
|
-
|
|
1125
|
-
const { r, g, b } = hexToRgb(color);
|
|
1126
|
-
return `\x1b[38;2;${r};${g};${b}m`;
|
|
1127
|
-
} else {
|
|
1128
|
-
const index = hexTo256(color);
|
|
1129
|
-
return `\x1b[38;5;${index}m`;
|
|
1130
|
-
}
|
|
1040
|
+
if (typeof color === "string") {
|
|
1041
|
+
return colorToAnsi(color, mode);
|
|
1131
1042
|
}
|
|
1132
1043
|
throw new Error(`Invalid color value: ${color}`);
|
|
1133
1044
|
}
|
|
@@ -1135,16 +1046,8 @@ function fgAnsi(color: string | number, mode: ColorMode): string {
|
|
|
1135
1046
|
function bgAnsi(color: string | number, mode: ColorMode): string {
|
|
1136
1047
|
if (color === "") return "\x1b[49m";
|
|
1137
1048
|
if (typeof color === "number") return `\x1b[48;5;${color}m`;
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
const { r, g, b } = hexToRgb(color);
|
|
1141
|
-
return `\x1b[48;2;${r};${g};${b}m`;
|
|
1142
|
-
} else {
|
|
1143
|
-
const index = hexTo256(color);
|
|
1144
|
-
return `\x1b[48;5;${index}m`;
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
throw new Error(`Invalid color value: ${color}`);
|
|
1049
|
+
const ansi = colorToAnsi(color, mode);
|
|
1050
|
+
return ansi.replace("\x1b[38;", "\x1b[48;");
|
|
1148
1051
|
}
|
|
1149
1052
|
|
|
1150
1053
|
function resolveVarRefs(
|
package/src/modes/types.ts
CHANGED
|
@@ -111,6 +111,8 @@ export interface InteractiveModeContext {
|
|
|
111
111
|
queueCompactionMessage(text: string, mode: "steer" | "followUp"): void;
|
|
112
112
|
flushCompactionQueue(options?: { willRetry?: boolean }): Promise<void>;
|
|
113
113
|
flushPendingBashComponents(): void;
|
|
114
|
+
setWorkingMessage(message?: string): void;
|
|
115
|
+
applyPendingWorkingMessage(): void;
|
|
114
116
|
isKnownSlashCommand(text: string): boolean;
|
|
115
117
|
addMessageToChat(message: AgentMessage, options?: { populateHistory?: boolean }): void;
|
|
116
118
|
renderSessionContext(
|