@mariozechner/pi-coding-agent 0.46.0 → 0.48.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 +61 -1
- package/README.md +34 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +10 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts +16 -3
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +125 -22
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +2 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +11 -4
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +17 -0
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +52 -23
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +0 -33
- package/dist/core/export-html/template.js +171 -18
- package/dist/core/export-html/tool-renderer.d.ts +35 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +57 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +8 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +41 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +45 -6
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +5 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +22 -28
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +5 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +8 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +43 -0
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +9 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +21 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +6 -37
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +19 -14
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +2 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +4 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +4 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +8 -3
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/path-utils.d.ts +1 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +7 -0
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +13 -2
- package/dist/core/tools/read.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +84 -14
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +2 -2
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +2 -2
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +3 -3
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +5 -3
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +12 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +3 -1
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +7 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +140 -4
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +123 -106
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +23 -3
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +7 -2
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +7 -1
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +6 -1
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +14 -1
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/photon.d.ts +28 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +51 -0
- package/dist/utils/photon.js.map +1 -0
- package/docs/extensions.md +83 -4
- package/docs/rpc.md +17 -15
- package/docs/sdk.md +1 -1
- package/docs/tree.md +20 -2
- package/docs/tui.md +26 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/modal-editor.ts +1 -1
- package/examples/extensions/overlay-test.ts +8 -3
- package/examples/extensions/question.ts +1 -1
- package/examples/extensions/questionnaire.ts +1 -1
- package/examples/extensions/rainbow-editor.ts +1 -8
- package/examples/extensions/subagent/agents.ts +3 -32
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +6 -5
|
@@ -12,11 +12,15 @@
|
|
|
12
12
|
*
|
|
13
13
|
* Modes use this class and add their own I/O layer on top.
|
|
14
14
|
*/
|
|
15
|
+
import { readFileSync } from "node:fs";
|
|
15
16
|
import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@mariozechner/pi-ai";
|
|
16
17
|
import { getAuthPath } from "../config.js";
|
|
18
|
+
import { theme } from "../modes/interactive/theme/theme.js";
|
|
19
|
+
import { stripFrontmatter } from "../utils/frontmatter.js";
|
|
17
20
|
import { executeBash as executeBashCommand, executeBashWithOperations } from "./bash-executor.js";
|
|
18
21
|
import { calculateContextTokens, collectEntriesForBranchSummary, compact, generateBranchSummary, prepareCompaction, shouldCompact, } from "./compaction/index.js";
|
|
19
22
|
import { exportSessionToHtml } from "./export-html/index.js";
|
|
23
|
+
import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
|
|
20
24
|
import { expandPromptTemplate } from "./prompt-templates.js";
|
|
21
25
|
// ============================================================================
|
|
22
26
|
// Constants
|
|
@@ -394,8 +398,25 @@ export class AgentSession {
|
|
|
394
398
|
return;
|
|
395
399
|
}
|
|
396
400
|
}
|
|
397
|
-
//
|
|
398
|
-
|
|
401
|
+
// Emit input event for extension interception (before skill/template expansion)
|
|
402
|
+
let currentText = text;
|
|
403
|
+
let currentImages = options?.images;
|
|
404
|
+
if (this._extensionRunner?.hasHandlers("input")) {
|
|
405
|
+
const inputResult = await this._extensionRunner.emitInput(currentText, currentImages, options?.source ?? "interactive");
|
|
406
|
+
if (inputResult.action === "handled") {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
if (inputResult.action === "transform") {
|
|
410
|
+
currentText = inputResult.text;
|
|
411
|
+
currentImages = inputResult.images ?? currentImages;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
// Expand skill commands (/skill:name args) and prompt templates (/template args)
|
|
415
|
+
let expandedText = currentText;
|
|
416
|
+
if (expandPromptTemplates) {
|
|
417
|
+
expandedText = this._expandSkillCommand(expandedText);
|
|
418
|
+
expandedText = expandPromptTemplate(expandedText, [...this._promptTemplates]);
|
|
419
|
+
}
|
|
399
420
|
// If streaming, queue via steer() or followUp() based on option
|
|
400
421
|
if (this.isStreaming) {
|
|
401
422
|
if (!options?.streamingBehavior) {
|
|
@@ -432,8 +453,8 @@ export class AgentSession {
|
|
|
432
453
|
const messages = [];
|
|
433
454
|
// Add user message
|
|
434
455
|
const userContent = [{ type: "text", text: expandedText }];
|
|
435
|
-
if (
|
|
436
|
-
userContent.push(...
|
|
456
|
+
if (currentImages) {
|
|
457
|
+
userContent.push(...currentImages);
|
|
437
458
|
}
|
|
438
459
|
messages.push({
|
|
439
460
|
role: "user",
|
|
@@ -447,7 +468,7 @@ export class AgentSession {
|
|
|
447
468
|
this._pendingNextTurnMessages = [];
|
|
448
469
|
// Emit before_agent_start extension event
|
|
449
470
|
if (this._extensionRunner) {
|
|
450
|
-
const result = await this._extensionRunner.emitBeforeAgentStart(expandedText,
|
|
471
|
+
const result = await this._extensionRunner.emitBeforeAgentStart(expandedText, currentImages, this._baseSystemPrompt);
|
|
451
472
|
// Add all custom messages from extensions
|
|
452
473
|
if (result?.messages) {
|
|
453
474
|
for (const msg of result.messages) {
|
|
@@ -502,10 +523,41 @@ export class AgentSession {
|
|
|
502
523
|
return true;
|
|
503
524
|
}
|
|
504
525
|
}
|
|
526
|
+
/**
|
|
527
|
+
* Expand skill commands (/skill:name args) to their full content.
|
|
528
|
+
* Returns the expanded text, or the original text if not a skill command or skill not found.
|
|
529
|
+
* Emits errors via extension runner if file read fails.
|
|
530
|
+
*/
|
|
531
|
+
_expandSkillCommand(text) {
|
|
532
|
+
if (!text.startsWith("/skill:"))
|
|
533
|
+
return text;
|
|
534
|
+
const spaceIndex = text.indexOf(" ");
|
|
535
|
+
const skillName = spaceIndex === -1 ? text.slice(7) : text.slice(7, spaceIndex);
|
|
536
|
+
const args = spaceIndex === -1 ? "" : text.slice(spaceIndex + 1).trim();
|
|
537
|
+
const skill = this._skills.find((s) => s.name === skillName);
|
|
538
|
+
if (!skill)
|
|
539
|
+
return text; // Unknown skill, pass through
|
|
540
|
+
try {
|
|
541
|
+
const content = readFileSync(skill.filePath, "utf-8");
|
|
542
|
+
const body = stripFrontmatter(content).trim();
|
|
543
|
+
const header = `Skill location: ${skill.filePath}\nReferences are relative to ${skill.baseDir}.`;
|
|
544
|
+
const skillMessage = `${header}\n\n${body}`;
|
|
545
|
+
return args ? `${skillMessage}\n\n---\n\nUser: ${args}` : skillMessage;
|
|
546
|
+
}
|
|
547
|
+
catch (err) {
|
|
548
|
+
// Emit error like extension commands do
|
|
549
|
+
this._extensionRunner?.emitError({
|
|
550
|
+
extensionPath: skill.filePath,
|
|
551
|
+
event: "skill_expansion",
|
|
552
|
+
error: err instanceof Error ? err.message : String(err),
|
|
553
|
+
});
|
|
554
|
+
return text; // Return original on error
|
|
555
|
+
}
|
|
556
|
+
}
|
|
505
557
|
/**
|
|
506
558
|
* Queue a steering message to interrupt the agent mid-run.
|
|
507
559
|
* Delivered after current tool execution, skips remaining tools.
|
|
508
|
-
* Expands
|
|
560
|
+
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
509
561
|
* @throws Error if text is an extension command
|
|
510
562
|
*/
|
|
511
563
|
async steer(text) {
|
|
@@ -513,14 +565,15 @@ export class AgentSession {
|
|
|
513
565
|
if (text.startsWith("/")) {
|
|
514
566
|
this._throwIfExtensionCommand(text);
|
|
515
567
|
}
|
|
516
|
-
// Expand
|
|
517
|
-
|
|
568
|
+
// Expand skill commands and prompt templates
|
|
569
|
+
let expandedText = this._expandSkillCommand(text);
|
|
570
|
+
expandedText = expandPromptTemplate(expandedText, [...this._promptTemplates]);
|
|
518
571
|
await this._queueSteer(expandedText);
|
|
519
572
|
}
|
|
520
573
|
/**
|
|
521
574
|
* Queue a follow-up message to be processed after the agent finishes.
|
|
522
575
|
* Delivered only when agent has no more tool calls or steering messages.
|
|
523
|
-
* Expands
|
|
576
|
+
* Expands skill commands and prompt templates. Errors on extension commands.
|
|
524
577
|
* @throws Error if text is an extension command
|
|
525
578
|
*/
|
|
526
579
|
async followUp(text) {
|
|
@@ -528,8 +581,9 @@ export class AgentSession {
|
|
|
528
581
|
if (text.startsWith("/")) {
|
|
529
582
|
this._throwIfExtensionCommand(text);
|
|
530
583
|
}
|
|
531
|
-
// Expand
|
|
532
|
-
|
|
584
|
+
// Expand skill commands and prompt templates
|
|
585
|
+
let expandedText = this._expandSkillCommand(text);
|
|
586
|
+
expandedText = expandPromptTemplate(expandedText, [...this._promptTemplates]);
|
|
533
587
|
await this._queueFollowUp(expandedText);
|
|
534
588
|
}
|
|
535
589
|
/**
|
|
@@ -641,6 +695,7 @@ export class AgentSession {
|
|
|
641
695
|
expandPromptTemplates: false,
|
|
642
696
|
streamingBehavior: options?.deliverAs,
|
|
643
697
|
images,
|
|
698
|
+
source: "extension",
|
|
644
699
|
});
|
|
645
700
|
}
|
|
646
701
|
/**
|
|
@@ -1169,10 +1224,16 @@ export class AgentSession {
|
|
|
1169
1224
|
}
|
|
1170
1225
|
}
|
|
1171
1226
|
catch (error) {
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1227
|
+
const errorMessage = error instanceof Error ? error.message : "compaction failed";
|
|
1228
|
+
this._emit({
|
|
1229
|
+
type: "auto_compaction_end",
|
|
1230
|
+
result: undefined,
|
|
1231
|
+
aborted: false,
|
|
1232
|
+
willRetry: false,
|
|
1233
|
+
errorMessage: reason === "overflow"
|
|
1234
|
+
? `Context overflow recovery failed: ${errorMessage}`
|
|
1235
|
+
: `Auto-compaction failed: ${errorMessage}`,
|
|
1236
|
+
});
|
|
1176
1237
|
}
|
|
1177
1238
|
finally {
|
|
1178
1239
|
this._autoCompactionAbortController = undefined;
|
|
@@ -1203,8 +1264,8 @@ export class AgentSession {
|
|
|
1203
1264
|
if (isContextOverflow(message, contextWindow))
|
|
1204
1265
|
return false;
|
|
1205
1266
|
const err = message.errorMessage;
|
|
1206
|
-
// Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection
|
|
1207
|
-
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|other side closed|fetch failed/i.test(err);
|
|
1267
|
+
// Match: overloaded_error, rate limit, 429, 500, 502, 503, 504, service unavailable, connection errors, fetch failed
|
|
1268
|
+
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server error|internal error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers/i.test(err);
|
|
1208
1269
|
}
|
|
1209
1270
|
/**
|
|
1210
1271
|
* Handle retryable errors with exponential backoff.
|
|
@@ -1334,13 +1395,16 @@ export class AgentSession {
|
|
|
1334
1395
|
*/
|
|
1335
1396
|
async executeBash(command, onChunk, options) {
|
|
1336
1397
|
this._bashAbortController = new AbortController();
|
|
1398
|
+
// Apply command prefix if configured (e.g., "shopt -s expand_aliases" for alias support)
|
|
1399
|
+
const prefix = this.settingsManager.getShellCommandPrefix();
|
|
1400
|
+
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
|
1337
1401
|
try {
|
|
1338
1402
|
const result = options?.operations
|
|
1339
|
-
? await executeBashWithOperations(
|
|
1403
|
+
? await executeBashWithOperations(resolvedCommand, process.cwd(), options.operations, {
|
|
1340
1404
|
onChunk,
|
|
1341
1405
|
signal: this._bashAbortController.signal,
|
|
1342
1406
|
})
|
|
1343
|
-
: await executeBashCommand(
|
|
1407
|
+
: await executeBashCommand(resolvedCommand, {
|
|
1344
1408
|
onChunk,
|
|
1345
1409
|
signal: this._bashAbortController.signal,
|
|
1346
1410
|
});
|
|
@@ -1529,6 +1593,8 @@ export class AgentSession {
|
|
|
1529
1593
|
* @param targetId The entry ID to navigate to
|
|
1530
1594
|
* @param options.summarize Whether user wants to summarize abandoned branch
|
|
1531
1595
|
* @param options.customInstructions Custom instructions for summarizer
|
|
1596
|
+
* @param options.replaceInstructions If true, customInstructions replaces the default prompt
|
|
1597
|
+
* @param options.label Label to attach to the branch summary entry
|
|
1532
1598
|
* @returns Result with editorText (if user message) and cancelled status
|
|
1533
1599
|
*/
|
|
1534
1600
|
async navigateTree(targetId, options = {}) {
|
|
@@ -1547,13 +1613,19 @@ export class AgentSession {
|
|
|
1547
1613
|
}
|
|
1548
1614
|
// Collect entries to summarize (from old leaf to common ancestor)
|
|
1549
1615
|
const { entries: entriesToSummarize, commonAncestorId } = collectEntriesForBranchSummary(this.sessionManager, oldLeafId, targetId);
|
|
1550
|
-
// Prepare event data
|
|
1616
|
+
// Prepare event data - mutable so extensions can override
|
|
1617
|
+
let customInstructions = options.customInstructions;
|
|
1618
|
+
let replaceInstructions = options.replaceInstructions;
|
|
1619
|
+
let label = options.label;
|
|
1551
1620
|
const preparation = {
|
|
1552
1621
|
targetId,
|
|
1553
1622
|
oldLeafId,
|
|
1554
1623
|
commonAncestorId,
|
|
1555
1624
|
entriesToSummarize,
|
|
1556
1625
|
userWantsSummary: options.summarize ?? false,
|
|
1626
|
+
customInstructions,
|
|
1627
|
+
replaceInstructions,
|
|
1628
|
+
label,
|
|
1557
1629
|
};
|
|
1558
1630
|
// Set up abort controller for summarization
|
|
1559
1631
|
this._branchSummaryAbortController = new AbortController();
|
|
@@ -1573,6 +1645,16 @@ export class AgentSession {
|
|
|
1573
1645
|
extensionSummary = result.summary;
|
|
1574
1646
|
fromExtension = true;
|
|
1575
1647
|
}
|
|
1648
|
+
// Allow extensions to override instructions and label
|
|
1649
|
+
if (result?.customInstructions !== undefined) {
|
|
1650
|
+
customInstructions = result.customInstructions;
|
|
1651
|
+
}
|
|
1652
|
+
if (result?.replaceInstructions !== undefined) {
|
|
1653
|
+
replaceInstructions = result.replaceInstructions;
|
|
1654
|
+
}
|
|
1655
|
+
if (result?.label !== undefined) {
|
|
1656
|
+
label = result.label;
|
|
1657
|
+
}
|
|
1576
1658
|
}
|
|
1577
1659
|
// Run default summarizer if needed
|
|
1578
1660
|
let summaryText;
|
|
@@ -1588,7 +1670,8 @@ export class AgentSession {
|
|
|
1588
1670
|
model,
|
|
1589
1671
|
apiKey,
|
|
1590
1672
|
signal: this._branchSummaryAbortController.signal,
|
|
1591
|
-
customInstructions
|
|
1673
|
+
customInstructions,
|
|
1674
|
+
replaceInstructions,
|
|
1592
1675
|
reserveTokens: branchSummarySettings.reserveTokens,
|
|
1593
1676
|
});
|
|
1594
1677
|
this._branchSummaryAbortController = undefined;
|
|
@@ -1638,6 +1721,10 @@ export class AgentSession {
|
|
|
1638
1721
|
// Create summary at target position (can be null for root)
|
|
1639
1722
|
const summaryId = this.sessionManager.branchWithSummary(newLeafId, summaryText, summaryDetails, fromExtension);
|
|
1640
1723
|
summaryEntry = this.sessionManager.getEntry(summaryId);
|
|
1724
|
+
// Attach label to the summary entry
|
|
1725
|
+
if (label) {
|
|
1726
|
+
this.sessionManager.appendLabelChange(summaryId, label);
|
|
1727
|
+
}
|
|
1641
1728
|
}
|
|
1642
1729
|
else if (newLeafId === null) {
|
|
1643
1730
|
// No summary, navigating to root - reset leaf
|
|
@@ -1647,6 +1734,10 @@ export class AgentSession {
|
|
|
1647
1734
|
// No summary, navigating to non-root
|
|
1648
1735
|
this.sessionManager.branch(newLeafId);
|
|
1649
1736
|
}
|
|
1737
|
+
// Attach label to target entry when not summarizing (no summary entry to label)
|
|
1738
|
+
if (label && !summaryText) {
|
|
1739
|
+
this.sessionManager.appendLabelChange(targetId, label);
|
|
1740
|
+
}
|
|
1650
1741
|
// Update agent state
|
|
1651
1742
|
const sessionContext = this.sessionManager.buildSessionContext();
|
|
1652
1743
|
this.agent.replaceMessages(sessionContext.messages);
|
|
@@ -1743,7 +1834,19 @@ export class AgentSession {
|
|
|
1743
1834
|
*/
|
|
1744
1835
|
async exportToHtml(outputPath) {
|
|
1745
1836
|
const themeName = this.settingsManager.getTheme();
|
|
1746
|
-
|
|
1837
|
+
// Create tool renderer if we have an extension runner (for custom tool HTML rendering)
|
|
1838
|
+
let toolRenderer;
|
|
1839
|
+
if (this._extensionRunner) {
|
|
1840
|
+
toolRenderer = createToolHtmlRenderer({
|
|
1841
|
+
getToolDefinition: (name) => this._extensionRunner.getToolDefinition(name),
|
|
1842
|
+
theme,
|
|
1843
|
+
});
|
|
1844
|
+
}
|
|
1845
|
+
return await exportSessionToHtml(this.sessionManager, this.state, {
|
|
1846
|
+
outputPath,
|
|
1847
|
+
themeName,
|
|
1848
|
+
toolRenderer,
|
|
1849
|
+
});
|
|
1747
1850
|
}
|
|
1748
1851
|
// =========================================================================
|
|
1749
1852
|
// Utilities
|