praxis-agent 0.14.0 → 0.16.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 (33) hide show
  1. package/README.md +5 -2
  2. package/dist/application/session-service.d.ts +18 -0
  3. package/dist/application/session-service.js +180 -41
  4. package/dist/application/subagent-service.d.ts +7 -1
  5. package/dist/application/subagent-service.js +238 -53
  6. package/dist/cli/interactive.d.ts +7 -1
  7. package/dist/cli/interactive.js +77 -3
  8. package/dist/cli/protocol.d.ts +13 -0
  9. package/dist/cli/protocol.js +34 -0
  10. package/dist/cli/tui/claude-command-inventory.d.ts +1 -2
  11. package/dist/cli/tui/claude-command-inventory.js +1 -6
  12. package/dist/cli/tui/claude-style.d.ts +4 -1
  13. package/dist/cli/tui/claude-style.js +8 -3
  14. package/dist/cli/tui/slash-commands.d.ts +1 -0
  15. package/dist/cli/tui/slash-commands.js +11 -0
  16. package/dist/cli/tui/theme.d.ts +2 -0
  17. package/dist/cli/tui/theme.js +69 -0
  18. package/dist/cli.d.ts +6 -0
  19. package/dist/cli.js +95 -27
  20. package/dist/compatibility/claude/agent-color.d.ts +25 -0
  21. package/dist/compatibility/claude/agent-color.js +79 -0
  22. package/dist/compatibility/claude/fork.js +5 -1
  23. package/dist/compatibility/claude/schema.js +13 -1
  24. package/dist/extensions/claude-extensions.d.ts +19 -1
  25. package/dist/extensions/claude-extensions.js +126 -1
  26. package/dist/hooks/claude-hooks.d.ts +3 -1
  27. package/dist/hooks/claude-hooks.js +14 -0
  28. package/dist/mcp/claude-mcp-tools.d.ts +18 -0
  29. package/dist/mcp/claude-mcp-tools.js +46 -0
  30. package/dist/persistence/claude-transcript-store.js +1 -0
  31. package/dist/tools/claude-interactive-tools.d.ts +1 -0
  32. package/dist/tools/claude-interactive-tools.js +3 -0
  33. package/package.json +2 -1
@@ -1,5 +1,5 @@
1
1
  import { randomBytes, randomUUID } from 'node:crypto';
2
- import { readdir, stat } from 'node:fs/promises';
2
+ import { mkdir, readFile, readdir, stat } from 'node:fs/promises';
3
3
  import { join } from 'node:path';
4
4
  import { Ajv2020 } from 'ajv/dist/2020.js';
5
5
  import { resolveClaudePaths } from '../compatibility/claude/paths.js';
@@ -103,6 +103,155 @@ class RestrictedToolRegistry {
103
103
  return this.base.execute(call, context);
104
104
  }
105
105
  }
106
+ const AGENT_UNAVAILABLE_TOOLS = new Set([
107
+ 'Agent',
108
+ 'Task',
109
+ 'TaskOutput',
110
+ 'TaskStop',
111
+ 'ExitPlanMode',
112
+ 'EnterPlanMode',
113
+ 'AskUserQuestion',
114
+ 'Workflow',
115
+ ]);
116
+ const BACKGROUND_AGENT_TOOLS = new Set([
117
+ 'Read',
118
+ 'WebSearch',
119
+ 'TodoWrite',
120
+ 'Grep',
121
+ 'WebFetch',
122
+ 'Glob',
123
+ 'Bash',
124
+ 'Edit',
125
+ 'Write',
126
+ 'NotebookEdit',
127
+ 'Skill',
128
+ 'StructuredOutput',
129
+ 'ToolSearch',
130
+ 'EnterWorktree',
131
+ 'ExitWorktree',
132
+ ]);
133
+ function agentToolRuleName(rule) {
134
+ const opening = rule.indexOf('(');
135
+ return (opening < 0 ? rule : rule.slice(0, opening)).trim();
136
+ }
137
+ function enabledAgentToolNames(base, definition, background, additiveTools = new Set()) {
138
+ const requested = definition?.tools
139
+ ? new Set(definition.tools.map(agentToolRuleName))
140
+ : null;
141
+ if (requested && definition?.memory) {
142
+ requested.add('Read');
143
+ requested.add('Edit');
144
+ requested.add('Write');
145
+ }
146
+ const disallowed = new Set(definition?.disallowedTools?.map(agentToolRuleName) ?? []);
147
+ return base
148
+ .definitions()
149
+ .map(({ name }) => name)
150
+ .filter((name) => {
151
+ if (additiveTools.has(name))
152
+ return true;
153
+ if (AGENT_UNAVAILABLE_TOOLS.has(name))
154
+ return false;
155
+ if (background &&
156
+ !name.startsWith('mcp__') &&
157
+ !BACKGROUND_AGENT_TOOLS.has(name)) {
158
+ return false;
159
+ }
160
+ if (requested && !requested.has(name))
161
+ return false;
162
+ return !disallowed.has(name);
163
+ });
164
+ }
165
+ function agentMemoryDirectory(configRoot, cwd, agentType, scope) {
166
+ const directoryName = agentType.replaceAll(':', '-');
167
+ if (scope === 'user') {
168
+ return join(configRoot, 'agent-memory', directoryName);
169
+ }
170
+ return join(cwd, '.claude', scope === 'project' ? 'agent-memory' : 'agent-memory-local', directoryName);
171
+ }
172
+ export async function agentMemoryPrompt(configRoot, cwd, definition) {
173
+ if (!definition?.memory)
174
+ return null;
175
+ const directory = agentMemoryDirectory(configRoot, cwd, definition.name, definition.memory);
176
+ await mkdir(directory, { recursive: true }).catch(() => undefined);
177
+ let source = '';
178
+ try {
179
+ source = await readFile(join(directory, 'MEMORY.md'), 'utf8');
180
+ }
181
+ catch {
182
+ source = '';
183
+ }
184
+ const lines = source.trim().split('\n');
185
+ const truncated = lines.slice(0, 200).join('\n').slice(0, 25_000);
186
+ const scopeGuidance = definition.memory === 'user'
187
+ ? 'Keep entries general enough to apply across projects.'
188
+ : definition.memory === 'project'
189
+ ? 'Keep entries specific to this project and suitable for version control.'
190
+ : 'Keep entries specific to this project and machine; this scope is not version controlled.';
191
+ return [
192
+ '# Persistent Agent Memory',
193
+ '',
194
+ `Use the file-based memory directory at \`${directory}\`. The directory already exists.`,
195
+ 'Keep MEMORY.md as a concise index and store detailed durable knowledge in linked Markdown files. Update existing entries instead of duplicating them, and do not save transient task state.',
196
+ scopeGuidance,
197
+ '',
198
+ '## MEMORY.md',
199
+ '',
200
+ truncated || 'The memory index is currently empty.',
201
+ ].join('\n');
202
+ }
203
+ function agentSkillMessages(catalog, definition) {
204
+ if (!catalog || !definition?.skills?.length)
205
+ return [];
206
+ const available = catalog.modelInvocableSkills();
207
+ const prefix = definition.name.split(':')[0];
208
+ return definition.skills.flatMap((requested) => {
209
+ const skill = available.find(({ name }) => name === requested) ??
210
+ available.find(({ name }) => name === `${prefix}:${requested}`) ??
211
+ available.find(({ name }) => name.endsWith(`:${requested}`));
212
+ if (!skill)
213
+ return [];
214
+ const content = catalog.renderSkill(skill.name, '');
215
+ if (content === null)
216
+ return [];
217
+ return [
218
+ {
219
+ role: 'user',
220
+ content: [
221
+ `<command-message>${skill.name}</command-message>`,
222
+ `<command-name>${skill.name}</command-name>`,
223
+ '<skill-format>true</skill-format>',
224
+ '',
225
+ content,
226
+ ].join('\n'),
227
+ },
228
+ ];
229
+ });
230
+ }
231
+ function agentHookSettings(definition) {
232
+ if (!definition?.hooks)
233
+ return [];
234
+ const { Stop, SubagentStop, ...hooks } = definition.hooks;
235
+ const stopHooks = Stop === undefined
236
+ ? SubagentStop
237
+ : SubagentStop === undefined
238
+ ? Stop
239
+ : Array.isArray(Stop) && Array.isArray(SubagentStop)
240
+ ? [...SubagentStop, ...Stop]
241
+ : Stop;
242
+ return [
243
+ {
244
+ path: definition.path,
245
+ scope: definition.scope,
246
+ value: {
247
+ hooks: {
248
+ ...hooks,
249
+ ...(stopHooks === undefined ? {} : { SubagentStop: stopHooks }),
250
+ },
251
+ },
252
+ },
253
+ ];
254
+ }
106
255
  function parseAgentInput(call) {
107
256
  const allowed = new Set([
108
257
  'description',
@@ -180,7 +329,7 @@ function parseAgentInput(call) {
180
329
  ? {}
181
330
  : { permissionMode: permissionMode }),
182
331
  ...(isolation === undefined ? {} : { isolation }),
183
- runInBackground: call.input.run_in_background !== false,
332
+ runInBackground: call.input.run_in_background === true,
184
333
  };
185
334
  }
186
335
  export class ClaudeSubagentExecutor {
@@ -209,6 +358,35 @@ export class ClaudeSubagentExecutor {
209
358
  cwd() {
210
359
  return this.options.cwdProvider?.() ?? this.options.cwd;
211
360
  }
361
+ agentDefinition(input) {
362
+ return this.options.extensions?.agent(input.subagentType) ?? null;
363
+ }
364
+ resolveAgentInput(input) {
365
+ const definition = this.agentDefinition(input);
366
+ const environmentModel = process.env.CLAUDE_CODE_SUBAGENT_MODEL?.trim();
367
+ const configuredModel = definition?.model && definition.model !== 'inherit'
368
+ ? definition.model
369
+ : undefined;
370
+ const model = environmentModel || input.model || configuredModel;
371
+ const parentPermissionMode = this.options.parentPermissionMode?.();
372
+ const definitionCanOverridePermissionMode = ![
373
+ 'acceptEdits',
374
+ 'auto',
375
+ 'bypassPermissions',
376
+ ].includes(parentPermissionMode ?? 'default');
377
+ const permissionMode = input.permissionMode ??
378
+ (definitionCanOverridePermissionMode
379
+ ? definition?.permissionMode
380
+ : parentPermissionMode);
381
+ const isolation = input.isolation ?? definition?.isolation;
382
+ return {
383
+ ...input,
384
+ ...(model ? { model } : {}),
385
+ ...(permissionMode ? { permissionMode } : {}),
386
+ ...(isolation ? { isolation } : {}),
387
+ runInBackground: input.runInBackground || definition?.background === true,
388
+ };
389
+ }
212
390
  registry(sessionId, depth, promptIdForCall) {
213
391
  return new ClaudeSubagentToolRegistry(this.options.baseTools, this, sessionId, depth, promptIdForCall);
214
392
  }
@@ -328,7 +506,7 @@ export class ClaudeSubagentExecutor {
328
506
  prepare(call, depth) {
329
507
  if (!this.isEnabled('Agent'))
330
508
  throw new Error('Tool Agent is unavailable');
331
- const input = parseAgentInput(call);
509
+ const input = this.resolveAgentInput(parseAgentInput(call));
332
510
  if (input.runInBackground && this.options.persistence === 'memory') {
333
511
  throw new Error('Background agents require session persistence');
334
512
  }
@@ -367,7 +545,7 @@ export class ClaudeSubagentExecutor {
367
545
  if (this.calls > maxCalls) {
368
546
  throw new Error(`Agent call count exceeded ${maxCalls}`);
369
547
  }
370
- const input = parseAgentInput(call);
548
+ const input = this.resolveAgentInput(parseAgentInput(call));
371
549
  const spawnDepth = depth + 1;
372
550
  const agentId = `a${randomBytes(8).toString('hex')}`;
373
551
  const paths = resolveClaudePaths({
@@ -959,33 +1137,52 @@ export class ClaudeSubagentExecutor {
959
1137
  await append(toClaudeSidechainEntry(entry, options.agentId, options.input.subagentType));
960
1138
  }
961
1139
  };
1140
+ const customAgent = this.agentDefinition(options.input);
962
1141
  const hookSession = {
963
1142
  session_id: String(options.root.sessionId),
964
1143
  transcript_path: options.transcriptPath,
965
1144
  cwd,
966
1145
  permission_mode: options.input.permissionMode ?? 'default',
967
1146
  };
1147
+ const scopedHookSettings = agentHookSettings(customAgent);
1148
+ const scopedHooks = scopedHookSettings.length > 0
1149
+ ? this.options.hooks?.withAdditionalSettings(scopedHookSettings)
1150
+ : this.options.hooks;
968
1151
  const nestedTools = this.registry(String(options.root.sessionId), options.spawnDepth, () => options.promptId);
969
- const builtInStatusLineAgent = this.options.extensions?.agent(options.input.subagentType)?.path ===
970
- BUILTIN_STATUSLINE_AGENT_PATH;
1152
+ const agentMcp = customAgent?.mcpServers?.length
1153
+ ? await this.options.mcp?.connectAgent?.({
1154
+ specs: customAgent.mcpServers,
1155
+ base: nestedTools,
1156
+ cwd,
1157
+ ...(options.signal ? { signal: options.signal } : {}),
1158
+ })
1159
+ : null;
1160
+ const agentToolBase = agentMcp?.tools ?? nestedTools;
1161
+ const inheritedToolNames = new Set(nestedTools.definitions().map(({ name }) => name));
1162
+ const additiveAgentToolNames = new Set(agentToolBase
1163
+ .definitions()
1164
+ .map(({ name }) => name)
1165
+ .filter((name) => !inheritedToolNames.has(name)));
1166
+ const agentScopedTools = new RestrictedToolRegistry(agentToolBase, enabledAgentToolNames(agentToolBase, customAgent, options.input.runInBackground, additiveAgentToolNames));
1167
+ const builtInStatusLineAgent = customAgent?.path === BUILTIN_STATUSLINE_AGENT_PATH;
971
1168
  const scopedTools = builtInStatusLineAgent
972
- ? new RestrictedToolRegistry(nestedTools, ['Read', 'Edit'])
973
- : nestedTools;
1169
+ ? new RestrictedToolRegistry(agentScopedTools, ['Read', 'Edit'])
1170
+ : agentScopedTools;
974
1171
  const agentTools = options.outputSchema
975
1172
  ? new StructuredOutputRegistry(builtInStatusLineAgent
976
1173
  ? new RestrictedToolRegistry(structuredOnlyTools, ['Read', 'Edit'])
977
1174
  : structuredOnlyTools, options.outputSchema, options.structuredOutput)
978
1175
  : scopedTools;
979
- const runtimeTools = this.options.hooks
1176
+ const runtimeTools = scopedHooks
980
1177
  ? new ClaudeHookToolCoordinator({
981
1178
  tools: agentTools,
982
1179
  permissions,
983
- hooks: this.options.hooks,
1180
+ hooks: scopedHooks,
984
1181
  session: hookSession,
985
1182
  recordOutcome: recordHookOutcome,
986
1183
  })
987
1184
  : agentTools;
988
- const runtimePermissions = this.options.hooks
1185
+ const runtimePermissions = scopedHooks
989
1186
  ? runtimeTools
990
1187
  : permissions;
991
1188
  const emit = (event) => {
@@ -1032,7 +1229,7 @@ export class ClaudeSubagentExecutor {
1032
1229
  const runtime = new AgentRuntime(options.provider, emit, {
1033
1230
  tools: runtimeTools,
1034
1231
  permissions: runtimePermissions,
1035
- maxModelTurns: 16,
1232
+ maxModelTurns: customAgent?.maxTurns ?? 16,
1036
1233
  maxModelOutputBytes: this.options.maxOutputBytes ?? DEFAULT_MAX_OUTPUT_BYTES,
1037
1234
  maxToolCallsPerTurn: 32,
1038
1235
  maxToolInputBytes: 1024 * 1024,
@@ -1104,36 +1301,31 @@ export class ClaudeSubagentExecutor {
1104
1301
  prompt: options.input.prompt,
1105
1302
  });
1106
1303
  try {
1107
- if (this.options.hooks) {
1108
- const start = await this.options.hooks.run({
1304
+ if (scopedHooks) {
1305
+ const start = await scopedHooks.run({
1109
1306
  ...hookSession,
1110
- hook_event_name: 'SessionStart',
1111
- source: 'startup',
1112
- }, 'startup', options.signal);
1307
+ hook_event_name: 'SubagentStart',
1308
+ agent_id: options.agentId,
1309
+ agent_type: options.input.subagentType,
1310
+ }, options.input.subagentType, options.signal);
1113
1311
  await recordHookOutcome(start);
1114
1312
  if (start.blockedReason) {
1115
- throw new Error(`SessionStart hook error: ${start.blockedReason}`);
1116
- }
1117
- const prompt = await this.options.hooks.run({
1118
- ...hookSession,
1119
- hook_event_name: 'UserPromptSubmit',
1120
- prompt_id: options.promptId,
1121
- prompt: options.input.prompt,
1122
- }, undefined, options.signal);
1123
- await recordHookOutcome(prompt);
1124
- if (prompt.blockedReason) {
1125
- throw new Error(`UserPromptSubmit hook error: ${prompt.blockedReason}`);
1313
+ throw new Error(`SubagentStart hook error: ${start.blockedReason}`);
1126
1314
  }
1127
1315
  }
1128
- const customAgent = this.options.extensions?.agent(options.input.subagentType);
1129
1316
  const baseSystem = options.input.subagentType === 'general-purpose'
1130
1317
  ? 'You are a general-purpose subagent. Complete the isolated task and return a concise result.'
1131
1318
  : options.input.subagentType === 'workflow-subagent'
1132
1319
  ? 'You are a workflow subagent. Complete the isolated task. Your final text is the raw return value consumed by the workflow, not a user-facing message.'
1133
1320
  : `# Agent definition: ${options.input.subagentType}\n\n${customAgent?.body ?? ''}`;
1134
- const system = options.outputSchema
1135
- ? `${baseSystem}\n\nYou MUST call StructuredOutput exactly once at the end with a value matching its schema.`
1321
+ const memoryPrompt = await agentMemoryPrompt(this.options.configRoot, cwd, customAgent);
1322
+ const agentSystem = memoryPrompt
1323
+ ? `${baseSystem}\n\n${memoryPrompt}`
1136
1324
  : baseSystem;
1325
+ const system = options.outputSchema
1326
+ ? `${agentSystem}\n\nYou MUST call StructuredOutput exactly once at the end with a value matching its schema.`
1327
+ : agentSystem;
1328
+ const preloadedSkills = agentSkillMessages(this.options.extensions, customAgent);
1137
1329
  let stopHookActive = false;
1138
1330
  const contextBudget = options.provider.capabilities.contextWindowTokens
1139
1331
  ? new ContextBudget({
@@ -1154,17 +1346,20 @@ export class ClaudeSubagentExecutor {
1154
1346
  ...(assembledContext?.systemMessages ?? []),
1155
1347
  { role: 'system', content: system },
1156
1348
  ...injectFirstUserMessageContext(projectClaudeModelMessages(snapshot.entries), assembledContext?.firstUserMessageContext),
1349
+ ...preloadedSkills,
1157
1350
  ];
1158
1351
  if (contextBudget) {
1159
1352
  contextBudget.assertFits(contextBudget.evaluate(messages, definitions));
1160
1353
  }
1161
1354
  return messages;
1162
1355
  };
1356
+ const configuredEffort = typeof customAgent?.effort === 'string' ? customAgent.effort : undefined;
1357
+ const effectiveEffort = options.effort ?? configuredEffort;
1163
1358
  const result = await runtime.run({
1164
1359
  messages: await assembleMessages(),
1165
1360
  reloadMessages: assembleMessages,
1166
1361
  cwd,
1167
- ...(options.effort ? { effort: options.effort } : {}),
1362
+ ...(effectiveEffort ? { effort: effectiveEffort } : {}),
1168
1363
  toolResultDirectory: options.toolResultDirectory,
1169
1364
  observer,
1170
1365
  ...(this.options.approveTool
@@ -1174,21 +1369,24 @@ export class ClaudeSubagentExecutor {
1174
1369
  ...(this.options.onPermissionUpdates
1175
1370
  ? { onPermissionUpdates: this.options.onPermissionUpdates }
1176
1371
  : {}),
1177
- ...(this.options.hooks || this.options.backgroundTaskNotifications
1372
+ ...(scopedHooks || this.options.backgroundTaskNotifications
1178
1373
  ? {
1179
1374
  onStop: async (text) => {
1180
1375
  const messages = [];
1181
- const outcome = await this.options.hooks?.run({
1376
+ const outcome = await scopedHooks?.run({
1182
1377
  ...hookSession,
1183
- hook_event_name: 'Stop',
1378
+ hook_event_name: 'SubagentStop',
1184
1379
  stop_hook_active: stopHookActive,
1380
+ agent_id: options.agentId,
1381
+ agent_transcript_path: options.transcriptPath,
1382
+ agent_type: options.input.subagentType,
1185
1383
  last_assistant_message: text,
1186
- }, undefined, options.signal);
1384
+ }, options.input.subagentType, options.signal);
1187
1385
  if (outcome) {
1188
1386
  await recordHookOutcome(outcome);
1189
1387
  if (outcome.blockedReason) {
1190
1388
  stopHookActive = true;
1191
- messages.push(`Stop hook error: ${outcome.blockedReason}`);
1389
+ messages.push(`SubagentStop hook error: ${outcome.blockedReason}`);
1192
1390
  }
1193
1391
  }
1194
1392
  const background = await this.background.notifications({
@@ -1251,25 +1449,12 @@ export class ClaudeSubagentExecutor {
1251
1449
  throw error;
1252
1450
  }
1253
1451
  finally {
1254
- try {
1255
- const outcome = await this.options.hooks?.run({
1256
- ...hookSession,
1257
- hook_event_name: 'SessionEnd',
1258
- reason: 'other',
1259
- }, 'other');
1260
- for (const execution of outcome?.executions.filter((value) => value.exitCode !== 0) ?? []) {
1261
- this.options.eventSink?.({
1262
- type: 'warning',
1263
- message: `Subagent SessionEnd hook failed: ${execution.stderr.trim() || execution.stdout.trim() || `exit code ${execution.exitCode}`}`,
1264
- });
1265
- }
1266
- }
1267
- catch (error) {
1452
+ await agentMcp?.close().catch((error) => {
1268
1453
  this.options.eventSink?.({
1269
1454
  type: 'warning',
1270
- message: `Subagent SessionEnd hook failed: ${error instanceof Error ? error.message : String(error)}`,
1455
+ message: `Agent MCP cleanup failed: ${error instanceof Error ? error.message : String(error)}`,
1271
1456
  });
1272
- }
1457
+ });
1273
1458
  }
1274
1459
  }
1275
1460
  }
@@ -8,6 +8,8 @@ import { type TuiMemoryFiles } from './tui/memory-files.js';
8
8
  import { type TuiDiffSnapshot } from './tui/git-diff.js';
9
9
  import { type TuiPermissionBehavior, type TuiPermissionRule } from './tui/permission-settings.js';
10
10
  import { type RecentlyDeniedStore } from './tui/recently-denied.js';
11
+ import { type AgentColorSelection } from '../compatibility/claude/agent-color.js';
12
+ import type { AgentColorName } from '../compatibility/claude/agent-color.js';
11
13
  import type { ClaudeResourceScope } from '../compatibility/claude/shared-resources.js';
12
14
  import type { TuiHookConfiguration } from './tui/hook-settings.js';
13
15
  import { type TuiSlashCommand } from './tui/slash-commands.js';
@@ -41,6 +43,8 @@ interface InteractiveSessionCommands {
41
43
  retryRecentlyDenied?(sessionId: string, display: string, signal?: AbortSignal): Promise<SessionRunResult>;
42
44
  answerSideQuestion?(sessionId: string | undefined, question: string, signal?: AbortSignal, onDelta?: (delta: string) => void, permissionMode?: ClaudePermissionMode): Promise<SideQuestionResult>;
43
45
  recordBtwUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
46
+ recordColorUsage?(sessionId: string | undefined, selection: AgentColorSelection, display: string, permissionMode?: ClaudePermissionMode): Promise<string>;
47
+ agentColor?(sessionId: string): Promise<AgentColorName | undefined>;
44
48
  recordBackgroundUsage?(sessionId: string | undefined, permissionMode?: ClaudePermissionMode): Promise<string>;
45
49
  recordBackgroundLaunch?(sessionId: string): Promise<SessionForkCheckpoint>;
46
50
  forkSideQuestion?(sessionId: string, question: string, signal?: AbortSignal): Promise<SideQuestionForkResult>;
@@ -58,6 +62,7 @@ interface InteractiveSessionCommands {
58
62
  slashCommands?(): readonly TuiSlashCommand[];
59
63
  agentDefinitions?(): readonly TuiAgentEntry[];
60
64
  runtimeInfo?(): CliRuntimeInfo;
65
+ initialAgentPrompt?(): string | undefined;
61
66
  setPermissionMode?(sessionId: string, mode: ClaudePermissionMode): Promise<void>;
62
67
  nextScheduledPrompt?(signal?: AbortSignal): Promise<{
63
68
  id: string;
@@ -110,6 +115,7 @@ interface InteractiveAppProps {
110
115
  initialSessions: readonly SessionSummary[];
111
116
  initialPrompt?: string;
112
117
  initialHistory?: readonly TranscriptItem[];
118
+ initialSessionColor?: AgentColorName;
113
119
  signal?: AbortSignal;
114
120
  onCancel?: () => void;
115
121
  onTurnChange?: (turn: Promise<void> | null) => void;
@@ -178,7 +184,7 @@ interface InteractiveAppProps {
178
184
  releaseNotesLoader?: (configRoot: string) => Promise<string>;
179
185
  settingSources?: readonly ClaudeResourceScope[];
180
186
  }
181
- export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, elicitationUrlOpener, releaseNotesLoader, settingSources, }: InteractiveAppProps): import("react").JSX.Element;
187
+ export declare function InteractiveApp({ factory, initialSessions, initialPrompt, initialHistory, initialSessionColor, signal, onCancel, onTurnChange, onCleanup, onRendererChange, onBackground, axScreenReader, allowNewSession, resume, display, terminalWidth, slashCommands, agents, allowDangerouslySkipPermissions, additionalDirectories, diffLoader, fileLoader, externalEditor, keybindingsConfigRoot, keybindingsFile, keybindingsLoader, keybindingsEditor, memoryFilesLoader, memoryEditor, memoryFolderOpener, suspendProcess, clipboardReader, clipboardWriter, sideQuestionClipboardWriter, exportWriter, permissionRuleStore, sandboxStore: suppliedSandboxStore, recentlyDeniedStore: suppliedRecentlyDeniedStore, terminalSetup: terminalSetupOverride, themeStore, initialThemeSettings, initialThemeLoadError, workspaceDirectoryResolver, workspaceDirectoryCompleter, runtimeSettings: suppliedRuntimeSettings, runtimeSettingsTarget, notificationWriter, elicitationUrlOpener, releaseNotesLoader, settingSources, }: InteractiveAppProps): import("react").JSX.Element;
182
188
  export declare function runInteractive(options: {
183
189
  factory: InteractiveServiceFactory;
184
190
  initialPrompt?: string;