@oh-my-pi/pi-coding-agent 16.0.4 → 16.0.6
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 +94 -0
- package/dist/cli.js +2027 -1396
- package/dist/types/advisor/advise-tool.d.ts +31 -19
- package/dist/types/autoresearch/tools/init-experiment.d.ts +13 -17
- package/dist/types/autoresearch/tools/log-experiment.d.ts +17 -19
- package/dist/types/autoresearch/tools/run-experiment.d.ts +3 -4
- package/dist/types/autoresearch/tools/update-notes.d.ts +4 -5
- package/dist/types/cli/args.d.ts +1 -0
- package/dist/types/cli/bench-cli.d.ts +6 -0
- package/dist/types/cli/ttsr-cli.d.ts +39 -0
- package/dist/types/commands/launch.d.ts +3 -0
- package/dist/types/commands/ttsr.d.ts +57 -0
- package/dist/types/commit/agentic/tools/analyze-file.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-file-diff.d.ts +4 -5
- package/dist/types/commit/agentic/tools/git-hunk.d.ts +5 -6
- package/dist/types/commit/agentic/tools/git-overview.d.ts +4 -5
- package/dist/types/commit/agentic/tools/propose-changelog.d.ts +23 -24
- package/dist/types/commit/agentic/tools/propose-commit.d.ts +11 -32
- package/dist/types/commit/agentic/tools/recent-commits.d.ts +3 -4
- package/dist/types/commit/agentic/tools/schemas.d.ts +6 -27
- package/dist/types/commit/agentic/tools/split-commit.d.ts +28 -49
- package/dist/types/commit/changelog/generate.d.ts +12 -13
- package/dist/types/commit/shared-llm.d.ts +10 -37
- package/dist/types/config/config-file.d.ts +4 -4
- package/dist/types/config/keybindings.d.ts +5 -0
- package/dist/types/config/models-config-schema.d.ts +625 -990
- package/dist/types/config/models-config.d.ts +229 -217
- package/dist/types/config/settings-schema.d.ts +144 -25
- package/dist/types/edit/hashline/params.d.ts +7 -11
- package/dist/types/edit/index.d.ts +2 -1
- package/dist/types/edit/modes/apply-patch.d.ts +4 -5
- package/dist/types/edit/modes/patch.d.ts +15 -24
- package/dist/types/edit/modes/replace.d.ts +16 -17
- package/dist/types/eval/js/index.d.ts +1 -0
- package/dist/types/extensibility/custom-commands/types.d.ts +6 -3
- package/dist/types/extensibility/custom-tools/types.d.ts +8 -5
- package/dist/types/extensibility/extensions/runner.d.ts +5 -2
- package/dist/types/extensibility/extensions/types.d.ts +14 -10
- package/dist/types/extensibility/hooks/types.d.ts +7 -4
- package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +13 -5
- package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +17 -0
- package/dist/types/extensibility/shared-events.d.ts +22 -1
- package/dist/types/extensibility/typebox.d.ts +80 -58
- package/dist/types/goals/tools/goal-tool.d.ts +11 -24
- package/dist/types/index.d.ts +2 -0
- package/dist/types/lsp/index.d.ts +11 -26
- package/dist/types/lsp/types.d.ts +12 -28
- package/dist/types/main.d.ts +1 -0
- package/dist/types/mcp/client.d.ts +8 -0
- package/dist/types/modes/components/btw-panel.d.ts +1 -0
- package/dist/types/modes/components/custom-editor.d.ts +3 -1
- package/dist/types/modes/components/status-line/component.d.ts +1 -1
- package/dist/types/modes/components/status-line/context-thresholds.d.ts +0 -1
- package/dist/types/modes/controllers/btw-controller.d.ts +2 -0
- package/dist/types/modes/controllers/input-controller.d.ts +1 -0
- package/dist/types/modes/interactive-mode.d.ts +3 -0
- package/dist/types/modes/rpc/rpc-types.d.ts +1 -1
- package/dist/types/modes/setup-wizard/index.d.ts +1 -0
- package/dist/types/modes/setup-wizard/startup-splash.d.ts +7 -0
- package/dist/types/modes/theme/theme.d.ts +1 -1
- package/dist/types/modes/types.d.ts +3 -0
- package/dist/types/modes/utils/context-usage.d.ts +12 -0
- package/dist/types/sdk.d.ts +8 -1
- package/dist/types/session/agent-session.d.ts +24 -0
- package/dist/types/session/session-persistence.d.ts +4 -0
- package/dist/types/startup-splash.d.ts +12 -0
- package/dist/types/task/types.d.ts +47 -48
- package/dist/types/tools/ask.d.ts +26 -27
- package/dist/types/tools/ast-edit.d.ts +17 -17
- package/dist/types/tools/ast-grep.d.ts +12 -13
- package/dist/types/tools/bash.d.ts +20 -17
- package/dist/types/tools/browser.d.ts +46 -71
- package/dist/types/tools/checkpoint.d.ts +14 -15
- package/dist/types/tools/debug.d.ts +82 -145
- package/dist/types/tools/eval.d.ts +30 -40
- package/dist/types/tools/find.d.ts +17 -18
- package/dist/types/tools/gh.d.ts +49 -78
- package/dist/types/tools/image-gen.d.ts +20 -36
- package/dist/types/tools/inspect-image.d.ts +10 -11
- package/dist/types/tools/irc.d.ts +22 -33
- package/dist/types/tools/job.d.ts +11 -12
- package/dist/types/tools/learn.d.ts +21 -28
- package/dist/types/tools/manage-skill.d.ts +13 -22
- package/dist/types/tools/memory-edit.d.ts +15 -24
- package/dist/types/tools/memory-recall.d.ts +7 -8
- package/dist/types/tools/memory-reflect.d.ts +9 -10
- package/dist/types/tools/memory-retain.d.ts +13 -14
- package/dist/types/tools/read.d.ts +8 -8
- package/dist/types/tools/resolve.d.ts +11 -18
- package/dist/types/tools/review.d.ts +9 -15
- package/dist/types/tools/search-tool-bm25.d.ts +9 -10
- package/dist/types/tools/search.d.ts +16 -17
- package/dist/types/tools/ssh.d.ts +14 -15
- package/dist/types/tools/todo.d.ts +27 -43
- package/dist/types/tools/tts.d.ts +8 -9
- package/dist/types/tools/write.d.ts +9 -10
- package/dist/types/tui/code-cell.d.ts +2 -0
- package/dist/types/tui/index.d.ts +1 -0
- package/dist/types/tui/width-aware-text.d.ts +23 -0
- package/dist/types/utils/image-vision-fallback.d.ts +28 -0
- package/dist/types/utils/markit.d.ts +10 -1
- package/dist/types/web/search/index.d.ts +17 -28
- package/dist/types/web/search/providers/base.d.ts +1 -0
- package/dist/types/web/search/providers/gemini.d.ts +1 -0
- package/dist/types/web/search/providers/perplexity.d.ts +0 -2
- package/dist/types/web/search/types.d.ts +32 -26
- package/package.json +14 -13
- package/scripts/omp +1 -1
- package/src/advisor/__tests__/advisor.test.ts +103 -1
- package/src/advisor/advise-tool.ts +47 -11
- package/src/autoresearch/tools/init-experiment.ts +13 -16
- package/src/autoresearch/tools/log-experiment.ts +15 -18
- package/src/autoresearch/tools/run-experiment.ts +3 -3
- package/src/autoresearch/tools/update-notes.ts +4 -4
- package/src/cli/args.ts +1 -0
- package/src/cli/bench-cli.ts +30 -7
- package/src/cli/flag-tables.ts +8 -0
- package/src/cli/ttsr-cli.ts +995 -0
- package/src/cli-commands.ts +1 -0
- package/src/cli.ts +7 -1
- package/src/collab/host.ts +2 -2
- package/src/commands/launch.ts +3 -0
- package/src/commands/ttsr.ts +125 -0
- package/src/commit/agentic/tools/analyze-file.ts +4 -4
- package/src/commit/agentic/tools/git-file-diff.ts +4 -4
- package/src/commit/agentic/tools/git-hunk.ts +7 -5
- package/src/commit/agentic/tools/git-overview.ts +4 -4
- package/src/commit/agentic/tools/propose-changelog.ts +18 -15
- package/src/commit/agentic/tools/propose-commit.ts +6 -6
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/schemas.ts +8 -20
- package/src/commit/agentic/tools/split-commit.ts +19 -23
- package/src/commit/analysis/summary.ts +7 -5
- package/src/commit/changelog/generate.ts +15 -11
- package/src/commit/shared-llm.ts +17 -24
- package/src/config/config-file.ts +13 -15
- package/src/config/keybindings.ts +6 -0
- package/src/config/models-config-schema.ts +206 -179
- package/src/config/settings-schema.ts +118 -2
- package/src/discovery/builtin-rules/index.ts +2 -0
- package/src/discovery/builtin-rules/ts-import-type.md +2 -2
- package/src/discovery/builtin-rules/ts-no-any.md +11 -2
- package/src/discovery/builtin-rules/ts-no-inline-cast-access.md +55 -0
- package/src/edit/hashline/params.ts +12 -11
- package/src/edit/index.ts +5 -4
- package/src/edit/modes/apply-patch.ts +4 -4
- package/src/edit/modes/patch.ts +15 -18
- package/src/edit/modes/replace.ts +13 -17
- package/src/edit/renderer.ts +0 -1
- package/src/eval/agent-bridge.ts +11 -13
- package/src/eval/completion-bridge.ts +25 -17
- package/src/eval/js/context-manager.ts +17 -2
- package/src/eval/js/index.ts +1 -1
- package/src/eval/py/executor.ts +2 -2
- package/src/eval/py/runner.py +44 -0
- package/src/extensibility/custom-commands/loader.ts +5 -3
- package/src/extensibility/custom-commands/types.ts +6 -3
- package/src/extensibility/custom-tools/loader.ts +4 -2
- package/src/extensibility/custom-tools/types.ts +8 -5
- package/src/extensibility/extensions/loader.ts +4 -2
- package/src/extensibility/extensions/runner.ts +20 -2
- package/src/extensibility/extensions/types.ts +22 -8
- package/src/extensibility/hooks/loader.ts +5 -2
- package/src/extensibility/hooks/types.ts +7 -4
- package/src/extensibility/legacy-pi-ai-shim.ts +42 -5
- package/src/extensibility/legacy-pi-coding-agent-shim.ts +113 -0
- package/src/extensibility/plugins/legacy-pi-compat.ts +13 -13
- package/src/extensibility/shared-events.ts +24 -0
- package/src/extensibility/tool-proxy.ts +4 -1
- package/src/extensibility/typebox.ts +778 -251
- package/src/goals/guided-setup.ts +12 -3
- package/src/goals/tools/goal-tool.ts +6 -6
- package/src/index.ts +2 -0
- package/src/internal-urls/docs-index.generated.ts +15 -13
- package/src/lsp/types.ts +13 -27
- package/src/main.ts +29 -21
- package/src/mcp/client.ts +38 -13
- package/src/mcp/render.ts +102 -89
- package/src/modes/components/agent-hub.ts +11 -4
- package/src/modes/components/branch-summary-message.ts +1 -0
- package/src/modes/components/btw-panel.ts +5 -1
- package/src/modes/components/collab-prompt-message.ts +9 -7
- package/src/modes/components/compaction-summary-message.ts +1 -0
- package/src/modes/components/custom-editor.ts +18 -0
- package/src/modes/components/custom-message.ts +1 -0
- package/src/modes/components/footer.ts +6 -5
- package/src/modes/components/hook-message.ts +1 -0
- package/src/modes/components/read-tool-group.ts +9 -3
- package/src/modes/components/skill-message.ts +1 -0
- package/src/modes/components/status-line/component.ts +139 -15
- package/src/modes/components/status-line/context-thresholds.ts +0 -1
- package/src/modes/components/todo-reminder.ts +1 -0
- package/src/modes/components/tool-execution.ts +17 -10
- package/src/modes/components/ttsr-notification.ts +1 -0
- package/src/modes/components/user-message.ts +6 -6
- package/src/modes/controllers/btw-controller.ts +69 -1
- package/src/modes/controllers/event-controller.ts +2 -7
- package/src/modes/controllers/input-controller.ts +29 -0
- package/src/modes/controllers/selector-controller.ts +10 -3
- package/src/modes/interactive-mode.ts +42 -10
- package/src/modes/rpc/rpc-types.ts +1 -1
- package/src/modes/setup-wizard/index.ts +1 -0
- package/src/modes/setup-wizard/scenes/sign-in.ts +77 -5
- package/src/modes/setup-wizard/startup-splash.ts +107 -0
- package/src/modes/theme/theme.ts +133 -143
- package/src/modes/types.ts +3 -0
- package/src/modes/utils/context-usage.ts +37 -20
- package/src/modes/utils/hotkeys-markdown.ts +1 -0
- package/src/prompts/system/system-prompt.md +1 -0
- package/src/prompts/tools/image-attachment-describe-system.md +8 -0
- package/src/prompts/tools/image-attachment-describe.md +10 -0
- package/src/sdk.ts +35 -22
- package/src/session/agent-session.ts +715 -255
- package/src/session/session-history-format.ts +11 -2
- package/src/session/session-loader.ts +19 -32
- package/src/session/session-persistence.ts +27 -11
- package/src/session/snapcompact-inline.ts +1 -1
- package/src/slash-commands/builtin-registry.ts +4 -11
- package/src/ssh/connection-manager.ts +3 -2
- package/src/startup-splash.ts +19 -0
- package/src/task/executor.ts +12 -7
- package/src/task/types.ts +44 -41
- package/src/tool-discovery/tool-index.ts +17 -4
- package/src/tools/ask.ts +14 -14
- package/src/tools/ast-edit.ts +17 -14
- package/src/tools/ast-grep.ts +10 -9
- package/src/tools/bash.ts +15 -10
- package/src/tools/browser/launch.ts +13 -0
- package/src/tools/browser.ts +26 -32
- package/src/tools/checkpoint.ts +7 -7
- package/src/tools/debug.ts +72 -69
- package/src/tools/eval.ts +18 -19
- package/src/tools/find.ts +20 -13
- package/src/tools/gh.ts +29 -49
- package/src/tools/image-gen.ts +94 -57
- package/src/tools/inspect-image.ts +8 -9
- package/src/tools/irc.ts +12 -12
- package/src/tools/job.ts +6 -6
- package/src/tools/learn.ts +11 -14
- package/src/tools/manage-skill.ts +19 -23
- package/src/tools/memory-edit.ts +8 -8
- package/src/tools/memory-recall.ts +4 -4
- package/src/tools/memory-reflect.ts +5 -5
- package/src/tools/memory-retain.ts +9 -11
- package/src/tools/puppeteer/02_stealth_hairline.txt +1 -1
- package/src/tools/puppeteer/04_stealth_iframe.txt +4 -4
- package/src/tools/puppeteer/05_stealth_webgl.txt +1 -1
- package/src/tools/puppeteer/10_stealth_plugins.txt +6 -4
- package/src/tools/puppeteer/12_stealth_codecs.txt +2 -2
- package/src/tools/puppeteer/13_stealth_worker.txt +1 -1
- package/src/tools/read.ts +197 -19
- package/src/tools/report-tool-issue.ts +6 -6
- package/src/tools/resolve.ts +6 -6
- package/src/tools/review.ts +10 -12
- package/src/tools/search-tool-bm25.ts +5 -5
- package/src/tools/search.ts +20 -29
- package/src/tools/ssh.ts +8 -8
- package/src/tools/todo.ts +16 -19
- package/src/tools/tts.ts +16 -15
- package/src/tools/write.ts +5 -5
- package/src/tui/code-cell.ts +44 -3
- package/src/tui/index.ts +1 -0
- package/src/tui/width-aware-text.ts +58 -0
- package/src/utils/image-vision-fallback.ts +197 -0
- package/src/utils/markit.ts +17 -2
- package/src/web/search/index.ts +21 -9
- package/src/web/search/providers/base.ts +1 -0
- package/src/web/search/providers/gemini.ts +56 -18
- package/src/web/search/providers/perplexity.ts +373 -126
- package/src/web/search/types.ts +28 -48
package/src/lsp/types.ts
CHANGED
|
@@ -1,38 +1,24 @@
|
|
|
1
1
|
import type { ptree } from "@oh-my-pi/pi-utils";
|
|
2
|
-
import {
|
|
2
|
+
import { type } from "arktype";
|
|
3
3
|
|
|
4
4
|
// =============================================================================
|
|
5
5
|
// Tool Schema
|
|
6
6
|
// =============================================================================
|
|
7
7
|
|
|
8
|
-
export const lspSchema =
|
|
9
|
-
action:
|
|
10
|
-
"diagnostics",
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"implementation",
|
|
20
|
-
"status",
|
|
21
|
-
"reload",
|
|
22
|
-
"capabilities",
|
|
23
|
-
"request",
|
|
24
|
-
]),
|
|
25
|
-
file: z.string().describe("file path or source path for rename_file").optional(),
|
|
26
|
-
line: z.number().describe("line number (1-indexed)").optional(),
|
|
27
|
-
symbol: z.string().describe("symbol substring on the line").optional(),
|
|
28
|
-
query: z.string().describe("search query or code-action selector").optional(),
|
|
29
|
-
new_name: z.string().describe("new symbol name or destination path").optional(),
|
|
30
|
-
apply: z.boolean().describe("apply edits").optional(),
|
|
31
|
-
timeout: z.number().describe("request timeout in seconds").optional(),
|
|
32
|
-
payload: z.string().describe("json-encoded request params").optional(),
|
|
8
|
+
export const lspSchema = type({
|
|
9
|
+
action:
|
|
10
|
+
"'diagnostics' | 'definition' | 'references' | 'hover' | 'symbols' | 'rename' | 'rename_file' | 'code_actions' | 'type_definition' | 'implementation' | 'status' | 'reload' | 'capabilities' | 'request'",
|
|
11
|
+
file: "string?",
|
|
12
|
+
line: "number?",
|
|
13
|
+
symbol: "string?",
|
|
14
|
+
query: "string?",
|
|
15
|
+
new_name: "string?",
|
|
16
|
+
apply: "boolean?",
|
|
17
|
+
timeout: "number?",
|
|
18
|
+
payload: "string?",
|
|
33
19
|
});
|
|
34
20
|
|
|
35
|
-
export type LspParams =
|
|
21
|
+
export type LspParams = typeof lspSchema.infer;
|
|
36
22
|
|
|
37
23
|
export interface LspToolDetails {
|
|
38
24
|
serverName?: string;
|
package/src/main.ts
CHANGED
|
@@ -68,6 +68,7 @@ import type { AuthStorage } from "./session/auth-storage";
|
|
|
68
68
|
import { resolveResumableSession, type SessionInfo } from "./session/session-listing";
|
|
69
69
|
import { SessionManager } from "./session/session-manager";
|
|
70
70
|
import { executeBuiltinSlashCommand } from "./slash-commands/builtin-registry";
|
|
71
|
+
import { shouldShowStartupSplash } from "./startup-splash";
|
|
71
72
|
import { discoverTitleSystemPromptFile, resolvePromptInput } from "./system-prompt";
|
|
72
73
|
import { createPersistedSubagentReviverFactory } from "./task/persisted-revive";
|
|
73
74
|
import { initTelemetryExport, isTelemetryExportEnabled } from "./telemetry-export";
|
|
@@ -90,17 +91,8 @@ type RunRpcMode = (
|
|
|
90
91
|
eventBus?: EventBus,
|
|
91
92
|
) => Promise<never>;
|
|
92
93
|
|
|
93
|
-
function
|
|
94
|
-
|
|
95
|
-
resuming: boolean;
|
|
96
|
-
quiet: boolean;
|
|
97
|
-
version: string;
|
|
98
|
-
}): void {
|
|
99
|
-
if (!options.isInteractive) return;
|
|
100
|
-
if (options.resuming || options.quiet) return;
|
|
101
|
-
if ($env.PI_TIMING) return;
|
|
102
|
-
if (!process.stdin.isTTY || !process.stdout.isTTY) return;
|
|
103
|
-
//process.stdout.write(`${chalk.dim(`omp ${options.version}`)}\n${chalk.dim("Initializing session…")}\n`);
|
|
94
|
+
export function writeStartupNotice(parsedArgs: Pick<Args, "mode">, text: string): void {
|
|
95
|
+
(parsedArgs.mode === "json" ? process.stderr : process.stdout).write(text);
|
|
104
96
|
}
|
|
105
97
|
|
|
106
98
|
async function checkForNewVersion(currentVersion: string): Promise<string | undefined> {
|
|
@@ -387,6 +379,7 @@ async function runInteractiveMode(
|
|
|
387
379
|
mcpManager: MCPManager | undefined,
|
|
388
380
|
resuming: boolean,
|
|
389
381
|
forceSetupWizard: boolean,
|
|
382
|
+
showStartupSplash: boolean,
|
|
390
383
|
eventBus?: EventBus,
|
|
391
384
|
initialMessage?: string,
|
|
392
385
|
initialImages?: ImageContent[],
|
|
@@ -407,10 +400,13 @@ async function runInteractiveMode(
|
|
|
407
400
|
// Cold-launch gate: the full setup wizard (every scene + the overlay and
|
|
408
401
|
// their TUI/OAuth/search/theme deps) is heavy, yet the common case only needs
|
|
409
402
|
// to know whether the stored setup version is current. Lazy-load the wizard
|
|
410
|
-
// barrel only when setup is stale or
|
|
403
|
+
// barrel only when setup is stale, forced, or the explicit startup splash
|
|
404
|
+
// setting needs the shared setup splash renderer.
|
|
411
405
|
const storedSetupVersion = settings.get("setupVersion");
|
|
412
406
|
const setupWizard =
|
|
413
|
-
forceSetupWizard || storedSetupVersion < CURRENT_SETUP_VERSION
|
|
407
|
+
forceSetupWizard || storedSetupVersion < CURRENT_SETUP_VERSION || showStartupSplash
|
|
408
|
+
? await import("./modes/setup-wizard")
|
|
409
|
+
: undefined;
|
|
414
410
|
const setupScenes = setupWizard
|
|
415
411
|
? await setupWizard.selectSetupScenes(storedSetupVersion, setupWizard.ALL_SCENES, mode, {
|
|
416
412
|
resuming,
|
|
@@ -419,12 +415,17 @@ async function runInteractiveMode(
|
|
|
419
415
|
force: forceSetupWizard,
|
|
420
416
|
})
|
|
421
417
|
: [];
|
|
418
|
+
const playStartupSplash = showStartupSplash && setupScenes.length === 0;
|
|
422
419
|
|
|
423
420
|
await mode.init({
|
|
424
|
-
suppressWelcomeIntro: resuming || setupScenes.length > 0,
|
|
421
|
+
suppressWelcomeIntro: resuming || setupScenes.length > 0 || playStartupSplash,
|
|
425
422
|
clearInitialTerminalHistory: true,
|
|
426
423
|
});
|
|
427
424
|
|
|
425
|
+
if (setupWizard && playStartupSplash) {
|
|
426
|
+
await setupWizard.runStartupSplash(mode);
|
|
427
|
+
}
|
|
428
|
+
|
|
428
429
|
if (setupWizard && setupScenes.length > 0) {
|
|
429
430
|
await setupWizard.runSetupWizard(mode, setupScenes);
|
|
430
431
|
}
|
|
@@ -758,6 +759,9 @@ async function buildSessionOptions(
|
|
|
758
759
|
cwd: parsed.cwd ?? getProjectDir(),
|
|
759
760
|
autoApprove: parsed.autoApprove ?? false,
|
|
760
761
|
};
|
|
762
|
+
if (parsed.maxTime !== undefined) {
|
|
763
|
+
options.deadline = Date.now() + parsed.maxTime * 1000;
|
|
764
|
+
}
|
|
761
765
|
|
|
762
766
|
// Auto-discover SYSTEM.md if no CLI system prompt provided
|
|
763
767
|
const systemPromptSource = parsed.systemPrompt ?? discoverSystemPromptFile();
|
|
@@ -944,7 +948,7 @@ export async function runRootCommand(
|
|
|
944
948
|
const modelRegistry = logger.time("modelRegistry:init", () => new ModelRegistry(authStorage));
|
|
945
949
|
|
|
946
950
|
if (parsedArgs.version) {
|
|
947
|
-
|
|
951
|
+
writeStartupNotice(parsedArgs, `${VERSION}\n`);
|
|
948
952
|
process.exit(0);
|
|
949
953
|
}
|
|
950
954
|
|
|
@@ -959,7 +963,7 @@ export async function runRootCommand(
|
|
|
959
963
|
process.stderr.write(`${chalk.red(`Error: ${message}`)}\n`);
|
|
960
964
|
process.exit(1);
|
|
961
965
|
}
|
|
962
|
-
|
|
966
|
+
writeStartupNotice(parsedArgs, `Exported to: ${result}\n`);
|
|
963
967
|
process.exit(0);
|
|
964
968
|
}
|
|
965
969
|
|
|
@@ -1095,7 +1099,7 @@ export async function runRootCommand(
|
|
|
1095
1099
|
// message rather than letting the decline bubble up as an uncaught exception
|
|
1096
1100
|
// (see issue #1668).
|
|
1097
1101
|
if (typeof parsedArgs.resume === "string" && !sessionManager) {
|
|
1098
|
-
|
|
1102
|
+
writeStartupNotice(parsedArgs, `${chalk.dim("Resume cancelled: session is in another project.")}\n`);
|
|
1099
1103
|
return;
|
|
1100
1104
|
}
|
|
1101
1105
|
|
|
@@ -1109,7 +1113,7 @@ export async function runRootCommand(
|
|
|
1109
1113
|
// picker can still open in all-projects scope instead of dead-ending.
|
|
1110
1114
|
preloadedAllSessions = await logger.time("SessionManager.listAll", SessionManager.listAll);
|
|
1111
1115
|
if (preloadedAllSessions.length === 0) {
|
|
1112
|
-
|
|
1116
|
+
writeStartupNotice(parsedArgs, `${chalk.dim("No sessions found")}\n`);
|
|
1113
1117
|
return;
|
|
1114
1118
|
}
|
|
1115
1119
|
startInAllScope = true;
|
|
@@ -1121,7 +1125,7 @@ export async function runRootCommand(
|
|
|
1121
1125
|
});
|
|
1122
1126
|
resumeStartupWatchdog();
|
|
1123
1127
|
if (!selected) {
|
|
1124
|
-
|
|
1128
|
+
writeStartupNotice(parsedArgs, `${chalk.dim("No session selected")}\n`);
|
|
1125
1129
|
return;
|
|
1126
1130
|
}
|
|
1127
1131
|
// Resuming a session from another project: switch the process into that
|
|
@@ -1254,11 +1258,14 @@ export async function runRootCommand(
|
|
|
1254
1258
|
stdinContent: pipedInput,
|
|
1255
1259
|
});
|
|
1256
1260
|
|
|
1257
|
-
|
|
1261
|
+
const showStartupSplash = shouldShowStartupSplash({
|
|
1262
|
+
configured: settingsInstance.get("startup.showSplash"),
|
|
1258
1263
|
isInteractive,
|
|
1259
1264
|
resuming: Boolean(parsedArgs.continue || parsedArgs.resume || parsedArgs.fork),
|
|
1260
1265
|
quiet: settingsInstance.get("startup.quiet"),
|
|
1261
|
-
|
|
1266
|
+
timing: Boolean($env.PI_TIMING),
|
|
1267
|
+
stdinIsTTY: process.stdin.isTTY,
|
|
1268
|
+
stdoutIsTTY: process.stdout.isTTY,
|
|
1262
1269
|
});
|
|
1263
1270
|
|
|
1264
1271
|
const { session, setToolUIContext, modelFallbackMessage, lspServers, mcpManager } = await createSession({
|
|
@@ -1350,6 +1357,7 @@ export async function runRootCommand(
|
|
|
1350
1357
|
mcpManager,
|
|
1351
1358
|
Boolean(parsedArgs.continue || parsedArgs.resume || parsedArgs.fork),
|
|
1352
1359
|
deps.forceSetupWizard === true,
|
|
1360
|
+
showStartupSplash,
|
|
1353
1361
|
eventBus,
|
|
1354
1362
|
initialMessage,
|
|
1355
1363
|
initialImages,
|
package/src/mcp/client.ts
CHANGED
|
@@ -303,8 +303,22 @@ export async function listResources(
|
|
|
303
303
|
return allResources;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
/** True when an error is a JSON-RPC "method not found" (-32601) response. */
|
|
307
|
+
function isMethodNotFoundError(error: unknown): boolean {
|
|
308
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
309
|
+
return message.includes("-32601") || /method not found/i.test(message);
|
|
310
|
+
}
|
|
311
|
+
|
|
306
312
|
/**
|
|
307
313
|
* List resource templates from a connected server.
|
|
314
|
+
*
|
|
315
|
+
* A server MAY advertise the `resources` capability without implementing the
|
|
316
|
+
* optional `resources/templates/list` method (it is optional in the MCP spec).
|
|
317
|
+
* Such servers reject the request with JSON-RPC -32601 ("Method not found").
|
|
318
|
+
* Treat that as "no templates" and return `[]` rather than throwing — otherwise
|
|
319
|
+
* a caller that loads resources and templates together (see `MCPManager`'s
|
|
320
|
+
* `Promise.all([listResources, listResourceTemplates])`) would discard the
|
|
321
|
+
* server's concrete resources too. Any other error still propagates.
|
|
308
322
|
*/
|
|
309
323
|
export async function listResourceTemplates(
|
|
310
324
|
connection: MCPServerConnection,
|
|
@@ -321,20 +335,31 @@ export async function listResourceTemplates(
|
|
|
321
335
|
const allTemplates: MCPResourceTemplate[] = [];
|
|
322
336
|
let cursor: string | undefined;
|
|
323
337
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
338
|
+
try {
|
|
339
|
+
do {
|
|
340
|
+
const params: Record<string, unknown> = {};
|
|
341
|
+
if (cursor) {
|
|
342
|
+
params.cursor = cursor;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const result = await connection.transport.request<MCPResourceTemplatesListResult>(
|
|
346
|
+
"resources/templates/list",
|
|
347
|
+
params,
|
|
348
|
+
options,
|
|
349
|
+
);
|
|
350
|
+
allTemplates.push(...result.resourceTemplates);
|
|
351
|
+
cursor = result.nextCursor;
|
|
352
|
+
} while (cursor);
|
|
353
|
+
} catch (error) {
|
|
354
|
+
// A server that doesn't implement the optional templates method answers
|
|
355
|
+
// -32601; cache an empty list so we neither retry nor let the failure
|
|
356
|
+
// bubble up and discard the server's concrete resources.
|
|
357
|
+
if (isMethodNotFoundError(error)) {
|
|
358
|
+
connection.resourceTemplates = [];
|
|
359
|
+
return [];
|
|
328
360
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
"resources/templates/list",
|
|
332
|
-
params,
|
|
333
|
-
options,
|
|
334
|
-
);
|
|
335
|
-
allTemplates.push(...result.resourceTemplates);
|
|
336
|
-
cursor = result.nextCursor;
|
|
337
|
-
} while (cursor);
|
|
361
|
+
throw error;
|
|
362
|
+
}
|
|
338
363
|
|
|
339
364
|
connection.resourceTemplates = allTemplates;
|
|
340
365
|
return allTemplates;
|
package/src/mcp/render.ts
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
* showing args and output in JSON tree format similar to task tool.
|
|
6
6
|
*/
|
|
7
7
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
8
|
-
import { Text } from "@oh-my-pi/pi-tui";
|
|
9
8
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
10
9
|
import type { Theme } from "../modes/theme/theme";
|
|
11
10
|
import {
|
|
@@ -20,25 +19,33 @@ import {
|
|
|
20
19
|
} from "../tools/json-tree";
|
|
21
20
|
import { formatStyledTruncationWarning, stripOutputNotice } from "../tools/output-meta";
|
|
22
21
|
import { formatExpandHint, truncateToWidth } from "../tools/render-utils";
|
|
23
|
-
import { renderStatusLine } from "../tui";
|
|
22
|
+
import { renderStatusLine, WidthAwareText } from "../tui";
|
|
24
23
|
import type { MCPToolDetails } from "./tool-bridge";
|
|
25
24
|
|
|
26
25
|
/**
|
|
27
26
|
* Render MCP tool call.
|
|
28
27
|
*/
|
|
29
28
|
export function renderMCPCall(args: Record<string, unknown>, theme: Theme, label: string): Component {
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
return new WidthAwareText(
|
|
30
|
+
contentWidth => {
|
|
31
|
+
const lines: string[] = [];
|
|
32
|
+
lines.push(renderStatusLine({ icon: "pending", title: label }, theme));
|
|
32
33
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
if (args && typeof args === "object" && Object.keys(args).length > 0) {
|
|
35
|
+
// Inline preview budgeted against the render width, leaving room for
|
|
36
|
+
// the ` └─ ` connector prefix instead of a fixed cap.
|
|
37
|
+
const inlineBudget = Math.max(20, contentWidth - Bun.stringWidth(theme.tree.last) - 2);
|
|
38
|
+
const preview = formatArgsInline(args, inlineBudget);
|
|
39
|
+
if (preview) {
|
|
40
|
+
lines.push(` ${theme.fg("dim", theme.tree.last)} ${theme.fg("dim", preview)}`);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
return lines.join("\n");
|
|
45
|
+
},
|
|
46
|
+
0,
|
|
47
|
+
0,
|
|
48
|
+
);
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
/**
|
|
@@ -51,92 +58,98 @@ export function renderMCPResult(
|
|
|
51
58
|
args?: Record<string, unknown>,
|
|
52
59
|
): Component {
|
|
53
60
|
const { expanded } = options;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (expanded && args && typeof args === "object" && Object.keys(args).length > 0) {
|
|
67
|
-
lines.push(`${theme.fg("dim", "Args")}`);
|
|
68
|
-
const maxDepth = JSON_TREE_MAX_DEPTH_EXPANDED;
|
|
69
|
-
const maxLines = JSON_TREE_MAX_LINES_EXPANDED;
|
|
70
|
-
const tree = renderJsonTreeLines(args, theme, maxDepth, maxLines, JSON_TREE_SCALAR_LEN_EXPANDED);
|
|
71
|
-
for (const line of tree.lines) {
|
|
72
|
-
lines.push(line);
|
|
73
|
-
}
|
|
74
|
-
if (tree.truncated) {
|
|
75
|
-
lines.push(theme.fg("dim", "…"));
|
|
76
|
-
}
|
|
77
|
-
lines.push(""); // Blank line before output
|
|
78
|
-
}
|
|
61
|
+
return new WidthAwareText(
|
|
62
|
+
contentWidth => {
|
|
63
|
+
const lines: string[] = [];
|
|
64
|
+
const isError = result.isError ?? result.details?.isError ?? false;
|
|
65
|
+
const title = result.details ? `${result.details.serverName}/${result.details.mcpToolName}` : "MCP";
|
|
66
|
+
const success = !isError;
|
|
67
|
+
lines.push(
|
|
68
|
+
renderStatusLine(
|
|
69
|
+
success ? { iconOverride: theme.styledSymbol("tool.mcp", "accent"), title } : { icon: "error", title },
|
|
70
|
+
theme,
|
|
71
|
+
),
|
|
72
|
+
);
|
|
79
73
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const trimmedOutput = stripOutputNotice(textContent, result.details?.meta).trimEnd();
|
|
87
|
-
const truncationWarning = result.details?.meta?.truncation
|
|
88
|
-
? formatStyledTruncationWarning(result.details.meta, theme)
|
|
89
|
-
: null;
|
|
90
|
-
|
|
91
|
-
if (!trimmedOutput) {
|
|
92
|
-
lines.push(theme.fg("dim", "(no output)"));
|
|
93
|
-
return new Text(lines.join("\n"), 0, 0);
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Try to parse as JSON for structured display
|
|
97
|
-
if (trimmedOutput.startsWith("{") || trimmedOutput.startsWith("[")) {
|
|
98
|
-
try {
|
|
99
|
-
const parsed = JSON.parse(trimmedOutput);
|
|
100
|
-
const maxDepth = expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
|
|
101
|
-
const maxLines = expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
|
|
102
|
-
const maxScalarLen = expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
|
|
103
|
-
const tree = renderJsonTreeLines(parsed, theme, maxDepth, maxLines, maxScalarLen);
|
|
104
|
-
|
|
105
|
-
if (tree.lines.length > 0) {
|
|
74
|
+
// Args section (when expanded)
|
|
75
|
+
if (expanded && args && typeof args === "object" && Object.keys(args).length > 0) {
|
|
76
|
+
lines.push(`${theme.fg("dim", "Args")}`);
|
|
77
|
+
const maxDepth = JSON_TREE_MAX_DEPTH_EXPANDED;
|
|
78
|
+
const maxLines = JSON_TREE_MAX_LINES_EXPANDED;
|
|
79
|
+
const tree = renderJsonTreeLines(args, theme, maxDepth, maxLines, JSON_TREE_SCALAR_LEN_EXPANDED);
|
|
106
80
|
for (const line of tree.lines) {
|
|
107
81
|
lines.push(line);
|
|
108
82
|
}
|
|
109
|
-
|
|
110
|
-
if (!expanded) {
|
|
111
|
-
lines.push(formatExpandHint(theme, expanded, true));
|
|
112
|
-
} else if (tree.truncated) {
|
|
83
|
+
if (tree.truncated) {
|
|
113
84
|
lines.push(theme.fg("dim", "…"));
|
|
114
85
|
}
|
|
115
|
-
|
|
116
|
-
|
|
86
|
+
lines.push(""); // Blank line before output
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Output section
|
|
90
|
+
const textContent = result.content?.find(c => c.type === "text")?.text ?? "";
|
|
91
|
+
// Strip the LLM-facing spill notice before parsing/rendering: a spilled
|
|
92
|
+
// result appends `[Showing… artifact://N]` to the body, which would break
|
|
93
|
+
// JSON detection and bury the recovery link. Surface it as a styled warning
|
|
94
|
+
// instead, mirroring the built-in read/bash/ssh/browser renderers.
|
|
95
|
+
const trimmedOutput = stripOutputNotice(textContent, result.details?.meta).trimEnd();
|
|
96
|
+
const truncationWarning = result.details?.meta?.truncation
|
|
97
|
+
? formatStyledTruncationWarning(result.details.meta, theme)
|
|
98
|
+
: null;
|
|
99
|
+
|
|
100
|
+
if (!trimmedOutput) {
|
|
101
|
+
lines.push(theme.fg("dim", "(no output)"));
|
|
102
|
+
return lines.join("\n");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Try to parse as JSON for structured display
|
|
106
|
+
if (trimmedOutput.startsWith("{") || trimmedOutput.startsWith("[")) {
|
|
107
|
+
try {
|
|
108
|
+
const parsed = JSON.parse(trimmedOutput);
|
|
109
|
+
const maxDepth = expanded ? JSON_TREE_MAX_DEPTH_EXPANDED : JSON_TREE_MAX_DEPTH_COLLAPSED;
|
|
110
|
+
const maxLines = expanded ? JSON_TREE_MAX_LINES_EXPANDED : JSON_TREE_MAX_LINES_COLLAPSED;
|
|
111
|
+
const maxScalarLen = expanded ? JSON_TREE_SCALAR_LEN_EXPANDED : JSON_TREE_SCALAR_LEN_COLLAPSED;
|
|
112
|
+
const tree = renderJsonTreeLines(parsed, theme, maxDepth, maxLines, maxScalarLen);
|
|
113
|
+
|
|
114
|
+
if (tree.lines.length > 0) {
|
|
115
|
+
for (const line of tree.lines) {
|
|
116
|
+
lines.push(line);
|
|
117
|
+
}
|
|
118
|
+
// Always show expand hint when collapsed (expanded view shows longer values and deeper nesting)
|
|
119
|
+
if (!expanded) {
|
|
120
|
+
lines.push(formatExpandHint(theme, expanded, true));
|
|
121
|
+
} else if (tree.truncated) {
|
|
122
|
+
lines.push(theme.fg("dim", "…"));
|
|
123
|
+
}
|
|
124
|
+
if (truncationWarning) lines.push(truncationWarning);
|
|
125
|
+
return lines.join("\n");
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
// Fall through to raw output
|
|
129
|
+
}
|
|
117
130
|
}
|
|
118
|
-
} catch {
|
|
119
|
-
// Fall through to raw output
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
132
|
+
// Raw text output
|
|
133
|
+
const outputLines = trimmedOutput.split("\n");
|
|
134
|
+
const maxOutputLines = expanded ? 12 : 4;
|
|
135
|
+
const displayLines = outputLines.slice(0, maxOutputLines);
|
|
127
136
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
137
|
+
for (const line of displayLines) {
|
|
138
|
+
lines.push(theme.fg("toolOutput", truncateToWidth(line, contentWidth)));
|
|
139
|
+
}
|
|
131
140
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
141
|
+
if (outputLines.length > maxOutputLines) {
|
|
142
|
+
const remaining = outputLines.length - maxOutputLines;
|
|
143
|
+
lines.push(`${theme.fg("dim", `… ${remaining} more lines`)} ${formatExpandHint(theme, expanded, true)}`);
|
|
144
|
+
} else if (!expanded) {
|
|
145
|
+
// Show expand hint when collapsed even if all lines shown (lines may be truncated)
|
|
146
|
+
lines.push(formatExpandHint(theme, expanded, true));
|
|
147
|
+
}
|
|
139
148
|
|
|
140
|
-
|
|
141
|
-
|
|
149
|
+
if (truncationWarning) lines.push(truncationWarning);
|
|
150
|
+
return lines.join("\n");
|
|
151
|
+
},
|
|
152
|
+
0,
|
|
153
|
+
0,
|
|
154
|
+
);
|
|
142
155
|
}
|
|
@@ -17,7 +17,7 @@ import * as fs from "node:fs";
|
|
|
17
17
|
import * as path from "node:path";
|
|
18
18
|
import type { AgentMessage, AgentTool } from "@oh-my-pi/pi-agent-core";
|
|
19
19
|
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
20
|
-
import { Container, Editor, matchesKey, ScrollView, Text, type TUI } from "@oh-my-pi/pi-tui";
|
|
20
|
+
import { Container, Editor, Ellipsis, matchesKey, ScrollView, Text, type TUI } from "@oh-my-pi/pi-tui";
|
|
21
21
|
import { formatAge, formatBytes, formatDuration, formatNumber, getProjectDir, logger } from "@oh-my-pi/pi-utils";
|
|
22
22
|
import type { AdvisorMessageDetails } from "../../advisor";
|
|
23
23
|
import { COLLAB_PROMPT_MESSAGE_TYPE, type CollabPromptDetails } from "../../collab/protocol";
|
|
@@ -81,7 +81,12 @@ function contentWidth(): number {
|
|
|
81
81
|
|
|
82
82
|
/** Sanitize a line for TUI display: replace tabs, then truncate to viewport width. */
|
|
83
83
|
function sanitizeLine(text: string, maxWidth?: number): string {
|
|
84
|
-
|
|
84
|
+
const singleLine = replaceTabs(text).replace(/[\r\n]+/g, " ");
|
|
85
|
+
return truncateToWidth(singleLine, maxWidth ?? contentWidth());
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function clampHubLine(line: string, width: number): string {
|
|
89
|
+
return truncateToWidth(line.replace(/[\r\n]+/g, " "), Math.max(1, width - 2), Ellipsis.Omit);
|
|
85
90
|
}
|
|
86
91
|
|
|
87
92
|
const STATUS_ORDER: Record<AgentStatus, number> = { running: 0, idle: 1, parked: 2, aborted: 3 };
|
|
@@ -298,7 +303,8 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
298
303
|
}
|
|
299
304
|
|
|
300
305
|
override render(width: number): readonly string[] {
|
|
301
|
-
|
|
306
|
+
const lines = this.#view === "table" ? this.#renderTable(width) : this.#renderChat(width);
|
|
307
|
+
return lines.map(line => clampHubLine(line, width));
|
|
302
308
|
}
|
|
303
309
|
|
|
304
310
|
handleInput(keyData: string): void {
|
|
@@ -490,7 +496,8 @@ export class AgentHubOverlayComponent extends Container {
|
|
|
490
496
|
parts.push(theme.fg("warning", `⧉ ${unread}`));
|
|
491
497
|
}
|
|
492
498
|
parts.push(theme.fg("dim", formatAge(Math.max(1, Math.round((Date.now() - ref.lastActivity) / 1000)))));
|
|
493
|
-
|
|
499
|
+
const rawLine = ` ${cursor} ${parts.join(theme.sep.dot)}`;
|
|
500
|
+
return truncateToWidth(rawLine.replace(/[\r\n]+/g, " "), Math.max(1, width - 1));
|
|
494
501
|
}
|
|
495
502
|
|
|
496
503
|
#handleTableInput(keyData: string): void {
|
|
@@ -58,6 +58,10 @@ export class BtwPanelComponent extends Container {
|
|
|
58
58
|
this.#rebuild();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
isBranchable(): boolean {
|
|
62
|
+
return this.#state === "complete" && this.#answer.trim().length > 0;
|
|
63
|
+
}
|
|
64
|
+
|
|
61
65
|
close(): void {
|
|
62
66
|
this.#closed = true;
|
|
63
67
|
}
|
|
@@ -85,7 +89,7 @@ export class BtwPanelComponent extends Container {
|
|
|
85
89
|
case "running":
|
|
86
90
|
return theme.fg("muted", "Esc cancel /btw");
|
|
87
91
|
case "complete":
|
|
88
|
-
return theme.fg("muted", "Esc dismiss");
|
|
92
|
+
return theme.fg("muted", this.isBranchable() ? "b branch · Esc dismiss" : "Esc dismiss");
|
|
89
93
|
case "aborted":
|
|
90
94
|
return theme.fg("warning", `${theme.status.warning} Cancelled · Esc dismiss`);
|
|
91
95
|
case "error":
|
|
@@ -12,7 +12,9 @@ export class CollabPromptMessageComponent extends Container {
|
|
|
12
12
|
constructor(message: CustomMessage<CollabPromptDetails>) {
|
|
13
13
|
super();
|
|
14
14
|
const from = message.details?.from?.trim() || "guest";
|
|
15
|
-
|
|
15
|
+
const authorText = new Text(theme.fg("accent", `\x1b[1m«${from}»\x1b[22m ›`), 1, 0);
|
|
16
|
+
authorText.setIgnoreTight(true);
|
|
17
|
+
this.addChild(authorText);
|
|
16
18
|
const text =
|
|
17
19
|
typeof message.content === "string"
|
|
18
20
|
? message.content
|
|
@@ -20,11 +22,11 @@ export class CollabPromptMessageComponent extends Container {
|
|
|
20
22
|
.filter((content): content is TextContent => content.type === "text")
|
|
21
23
|
.map(content => content.text)
|
|
22
24
|
.join("");
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
);
|
|
25
|
+
const md = new Markdown(text, 1, 1, getMarkdownTheme(), {
|
|
26
|
+
bgColor: (value: string) => theme.bg("userMessageBg", value),
|
|
27
|
+
color: (value: string) => theme.fg("userMessageText", value),
|
|
28
|
+
});
|
|
29
|
+
md.setIgnoreTight(true);
|
|
30
|
+
this.addChild(md);
|
|
29
31
|
}
|
|
30
32
|
}
|
|
@@ -62,6 +62,7 @@ class SummaryDividerComponent implements Component {
|
|
|
62
62
|
#detailBox(): Box {
|
|
63
63
|
if (this.#detail) return this.#detail;
|
|
64
64
|
const box = new Box(1, 1, t => theme.bg("customMessageBg", t));
|
|
65
|
+
box.setIgnoreTight(true);
|
|
65
66
|
box.addChild(
|
|
66
67
|
new Markdown(this.options.detailMarkdown(), 0, 0, getMarkdownTheme(), {
|
|
67
68
|
color: (text: string) => theme.fg("customMessageText", text),
|
|
@@ -22,6 +22,7 @@ type ConfigurableEditorAction = Extract<
|
|
|
22
22
|
| "app.editor.external"
|
|
23
23
|
| "app.history.search"
|
|
24
24
|
| "app.message.dequeue"
|
|
25
|
+
| "app.retry"
|
|
25
26
|
| "app.clipboard.pasteImage"
|
|
26
27
|
| "app.clipboard.pasteTextRaw"
|
|
27
28
|
| "app.clipboard.copyPrompt"
|
|
@@ -43,6 +44,7 @@ const DEFAULT_ACTION_KEYS: Record<ConfigurableEditorAction, KeyId[]> = {
|
|
|
43
44
|
"app.editor.external": ["ctrl+g"],
|
|
44
45
|
"app.history.search": ["ctrl+r"],
|
|
45
46
|
"app.message.dequeue": ["alt+up"],
|
|
47
|
+
"app.retry": ["alt+r"],
|
|
46
48
|
"app.clipboard.pasteImage": ["ctrl+v"],
|
|
47
49
|
"app.clipboard.pasteTextRaw": ["ctrl+shift+v", "alt+shift+v"],
|
|
48
50
|
"app.clipboard.copyPrompt": ["alt+shift+c"],
|
|
@@ -268,6 +270,8 @@ export class CustomEditor extends Editor {
|
|
|
268
270
|
onPasteTextRaw?: () => void;
|
|
269
271
|
/** Called when the configured dequeue shortcut is pressed. */
|
|
270
272
|
onDequeue?: () => void;
|
|
273
|
+
/** Called when the configured retry shortcut is pressed. */
|
|
274
|
+
onRetry?: () => void;
|
|
271
275
|
/** Called when Caps Lock is pressed. */
|
|
272
276
|
onCapsLock?: () => void;
|
|
273
277
|
/** Called when left-arrow is pressed while the editor is empty (cursor necessarily at start). */
|
|
@@ -588,6 +592,20 @@ export class CustomEditor extends Editor {
|
|
|
588
592
|
return;
|
|
589
593
|
}
|
|
590
594
|
|
|
595
|
+
// Intercept configured retry shortcut. Later user/custom handlers keep
|
|
596
|
+
// precedence so adding the default Alt+R binding does not steal existing
|
|
597
|
+
// shortcuts such as app.plan.toggle or extension commands; copy-prompt is
|
|
598
|
+
// checked above for the same reason.
|
|
599
|
+
if (this.#matchesAction(canonical, "app.retry") && this.onRetry) {
|
|
600
|
+
const customHandler = this.#customMatchKeys.get(canonical);
|
|
601
|
+
if (customHandler) {
|
|
602
|
+
customHandler();
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
this.onRetry();
|
|
606
|
+
return;
|
|
607
|
+
}
|
|
608
|
+
|
|
591
609
|
// Check custom key handlers (extensions)
|
|
592
610
|
const handler = this.#customMatchKeys.get(canonical);
|
|
593
611
|
if (handler) {
|