gentle-pi 4.1.0 → 4.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.
- package/README.md +352 -128
- package/assets/agents/gentle-ai-explore.md +1 -0
- package/assets/agents/gentle-ai-verify.md +6 -4
- package/assets/agents/gentle-ai-worker.md +7 -1
- package/assets/orchestrator-delegation-reference.md +163 -0
- package/assets/orchestrator-delegation.md +25 -176
- package/assets/orchestrator-tracking.md +1 -1
- package/assets/orchestrator-verification.md +14 -8
- package/assets/orchestrator-writer.md +5 -1
- package/assets/orchestrator.md +9 -9
- package/bin/engram-guard +1 -1
- package/bin/gentle-shell.mjs +188 -35
- package/contracts/review-provider-contract-mirror/provider-contract.lock.json +8 -7
- package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/README.md +7 -0
- package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/manifest.json +11 -2
- package/contracts/review-provider-contract-mirror/v1.4.0/bundle/routing/pi.md +92 -0
- package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/generated/provider-capabilities.baseline.json +8 -1
- package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/generated/provider-roles.baseline.json +1 -1
- package/docs/assets/diagrams/agent-orchestration.svg +54 -15
- package/docs/assets/diagrams/gentleman-workflow.svg +69 -11
- package/docs/assets/diagrams/measured-routing.svg +49 -0
- package/docs/assets/diagrams/native-review.svg +52 -12
- package/docs/assets/diagrams/odd-workflow.svg +128 -66
- package/docs/assets/diagrams/permission-modes.svg +51 -0
- package/docs/assets/features/audio-notifications.png +0 -0
- package/docs/assets/features/command-palette.png +0 -0
- package/docs/auto-permission-answers.md +25 -0
- package/docs/auto-permission-evidence.md +39 -0
- package/docs/bundled-install.md +40 -8
- package/docs/delegated-verification.md +10 -8
- package/docs/gentle-agents-activity.md +11 -5
- package/docs/gentle-shell-uninstall.md +8 -1
- package/docs/gentle-shell.md +20 -12
- package/docs/install-wizard.md +17 -10
- package/docs/permission-modes.md +51 -6
- package/docs/readme-reference.md +155 -31
- package/docs/session-profile-format.md +39 -0
- package/docs/yolo-mode.md +21 -7
- package/extensions/ask-user-choice.ts +4 -0
- package/extensions/ask-user-question.ts +6 -1
- package/extensions/codegraph-tools.ts +68 -6
- package/extensions/gentle-agents.ts +146 -28
- package/extensions/gentle-ai.ts +380 -68
- package/extensions/gentle-herdr-activity.ts +2 -3
- package/extensions/gentle-shell.ts +53 -43
- package/extensions/gentle-todo.ts +62 -18
- package/extensions/quiet-tools.ts +1 -1
- package/extensions/session-scratch.ts +365 -0
- package/extensions/startup-banner.ts +2 -3
- package/lib/agent-home.ts +8 -3
- package/lib/agents-protocol.ts +3 -0
- package/lib/agents-runner.ts +55 -6
- package/lib/agents-view.ts +3 -1
- package/lib/auto-permission-answers.ts +133 -0
- package/lib/auto-permission-classifier.ts +215 -36
- package/lib/auto-permission-evidence.ts +88 -0
- package/lib/auto-permission-memory.ts +69 -0
- package/lib/auto-permission-runtime.ts +251 -35
- package/lib/auto-permission-tool-context.ts +61 -0
- package/lib/bounded-writer-admission.ts +51 -0
- package/lib/command-palette-catalog.ts +0 -4
- package/lib/commit-slice-signal.ts +100 -0
- package/lib/context-backstop.ts +84 -0
- package/lib/delivered-test-lint.ts +80 -0
- package/lib/destructive-command-guard.ts +215 -28
- package/lib/gauge-theme.ts +146 -0
- package/lib/gentle-ai-binary.ts +28 -7
- package/lib/gentle-shell-bundled.ts +62 -8
- package/lib/gentle-shell-import-pi.ts +233 -0
- package/lib/gentle-shell-launcher.ts +146 -12
- package/lib/gentle-shell-uninstall.ts +18 -1
- package/lib/herdr-activity.ts +24 -0
- package/lib/model-routing-authority.ts +6 -1
- package/lib/native-review-cli.ts +9 -1
- package/lib/orchestrator-discovery.ts +5 -1
- package/lib/orchestrator-presence.ts +9 -0
- package/lib/orchestrator-scope.ts +21 -3
- package/lib/provider-contract-bundle.ts +99 -53
- package/lib/review-candidate-view-owner.ts +29 -19
- package/lib/review-candidate-view.ts +36 -2
- package/lib/review-risk-assessment.ts +43 -38
- package/lib/review-session-standing-permission.ts +3 -1
- package/lib/selection-engine.ts +4 -1
- package/lib/session-profile-freeze.ts +40 -16
- package/lib/session-profile-persistence.ts +187 -0
- package/lib/session-scratch.ts +474 -0
- package/lib/shell-bar.ts +25 -25
- package/lib/shell-changes-view.ts +80 -13
- package/lib/shell-changes.ts +2 -0
- package/lib/shell-gauge.ts +49 -6
- package/lib/shell-prompt.ts +6 -4
- package/lib/shell-todo.ts +39 -8
- package/lib/shell-usage-view.ts +5 -1
- package/lib/shell-usage.ts +7 -7
- package/lib/verifier-admission.ts +29 -0
- package/lib/vim-editor-adapter.ts +22 -4
- package/lib/yolo-temp-scratch.ts +69 -0
- package/package.json +5 -6
- package/runtime/gentle-ai-binary.mjs +28 -7
- package/runtime/gentle-shell-bundled.mjs +61 -7
- package/runtime/gentle-shell-import-pi.mjs +234 -0
- package/runtime/gentle-shell-launcher.mjs +144 -10
- package/runtime/gentle-shell-uninstall.mjs +18 -1
- package/runtime/native-review-cli.mjs +8 -0
- package/runtime/review-risk-assessment.mjs +43 -38
- package/scripts/build-runtime-modules.mjs +1 -0
- package/scripts/bundled-engram-migration.mjs +125 -0
- package/scripts/gentle-ai-installer.mjs +10 -10
- package/scripts/install-wizard-preview.mjs +2 -2
- package/scripts/installer-downloads.mjs +7 -7
- package/scripts/installer-preflight.mjs +1 -1
- package/scripts/installer-server.mjs +14 -4
- package/scripts/main-channel.mjs +3 -2
- package/scripts/pi-update.mjs +223 -0
- package/scripts/run-test-suite.mjs +5 -0
- package/scripts/verify-package-files.mjs +19 -13
- package/skills/gentle-ai/SKILL.md +3 -3
- package/skills/work-unit-commits/SKILL.md +5 -3
- package/tests/agent-risk-escalation.test.ts +37 -10
- package/tests/agents-runner.test.ts +260 -3
- package/tests/append-system-prompt-route.test.ts +18 -1
- package/tests/auto-mode-human-answers.test.ts +68 -0
- package/tests/auto-mode-invariants.test.ts +23 -5
- package/tests/auto-mode-sdk.test.ts +29 -2
- package/tests/auto-permission-answers.test.ts +170 -0
- package/tests/auto-permission-classifier.test.ts +353 -2
- package/tests/auto-permission-compound.test.ts +24 -0
- package/tests/auto-permission-evidence.test.ts +88 -0
- package/tests/auto-permission-memory.test.ts +46 -0
- package/tests/auto-permission-public-regressions.test.ts +111 -0
- package/tests/auto-permission-runtime.test.ts +270 -12
- package/tests/autonomous-guard.test.ts +208 -16
- package/tests/bounded-writer-admission.test.ts +11 -3
- package/tests/bundled-install.test.ts +3 -3
- package/tests/card-content-policy.test.ts +19 -9
- package/tests/child-safety.test.ts +39 -0
- package/tests/codegraph-tools.test.ts +123 -2
- package/tests/command-palette.test.ts +14 -4
- package/tests/commit-slice-signal.test.ts +162 -0
- package/tests/context-backstop.test.ts +159 -0
- package/tests/delegate-for-reason-contract.test.ts +91 -24
- package/tests/delivered-test-lint.test.ts +105 -0
- package/tests/destructive-command-guard.test.ts +85 -1
- package/tests/engram-safety.test.ts +35 -7
- package/tests/fixtures/primary-session-prompt/gentleman.golden.md +143 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/README.md +29 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/manifest.json +83 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/orchestration/pi.md +70 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/routing/pi.md +92 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/lens.schema.json +16 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/refuter.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/schemas/targeted-validator.schema.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/lens.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/refuter.json +1 -0
- package/tests/fixtures/provider-contract-bundle/v1.4.0/vectors/targeted-validator.json +1 -0
- package/tests/gauge-theme.test.ts +120 -0
- package/tests/gentle-agents.test.ts +443 -8
- package/tests/gentle-ai-binary.test.ts +1 -1
- package/tests/gentle-ai-child-guards.test.ts +61 -0
- package/tests/gentle-ai-doctor-herdr.test.ts +94 -0
- package/tests/gentle-ai-installer.test.ts +51 -51
- package/tests/gentle-shell-bin.test.ts +180 -17
- package/tests/gentle-shell-bundled.test.ts +235 -38
- package/tests/gentle-shell-import-pi.test.ts +262 -0
- package/tests/gentle-shell-launcher.test.ts +97 -13
- package/tests/gentle-shell-uninstall.test.ts +30 -0
- package/tests/gentle-shell.test.ts +113 -14
- package/tests/gentle-todo.test.ts +258 -27
- package/tests/headless-delivery-question.test.ts +58 -0
- package/tests/herdr-activity.test.ts +34 -1
- package/tests/install-wizard.test.ts +2 -2
- package/tests/installer-posix-bootstrap.test.ts +8 -8
- package/tests/installer-preflight.test.ts +3 -3
- package/tests/installer-probes.test.ts +8 -8
- package/tests/installer-runner.test.ts +14 -13
- package/tests/installer-server.test.ts +13 -5
- package/tests/installer-windows-bootstrap.test.ts +33 -4
- package/tests/main-channel-upgrade.test.ts +7 -1
- package/tests/native-review-capability-contract.test.ts +7 -1
- package/tests/native-review-parity.test.ts +22 -1
- package/tests/no-self-pause-contract.test.ts +5 -2
- package/tests/odd-integration.test.ts +5 -1
- package/tests/odd-routing-canonical-ratchet.test.ts +127 -162
- package/tests/odd-routing-contract.test.ts +115 -30
- package/tests/odd-runtime-delegation-gate.test.ts +4 -1
- package/tests/orchestrator-budget.test.ts +19 -8
- package/tests/orchestrator-discovery.test.ts +29 -0
- package/tests/orchestrator-rdd-ownership.test.ts +3 -1
- package/tests/orchestrator-scope.test.ts +66 -0
- package/tests/orchestrator-status-publication-contract.test.ts +12 -8
- package/tests/package-manifest.test.ts +28 -24
- package/tests/pi-update-launcher.test.ts +106 -0
- package/tests/pi-update.test.ts +186 -0
- package/tests/primary-session-prompt.test.ts +101 -0
- package/tests/provider-contract-bundle.test.ts +118 -0
- package/tests/provider-contract-mirror.test.ts +24 -0
- package/tests/quiet-tool-rendering.test.ts +23 -0
- package/tests/rdd-aware-verification-contract.test.ts +29 -11
- package/tests/rdd-status-line.test.ts +131 -0
- package/tests/review-agent-end-preflight.test.ts +6 -0
- package/tests/review-candidate-view.test.ts +49 -0
- package/tests/review-contract-prompt.test.ts +5 -2
- package/tests/review-controller-native-routing.test.ts +14 -1
- package/tests/review-controller.test.ts +1 -1
- package/tests/review-host-relay-routing.test.ts +59 -2
- package/tests/review-loadout-rdd-off-sdk.test.ts +237 -0
- package/tests/review-owner-identity.test.ts +132 -0
- package/tests/review-risk-assessment.test.ts +163 -76
- package/tests/review-session-standing-permission-controller.test.ts +14 -1
- package/tests/review-session-standing-permission.test.ts +27 -1
- package/tests/run-test-suite.test.ts +15 -0
- package/tests/runtime-harness.mjs +16 -6
- package/tests/selection-engine.test.ts +35 -5
- package/tests/session-changes-shell.test.ts +1 -1
- package/tests/session-profile-freeze.test.ts +37 -1
- package/tests/session-profile-persistence.test.ts +334 -0
- package/tests/session-scratch.test.ts +945 -0
- package/tests/session-subject-routing-contract.test.ts +2 -1
- package/tests/shell-bar.test.ts +7 -0
- package/tests/shell-changes-view.test.ts +137 -1
- package/tests/shell-changes.test.ts +18 -0
- package/tests/shell-gauge.test.ts +42 -0
- package/tests/shell-todo.test.ts +15 -12
- package/tests/small-task-inline-contract.test.ts +37 -0
- package/tests/standalone-config-home.test.ts +324 -0
- package/tests/startup-banner.test.ts +5 -4
- package/tests/startup-home-repo.test.ts +34 -0
- package/tests/support/orchestrator-modules.ts +1 -0
- package/tests/task-size-routing-contract.test.ts +69 -9
- package/tests/test-scratch-contract.test.ts +102 -0
- package/tests/test-strength-contract.test.ts +36 -1
- package/tests/tool-batching-contract.test.ts +64 -0
- package/tests/verification-proportionality.test.ts +46 -0
- package/tests/verifier-admission.test.ts +137 -0
- package/tests/verify-agent-contract.test.ts +8 -8
- package/tests/vim-editor-adapter.test.ts +41 -15
- package/tests/windows-hidden-processes.test.ts +5 -0
- package/tests/writer-edit-surface-scope.test.ts +3 -0
- package/tests/writer-feature-document-admission.test.ts +156 -0
- package/tests/yolo-mode.test.ts +24 -1
- package/tests/yolo-temp-scratch.test.ts +71 -0
- package/scripts/mirror-odd-routing.mjs +0 -242
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/orchestration/pi.md +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/lens.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/refuter.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/schemas/targeted-validator.schema.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/lens.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/refuter.json +0 -0
- /package/contracts/review-provider-contract-mirror/{v1.3.0 → v1.4.0}/bundle/vectors/targeted-validator.json +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { statSync } from "node:fs";
|
|
2
2
|
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
3
|
-
import { activitySummary, ActivityPublisher, createActivityColumns, metadataTransport } from "../lib/herdr-activity.ts";
|
|
3
|
+
import { activitySummary, ActivityPublisher, createActivityColumns, herdrDetected, metadataTransport } from "../lib/herdr-activity.ts";
|
|
4
4
|
import { replayTodo, type TodoState } from "../lib/shell-todo.ts";
|
|
5
5
|
|
|
6
6
|
interface ActivityOptions {
|
|
@@ -15,8 +15,7 @@ interface ActivityOptions {
|
|
|
15
15
|
export function createHerdrActivityExtension(options: ActivityOptions = {}) {
|
|
16
16
|
return (pi: ExtensionAPI): void => {
|
|
17
17
|
const env = options.env ?? process.env;
|
|
18
|
-
if (env.GENTLE_PI_AGENTS_CHILD === "1" || env
|
|
19
|
-
!env.HERDR_PANE_ID?.trim() || !env.HERDR_SOCKET_PATH?.trim()) return;
|
|
18
|
+
if (env.GENTLE_PI_AGENTS_CHILD === "1" || !herdrDetected(env)) return;
|
|
20
19
|
const isSocket = options.isSocket ?? ((path: string) => {
|
|
21
20
|
try { return statSync(path).isSocket(); } catch { return false; }
|
|
22
21
|
});
|
|
@@ -6,13 +6,13 @@ import { existsSync, realpathSync, statSync } from "node:fs";
|
|
|
6
6
|
import { lstat, readFile } from "node:fs/promises";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
8
|
import { profilesFilePath, profileRoleEntries, readProfilesFileResult } from "../lib/agent-profiles.ts";
|
|
9
|
-
import {
|
|
10
|
-
import { resolveProfilePin } from "../lib/agent-profile-pin.ts";
|
|
9
|
+
import { resolveSessionProfile, sessionProfileLabel, sessionProfileModelProfiles } from "../lib/session-profile-freeze.ts";
|
|
11
10
|
import * as os from "node:os";
|
|
12
11
|
import { dirname, join, resolve } from "node:path";
|
|
13
12
|
import { buildShellHeaderModel, renderShellBar, renderShellBelowInputFloat, renderShellBottomOnlyBar, renderShellHeaderChrome, renderShellSidebarBar, keepNativeWorkingRow, shellEnabled, shellHeaderUsageHit, shellJobsCount, type ShellBarModel, type ShellBarTheme } from "../lib/shell-bar.ts";
|
|
14
13
|
import { CHANGE_STATUS, DIFF_MAX_BYTES, DIFF_MAX_LINES, DIFF_TOO_LARGE, WorktreeChangesTracker, renderChangesWidget, type ChangedFile, type ChangesModel, type FileRevision, type GitRunner, type LineCounter, type WorktreeChanges } from "../lib/shell-changes.ts";
|
|
15
14
|
import { WorktreeChangesView } from "../lib/shell-changes-view.ts";
|
|
15
|
+
import { createNativeFullscreenInteraction } from "../lib/native-fullscreen-interaction.ts";
|
|
16
16
|
import { SessionWorktreeRegistry, resolveSessionWorktree, worktreeGitEnvironment, type WorktreeResolver, type WorktreeIdentity } from "../lib/session-worktree-registry.ts";
|
|
17
17
|
import { CARD_STYLE, CARD_TONE, cardStyle, renderCard, setCardStyle, type Card, type CardTheme } from "../lib/shell-card.ts";
|
|
18
18
|
import { resolveCardStyle, writeCardStyle } from "../lib/card-style-policy.ts";
|
|
@@ -22,6 +22,8 @@ import { buildCommandPaletteGroups } from "../lib/command-palette-catalog.ts";
|
|
|
22
22
|
import { discoverYoloUiAdapter, YOLO_DISPLAY, type YoloDisplay, type YoloUiAdapter } from "../lib/yolo-session-policy.ts";
|
|
23
23
|
import { VisualCustomizeView, type CustomizeCategory, type CustomizeRow, type ProfileActions } from "../lib/visual-customize-view.ts";
|
|
24
24
|
import { deleteVisualProfile, getVisualProfile, listVisualProfiles, resetVisualProfiles, saveVisualProfile } from "../lib/visual-profiles.ts";
|
|
25
|
+
import { gaugePaintFor } from "../lib/gauge-theme.ts";
|
|
26
|
+
import type { GaugePaint } from "../lib/shell-gauge.ts";
|
|
25
27
|
import { sourcePalettePreview } from "../lib/theme-customization.ts";
|
|
26
28
|
import { DEFAULT_VISUAL_SETTINGS, DENSITY, HEADER_PLACEMENT, STATUS_PLACEMENT, VISUAL_SECTION_KEYS, resolveVisualSettings, writeVisualSettings } from "../lib/visual-customization-policy.ts";
|
|
27
29
|
import { BANNER_COLORS, DEFAULT_BANNER_CONFIG, readBannerConfig, readBannerConfigForEdit, writeBannerConfig } from "./startup-banner.ts";
|
|
@@ -32,7 +34,6 @@ import { oddPhaseRegistry } from "../lib/odd-phase.ts";
|
|
|
32
34
|
import { inferOddPhase } from "../lib/odd-phase-inference.ts";
|
|
33
35
|
import { isInteractiveMode } from "../lib/rpc-host.ts";
|
|
34
36
|
import { gentlePiConfigHome } from "../lib/agent-home.ts";
|
|
35
|
-
import { bundledGentlePiConfigHome } from "../lib/gentle-shell-bundled.ts";
|
|
36
37
|
import { isNanAdaptiveReasoningModel } from "../lib/nan-provider.ts";
|
|
37
38
|
import { resolveAnimationPolicy, writeAnimationPolicy, type AnimationPolicy } from "../lib/animation-policy.ts";
|
|
38
39
|
import { resolveVimPolicy, writeVimPolicy, type VimPolicy } from "../lib/vim-policy.ts";
|
|
@@ -181,7 +182,7 @@ export type ActiveProfileReader = (() => string | undefined) & {
|
|
|
181
182
|
// Unbound reads retain the global file-identity cache, including atomic replacements.
|
|
182
183
|
// Bound reads are snapshots: no filesystem or Git work is done during a frame.
|
|
183
184
|
export function createActiveProfileReader(env: NodeJS.ProcessEnv = process.env): ActiveProfileReader {
|
|
184
|
-
const path = profilesFilePath(
|
|
185
|
+
const path = profilesFilePath(gentlePiConfigHome(env));
|
|
185
186
|
let fingerprint: string | undefined;
|
|
186
187
|
let name: string | undefined;
|
|
187
188
|
let bound = false;
|
|
@@ -208,23 +209,18 @@ export function createActiveProfileReader(env: NodeJS.ProcessEnv = process.env):
|
|
|
208
209
|
const reader = (() => bound ? effective : global()) as ActiveProfileReader;
|
|
209
210
|
reader.refresh = () => {
|
|
210
211
|
if (!bound) return false;
|
|
211
|
-
// gentle-shell#1064
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
//
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
const changed = next !== effective;
|
|
219
|
-
effective = next;
|
|
220
|
-
return changed;
|
|
221
|
-
}
|
|
222
|
-
const pin = identity && cwd ? resolveProfilePin({
|
|
212
|
+
// gentle-shell#1064: the status shows the profile launches use, through
|
|
213
|
+
// the same single rule (explicit Enter binding → profile frozen at
|
|
214
|
+
// startup → live p → P → G only in follow mode), with the existing
|
|
215
|
+
// spelling: "name (session)", "name (local)", "name (repo)", or the bare
|
|
216
|
+
// global name.
|
|
217
|
+
const next = cwd === undefined ? global() : sessionProfileLabel(resolveSessionProfile({
|
|
218
|
+
sessionId,
|
|
223
219
|
cwd,
|
|
224
|
-
configHome:
|
|
225
|
-
resolveWorktree: () => identity
|
|
226
|
-
|
|
227
|
-
|
|
220
|
+
configHome: gentlePiConfigHome(env),
|
|
221
|
+
resolveWorktree: () => identity,
|
|
222
|
+
env,
|
|
223
|
+
}));
|
|
228
224
|
const changed = next !== effective;
|
|
229
225
|
effective = next;
|
|
230
226
|
return changed;
|
|
@@ -340,6 +336,16 @@ export function buildShellBarModel(
|
|
|
340
336
|
};
|
|
341
337
|
}
|
|
342
338
|
|
|
339
|
+
// Gauge-specific theme roles (issue #2222): resolved from the installed theme
|
|
340
|
+
// source and memoized by gauge-theme.ts, so the render hot path only stats the
|
|
341
|
+
// theme file. Undefined — and therefore today's shared roles — whenever the theme
|
|
342
|
+
// source is unavailable.
|
|
343
|
+
function gaugePaint(ctx: ExtensionContext): GaugePaint | undefined {
|
|
344
|
+
const themeName = ctx.ui.theme.name;
|
|
345
|
+
const source = ctx.ui.theme.sourcePath ?? ctx.ui.getAllThemes?.().find((item) => item?.name === themeName)?.path;
|
|
346
|
+
return gaugePaintFor(typeof source === "string" ? source : undefined);
|
|
347
|
+
}
|
|
348
|
+
|
|
343
349
|
export function createShellBarComponent(
|
|
344
350
|
pi: ExtensionAPI,
|
|
345
351
|
ctx: ExtensionContext,
|
|
@@ -356,7 +362,7 @@ export function createShellBarComponent(
|
|
|
356
362
|
});
|
|
357
363
|
return {
|
|
358
364
|
render(width: number) {
|
|
359
|
-
return renderShellBar(buildShellBarModel(pi, ctx, footerData, { dirty: dirty(), usage: usage() }), theme, width, presentation?.());
|
|
365
|
+
return renderShellBar(buildShellBarModel(pi, ctx, footerData, { dirty: dirty(), usage: usage() }), theme, width, presentation?.(), gaugePaint(ctx));
|
|
360
366
|
},
|
|
361
367
|
invalidate() {},
|
|
362
368
|
dispose() {
|
|
@@ -1229,8 +1235,6 @@ const CHANGES_SHORTCUT_DEFAULT = "alt+g";
|
|
|
1229
1235
|
const CHANGES_POLL_DEFAULT_MS = 2000;
|
|
1230
1236
|
const GIT_TIMEOUT_MS = 5000;
|
|
1231
1237
|
const COMMANDS_COMMAND_NAME = "gentle:commands";
|
|
1232
|
-
const OVERLAY_HEIGHT_RATIO = 0.8;
|
|
1233
|
-
const OVERLAY_MIN_ROWS = 8;
|
|
1234
1238
|
|
|
1235
1239
|
export function shellGitRunner(cwd: string, env: NodeJS.ProcessEnv = process.env, run: typeof execFile = execFile, maxBuffer = Infinity): GitRunner {
|
|
1236
1240
|
// Pi exec cannot replace the inherited environment. Use argv directly and
|
|
@@ -1335,6 +1339,8 @@ interface OverlayDeps {
|
|
|
1335
1339
|
}
|
|
1336
1340
|
|
|
1337
1341
|
// The overlay polls each root's Git state while it is open; diffs load lazily.
|
|
1342
|
+
// Like Gentle Agents it takes the whole terminal, and the native fullscreen
|
|
1343
|
+
// wrapper keeps mouse dispatch on the view while it owns the keyboard.
|
|
1338
1344
|
async function showChangesOverlay(ctx: ExtensionContext, deps: OverlayDeps): Promise<void> {
|
|
1339
1345
|
let host: ExternalEditorHost | undefined;
|
|
1340
1346
|
let view: WorktreeChangesView | undefined;
|
|
@@ -1352,16 +1358,18 @@ async function showChangesOverlay(ctx: ExtensionContext, deps: OverlayDeps): Pro
|
|
|
1352
1358
|
host = tui;
|
|
1353
1359
|
view = new WorktreeChangesView(deps.worktrees(), {
|
|
1354
1360
|
theme,
|
|
1355
|
-
rows: () => Math.max(
|
|
1361
|
+
rows: () => Math.max(0, tui.terminal.rows),
|
|
1356
1362
|
loadDiff: deps.loadDiff,
|
|
1357
1363
|
onOpen: (root, file) => close({ root, file }),
|
|
1358
1364
|
onRefresh: () => void refresh().catch(() => {}),
|
|
1359
1365
|
onClose: () => close(null),
|
|
1360
1366
|
requestRender: () => tui.requestRender(),
|
|
1361
1367
|
});
|
|
1362
|
-
|
|
1368
|
+
const interaction = createNativeFullscreenInteraction({ keyboardTarget: view, requestRender: () => tui.requestRender() });
|
|
1369
|
+
interaction.addChild(view);
|
|
1370
|
+
return interaction;
|
|
1363
1371
|
},
|
|
1364
|
-
{ overlay: true, overlayOptions: { width: "
|
|
1372
|
+
{ overlay: true, overlayOptions: { width: "100%", maxHeight: "100%", margin: 0, anchor: "center" } },
|
|
1365
1373
|
);
|
|
1366
1374
|
if (!chosen || !host) return;
|
|
1367
1375
|
if (!openInExternalEditor(host, chosen.file.path, process.env, spawnSync, chosen.root)) ctx.ui.notify("No editor configured. Set $VISUAL or $EDITOR.", "warning");
|
|
@@ -1578,19 +1586,20 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
1578
1586
|
// store and the profile reader cannot drift onto two different stores.
|
|
1579
1587
|
const usageConfigHome = gentlePiConfigHome(env);
|
|
1580
1588
|
const usageFetchTimeout = usageFetchTimeoutMs(env);
|
|
1581
|
-
// The subagent routing in force for this session
|
|
1582
|
-
// (gentle-shell#1064
|
|
1583
|
-
// profile
|
|
1584
|
-
//
|
|
1589
|
+
// The subagent routing in force for this session, through the same single
|
|
1590
|
+
// rule launches use (gentle-shell#1064): explicit Enter binding, then the
|
|
1591
|
+
// profile frozen at startup, then the live p → P → G only in follow mode.
|
|
1592
|
+
// Only the profile's own role entries count; the reserved orchestrator key
|
|
1593
|
+
// is not a route.
|
|
1585
1594
|
const activeRoutingModels = (ctx: ExtensionContext): Array<string | undefined> => {
|
|
1586
|
-
const
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
return
|
|
1595
|
+
const config = sessionProfileModelProfiles(resolveSessionProfile({
|
|
1596
|
+
sessionId: ctx.sessionManager?.getSessionId?.(),
|
|
1597
|
+
cwd: ctx.cwd,
|
|
1598
|
+
configHome: usageConfigHome,
|
|
1599
|
+
resolveWorktree: deps.resolveWorktree,
|
|
1600
|
+
env,
|
|
1601
|
+
}));
|
|
1602
|
+
return config ? profileRoleEntries(config).map(([, entry]) => entry.model) : [];
|
|
1594
1603
|
};
|
|
1595
1604
|
// A bare model id names a provider only when exactly one provider in the
|
|
1596
1605
|
// registry carries that id; anything else stays untargeted rather than guessed.
|
|
@@ -1743,6 +1752,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
1743
1752
|
onClose: () => withOverlayRepaint(tui, done)(null),
|
|
1744
1753
|
requestRender: () => tui.requestRender(),
|
|
1745
1754
|
scope: () => ({ providers: usageScope, failed: new Set(usageFailures) }),
|
|
1755
|
+
gauge: () => gaugePaint(ctx),
|
|
1746
1756
|
});
|
|
1747
1757
|
// Open promptly: the panel draws whatever the store already holds
|
|
1748
1758
|
// while the forced refresh runs underneath it, and repaints when
|
|
@@ -1929,7 +1939,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
1929
1939
|
const statusOwner = () => narrowStatusOwner({ mode: (tui as TUI & { mode?: string }).mode, columns: tui.terminal?.columns ?? 0, statusPlacement: visualSettings.statusPlacement, headerPlacement: visualSettings.headerPlacement });
|
|
1930
1940
|
const statusCardVisible = () => Boolean(tui.terminal && tui.terminal.columns >= SIDEBAR_BREAKPOINT && sidebarState(tui).ownsHost?.() && visualSettings.statusPlacement !== "hidden");
|
|
1931
1941
|
const belowFloat = (width: number, statuses: boolean) => (tui as TUI & { mode?: string }).mode === "fullscreen"
|
|
1932
|
-
? renderShellBelowInputFloat({ ...footerModel(), ...(statuses ? {} : { statuses: [] }), ...(statusCardVisible() ? { jobs: undefined } : {}) }, theme, width, usageShortcutKey, visualSettings, tracker.model)
|
|
1942
|
+
? renderShellBelowInputFloat({ ...footerModel(), ...(statuses ? {} : { statuses: [] }), ...(statusCardVisible() ? { jobs: undefined } : {}) }, theme, width, usageShortcutKey, visualSettings, tracker.model, gaugePaint(ctx))
|
|
1933
1943
|
: undefined;
|
|
1934
1944
|
// Match sidebarPart's live paint ownership, including an unavailable rail.
|
|
1935
1945
|
const footerSuppressed = () => {
|
|
@@ -1940,7 +1950,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
1940
1950
|
groupedChangesOwner = (width) => belowFloat(width, !footerSuppressed()) !== undefined;
|
|
1941
1951
|
const bottomBar = {
|
|
1942
1952
|
...bottom,
|
|
1943
|
-
render: (width: number) => belowFloat(width, true)?.rows ?? (statusOwner() === STATUS_OWNER.BOTTOM ? renderShellBottomOnlyBar(footerModel(), theme, width, usageShortcutKey, visualSettings) : bottom.render(width)),
|
|
1953
|
+
render: (width: number) => belowFloat(width, true)?.rows ?? (statusOwner() === STATUS_OWNER.BOTTOM ? renderShellBottomOnlyBar(footerModel(), theme, width, usageShortcutKey, visualSettings, undefined, gaugePaint(ctx)) : bottom.render(width)),
|
|
1944
1954
|
handleMouse(event: Parameters<NonNullable<SidebarRail["handleMouse"]>>[0]) {
|
|
1945
1955
|
if (footerSuppressed() || event.type !== "click" || event.button !== "left") return undefined;
|
|
1946
1956
|
const chrome = belowFloat(event.width, true);
|
|
@@ -1957,7 +1967,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
1957
1967
|
// The header row carries everything that ticks every frame (model,
|
|
1958
1968
|
// effort, context, cost, usage) plus session identity and the jobs count
|
|
1959
1969
|
// when Status is absent. Opaque statuses and working state stay excluded.
|
|
1960
|
-
const headerBar = (width: number) => renderShellHeaderChrome(buildShellHeaderModel(footerModel(), !statusCardVisible() && (statusOwner() === STATUS_OWNER.HEADER || visualSettings.statusPlacement === "hidden")), theme, width, usageShortcutKey, visualSettings);
|
|
1970
|
+
const headerBar = (width: number) => renderShellHeaderChrome(buildShellHeaderModel(footerModel(), !statusCardVisible() && (statusOwner() === STATUS_OWNER.HEADER || visualSettings.statusPlacement === "hidden")), theme, width, usageShortcutKey, visualSettings, gaugePaint(ctx));
|
|
1961
1971
|
const disposeHeader = sidebarHeader(tui, {
|
|
1962
1972
|
digest: () => JSON.stringify([footerModel(), tracker.model, visualSettings, cardStyle()]),
|
|
1963
1973
|
render: (width) => headerBar(width).rows,
|
|
@@ -2261,7 +2271,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
2261
2271
|
});
|
|
2262
2272
|
for (const mode of ["normal", "auto", "yolo"] as const) rows.push({
|
|
2263
2273
|
category,
|
|
2264
|
-
label: () => `Session permissions: ${mode.toUpperCase()}${permissionDisplay === mode ? " (current)" : ""}`,
|
|
2274
|
+
label: () => `Session permissions: ${mode.toUpperCase()}${mode === "auto" ? " (beta)" : ""}${permissionDisplay === mode ? " (current)" : ""}`,
|
|
2265
2275
|
preview: () => ({ title: "Permissions · current session", sample: mode === "auto"
|
|
2266
2276
|
? "independent session-model action checks · extra inference cost · hard safety and native consent remain"
|
|
2267
2277
|
: mode === "yolo" ? "ordinary scoped delivery permission · destructive confirmations remain" : "normal checks · overrides an elevated global default" }),
|
|
@@ -2273,7 +2283,7 @@ export default function gentleShell(pi: ExtensionAPI, env: NodeJS.ProcessEnv = p
|
|
|
2273
2283
|
});
|
|
2274
2284
|
for (const mode of ["normal", "auto", "yolo"] as const) rows.push({
|
|
2275
2285
|
category,
|
|
2276
|
-
label: () => `Default permissions: ${mode.toUpperCase()}${permissionDefault === mode ? " (saved)" : ""}`,
|
|
2286
|
+
label: () => `Default permissions: ${mode.toUpperCase()}${mode === "auto" ? " (beta)" : ""}${permissionDefault === mode ? " (saved)" : ""}`,
|
|
2277
2287
|
preview: () => ({ title: "Permissions · user-global default", sample: `New primary sessions start in ${mode.toUpperCase()}; current session stays unchanged. ${mode === "auto" ? "Additional classifier inference uses the session model; usage is separate." : "Independent safety and consent remain."}` }),
|
|
2278
2288
|
action: async () => {
|
|
2279
2289
|
if (closed) return;
|
|
@@ -13,9 +13,13 @@ import {
|
|
|
13
13
|
staleTurns,
|
|
14
14
|
TODO_DETAILS_KEY,
|
|
15
15
|
TODO_GLYPH,
|
|
16
|
+
TODO_PROGRESS_EVENT,
|
|
16
17
|
TODO_TOOL_NAME,
|
|
17
18
|
todoCardTone,
|
|
19
|
+
TODO_CLOSED_STATE,
|
|
20
|
+
todoProgress,
|
|
18
21
|
todoPromptBlock,
|
|
22
|
+
todoStateMessage,
|
|
19
23
|
todoSummary,
|
|
20
24
|
type TodoParams,
|
|
21
25
|
type TodoState,
|
|
@@ -24,10 +28,13 @@ import {
|
|
|
24
28
|
// Gentle Todo: the task list the model keeps while it works, drawn as a
|
|
25
29
|
// Gentle Shell card above the editor. Three things keep it current that a
|
|
26
30
|
// static tool description cannot: `write` replaces the whole list in one
|
|
27
|
-
// call, each run's system prompt carries
|
|
28
|
-
//
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
+
// call, each run's system prompt carries a byte-stable rules block while the
|
|
32
|
+
// open tasks reach the model as a hidden transcript message appended when the
|
|
33
|
+
// list changes (so list changes never invalidate the cached prompt prefix and
|
|
34
|
+
// requests stay append-only, gentle-shell#1662, #2195), and
|
|
35
|
+
// a list that goes untouched while tasks stay open is marked stale for the
|
|
36
|
+
// human. Long runs also receive one request-local reminder after several
|
|
37
|
+
// tool-use turns, without waking the agent or changing tasks.
|
|
31
38
|
|
|
32
39
|
const WIDGET_KEY = "gentle-todo";
|
|
33
40
|
const STATUS_ENUM = ["pending", "in_progress", "blocked", "done", "dropped"];
|
|
@@ -84,6 +91,10 @@ interface TodoSession {
|
|
|
84
91
|
collapsed: boolean;
|
|
85
92
|
/** A finished list stays on screen for the turn it finished in, then clears. */
|
|
86
93
|
clearOnNextTurn: boolean;
|
|
94
|
+
/** The last state snapshot sent to the transcript. */
|
|
95
|
+
lastSent: string | undefined;
|
|
96
|
+
/** A snapshot queued during the current turn; Pi appends it at turn_end. */
|
|
97
|
+
pending: string | undefined;
|
|
87
98
|
ui: ExtensionContext["ui"] | undefined;
|
|
88
99
|
host: { requestRender(): void } | undefined;
|
|
89
100
|
tui: TUI | undefined;
|
|
@@ -104,12 +115,21 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
104
115
|
const key = sessionKey(ctx);
|
|
105
116
|
let current = sessions.get(key);
|
|
106
117
|
if (!current) {
|
|
107
|
-
current = { state: emptyTodo(), turn: 0, toolTurnsSinceWrite: 0, reminded: false, wroteThisTurn: false, collapsed: false, clearOnNextTurn: false, ui: undefined, host: undefined, tui: undefined };
|
|
118
|
+
current = { state: emptyTodo(), turn: 0, toolTurnsSinceWrite: 0, reminded: false, wroteThisTurn: false, collapsed: false, clearOnNextTurn: false, lastSent: undefined, pending: undefined, ui: undefined, host: undefined, tui: undefined };
|
|
108
119
|
sessions.set(key, current);
|
|
109
120
|
}
|
|
110
121
|
return current;
|
|
111
122
|
};
|
|
112
123
|
|
|
124
|
+
// While the agent streams, Pi appends this hidden message at turn_end, after
|
|
125
|
+
// the tool results and before the next model request; it never starts a turn.
|
|
126
|
+
const persistState = (current: TodoSession, state: string) => {
|
|
127
|
+
if (!pi.sendMessage) return;
|
|
128
|
+
pi.sendMessage({ customType: "gentle-todo-state", content: state, display: false }, { triggerTurn: false });
|
|
129
|
+
current.lastSent = state;
|
|
130
|
+
current.pending = state;
|
|
131
|
+
};
|
|
132
|
+
|
|
113
133
|
const toggle = (current: TodoSession) => {
|
|
114
134
|
current.collapsed = !current.collapsed;
|
|
115
135
|
if (current.tui) invalidateSidebar(current.tui);
|
|
@@ -262,6 +282,11 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
262
282
|
current.toolTurnsSinceWrite = 0;
|
|
263
283
|
current.reminded = false;
|
|
264
284
|
current.wroteThisTurn = true;
|
|
285
|
+
// A closed list persists the closing marker, so the last open
|
|
286
|
+
// snapshot in the transcript never reads as current work.
|
|
287
|
+
const state = todoStateMessage(current.state) ?? (current.lastSent === undefined ? undefined : TODO_CLOSED_STATE);
|
|
288
|
+
if (state !== undefined && state !== current.lastSent) persistState(current, state);
|
|
289
|
+
pi.events?.emit(TODO_PROGRESS_EVENT, todoProgress(current.state, ctx.sessionManager.getSessionId()));
|
|
265
290
|
}
|
|
266
291
|
if (current.tui) invalidateSidebar(current.tui);
|
|
267
292
|
}
|
|
@@ -281,7 +306,9 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
281
306
|
});
|
|
282
307
|
}
|
|
283
308
|
|
|
284
|
-
|
|
309
|
+
// Pi binds ctrl+shift+up/down to prompt navigation (tui.altScreen.*Prompt) and
|
|
310
|
+
// alt+up/down to dequeue and model reordering; alt+shift+up/down are free.
|
|
311
|
+
for (const [key, lines] of [["alt+shift+up", -3], ["alt+shift+down", 3]] as const) {
|
|
285
312
|
pi.registerShortcut(key, {
|
|
286
313
|
description: `Scroll the Todo list ${lines < 0 ? "up" : "down"}`,
|
|
287
314
|
handler: async (ctx) => session(ctx).scrollTodo?.(lines),
|
|
@@ -298,6 +325,8 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
298
325
|
current.toolTurnsSinceWrite = 0;
|
|
299
326
|
current.reminded = false;
|
|
300
327
|
current.wroteThisTurn = false;
|
|
328
|
+
current.lastSent = undefined;
|
|
329
|
+
current.pending = undefined;
|
|
301
330
|
current.ui = ctx.hasUI ? ctx.ui : undefined;
|
|
302
331
|
show(current);
|
|
303
332
|
});
|
|
@@ -315,11 +344,10 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
315
344
|
current.clearOnNextTurn = false;
|
|
316
345
|
show(current);
|
|
317
346
|
}
|
|
318
|
-
const block = todoPromptBlock(current.state, staleTurns(current.state, current.turn));
|
|
319
|
-
if (!block) return undefined;
|
|
320
347
|
// gentle-shell#1485: pi-claude-bridge drops a handler-returned
|
|
321
|
-
// systemPrompt, so the
|
|
322
|
-
|
|
348
|
+
// systemPrompt, so the rules block goes through appendSystemPrompt. It is
|
|
349
|
+
// the same bytes on every turn, list or no list (gentle-shell#1662).
|
|
350
|
+
appendSystemPromptOnce(event.systemPromptOptions, todoPromptBlock());
|
|
323
351
|
return undefined;
|
|
324
352
|
});
|
|
325
353
|
|
|
@@ -331,18 +359,34 @@ export default function gentleTodo(pi: ExtensionAPI, env: NodeJS.ProcessEnv = pr
|
|
|
331
359
|
current.toolTurnsSinceWrite += 1;
|
|
332
360
|
}
|
|
333
361
|
current.wroteThisTurn = false;
|
|
362
|
+
// Pi flushes the queued snapshot right after this event.
|
|
363
|
+
current.pending = undefined;
|
|
334
364
|
});
|
|
335
365
|
|
|
336
366
|
pi.on("context", (event, ctx) => {
|
|
337
367
|
const current = session(ctx);
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
//
|
|
342
|
-
//
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
};
|
|
368
|
+
// gentle-shell#1662, #2195: providers cache the request prefix up to the
|
|
369
|
+
// last message (Anthropic) or send only the delta after the previous input
|
|
370
|
+
// (openai-codex), so a trailing message that the next request drops breaks
|
|
371
|
+
// both. The list is persisted when it changes; this transform only covers a
|
|
372
|
+
// transcript that lacks the current snapshot (compaction, branch navigation,
|
|
373
|
+
// sessions recorded earlier): it trails this one request and persists the
|
|
374
|
+
// snapshot once, so the following requests are append-only again.
|
|
375
|
+
const trailing: Array<{ role: "custom"; customType: string; content: string; display: false; timestamp: number }> = [];
|
|
376
|
+
const last = [...event.messages].reverse().find((message) => (message as { customType?: string }).customType === "gentle-todo-state") as { content?: unknown } | undefined;
|
|
377
|
+
const seen = typeof last?.content === "string" ? last.content : undefined;
|
|
378
|
+
const state = todoStateMessage(current.state) ?? (seen === undefined || seen === TODO_CLOSED_STATE ? undefined : TODO_CLOSED_STATE);
|
|
379
|
+
if (state !== undefined && seen !== state) {
|
|
380
|
+
trailing.push({ role: "custom", customType: "gentle-todo-state", content: state, display: false, timestamp: Date.now() });
|
|
381
|
+
if (current.pending !== state) persistState(current, state);
|
|
382
|
+
}
|
|
383
|
+
const actionable = current.state.tasks.some((task) => task.status === "pending" || task.status === "in_progress");
|
|
384
|
+
if (!current.reminded && current.toolTurnsSinceWrite >= REMIND_AFTER_TOOL_TURNS && actionable) {
|
|
385
|
+
current.reminded = true;
|
|
386
|
+
trailing.push({ role: "custom", customType: "gentle-todo-reminder", content: TODO_REMINDER, display: false, timestamp: Date.now() });
|
|
387
|
+
}
|
|
388
|
+
if (trailing.length === 0) return undefined;
|
|
389
|
+
return { messages: [...event.messages, ...trailing] };
|
|
346
390
|
});
|
|
347
391
|
|
|
348
392
|
pi.on("tool_execution_end", (event, ctx) => {
|
|
@@ -795,7 +795,7 @@ export function createQuietToolRenderer(
|
|
|
795
795
|
safeResult,
|
|
796
796
|
options,
|
|
797
797
|
theme,
|
|
798
|
-
sanitizedRenderContext(renderContext) as any,
|
|
798
|
+
{ ...sanitizedRenderContext(renderContext), lastComponent: undefined } as any,
|
|
799
799
|
), false);
|
|
800
800
|
}
|
|
801
801
|
let output = formatToolResultOutput(toolName, safeResult, {
|