@oh-my-pi/pi-coding-agent 15.0.0 → 15.0.2
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 +79 -0
- package/examples/extensions/plan-mode.ts +0 -1
- package/package.json +10 -10
- package/scripts/build-binary.ts +5 -0
- package/src/autoresearch/helpers.ts +17 -0
- package/src/autoresearch/tools/log-experiment.ts +9 -17
- package/src/autoresearch/tools/run-experiment.ts +2 -17
- package/src/capability/skill.ts +7 -0
- package/src/cli/list-models.ts +1 -1
- package/src/cli/shell-cli.ts +3 -13
- package/src/cli/update-cli.ts +1 -1
- package/src/cli.ts +10 -29
- package/src/commands/commit.ts +10 -0
- package/src/commit/agentic/tools/propose-changelog.ts +8 -1
- package/src/commit/analysis/conventional.ts +8 -66
- package/src/commit/map-reduce/reduce-phase.ts +6 -65
- package/src/commit/pipeline.ts +2 -2
- package/src/commit/shared-llm.ts +89 -0
- package/src/config/config-file.ts +210 -0
- package/src/config/model-equivalence.ts +8 -11
- package/src/config/model-registry.ts +44 -3
- package/src/config/model-resolver.ts +1 -4
- package/src/config/settings-schema.ts +82 -1
- package/src/config/settings.ts +1 -1
- package/src/config.ts +3 -219
- package/src/discovery/claude-plugins.ts +19 -7
- package/src/edit/renderer.ts +7 -1
- package/src/eval/js/executor.ts +3 -0
- package/src/eval/js/shared/rewrite-imports.ts +2 -2
- package/src/eval/py/executor.ts +5 -0
- package/src/eval/py/runner.py +42 -11
- package/src/eval/py/runtime.ts +1 -0
- package/src/exa/factory.ts +2 -2
- package/src/exa/mcp-client.ts +74 -1
- package/src/exec/bash-executor.ts +5 -1
- package/src/export/html/template.generated.ts +1 -1
- package/src/export/html/template.js +0 -11
- package/src/extensibility/extensions/get-commands-handler.ts +77 -0
- package/src/extensibility/extensions/runner.ts +1 -1
- package/src/extensibility/extensions/types.ts +89 -223
- package/src/extensibility/hooks/types.ts +89 -314
- package/src/extensibility/plugins/legacy-pi-compat.ts +48 -31
- package/src/extensibility/shared-events.ts +343 -0
- package/src/extensibility/skills.ts +9 -0
- package/src/goals/index.ts +3 -0
- package/src/goals/runtime.ts +500 -0
- package/src/goals/state.ts +37 -0
- package/src/goals/tools/goal-tool.ts +237 -0
- package/src/hashline/anchors.ts +2 -2
- package/src/hashline/input.ts +2 -1
- package/src/hashline/parser.ts +27 -3
- package/src/hindsight/mental-models.ts +1 -1
- package/src/internal-urls/agent-protocol.ts +1 -20
- package/src/internal-urls/artifact-protocol.ts +1 -19
- package/src/internal-urls/docs-index.generated.ts +11 -12
- package/src/internal-urls/registry-helpers.ts +25 -0
- package/src/internal-urls/router.ts +8 -0
- package/src/internal-urls/types.ts +21 -0
- package/src/lsp/config.ts +15 -6
- package/src/lsp/defaults.json +6 -2
- package/src/main.ts +11 -2
- package/src/mcp/oauth-flow.ts +20 -0
- package/src/modes/acp/acp-agent.ts +327 -95
- package/src/modes/components/assistant-message.ts +14 -8
- package/src/modes/components/bash-execution.ts +24 -63
- package/src/modes/components/custom-message.ts +14 -40
- package/src/modes/components/eval-execution.ts +27 -57
- package/src/modes/components/execution-shared.ts +102 -0
- package/src/modes/components/hook-message.ts +17 -49
- package/src/modes/components/mcp-add-wizard.ts +26 -5
- package/src/modes/components/message-frame.ts +88 -0
- package/src/modes/components/model-selector.ts +1 -1
- package/src/modes/components/session-observer-overlay.ts +6 -2
- package/src/modes/components/session-selector.ts +1 -1
- package/src/modes/components/status-line/segments.ts +93 -8
- package/src/modes/components/status-line/types.ts +4 -0
- package/src/modes/components/status-line.ts +28 -10
- package/src/modes/components/tool-execution.ts +7 -8
- package/src/modes/controllers/command-controller-shared.ts +108 -0
- package/src/modes/controllers/command-controller.ts +13 -4
- package/src/modes/controllers/event-controller.ts +36 -7
- package/src/modes/controllers/extension-ui-controller.ts +3 -2
- package/src/modes/controllers/input-controller.ts +13 -0
- package/src/modes/controllers/mcp-command-controller.ts +56 -61
- package/src/modes/controllers/ssh-command-controller.ts +18 -57
- package/src/modes/interactive-mode.ts +624 -52
- package/src/modes/print-mode.ts +16 -86
- package/src/modes/rpc/host-uris.ts +235 -0
- package/src/modes/rpc/rpc-mode.ts +41 -88
- package/src/modes/rpc/rpc-types.ts +57 -0
- package/src/modes/runtime-init.ts +116 -0
- package/src/modes/theme/defaults/dark-poimandres.json +3 -0
- package/src/modes/theme/defaults/light-poimandres.json +3 -0
- package/src/modes/theme/theme.ts +24 -6
- package/src/modes/types.ts +14 -3
- package/src/modes/utils/context-usage.ts +13 -13
- package/src/modes/utils/ui-helpers.ts +10 -3
- package/src/plan-mode/approved-plan.ts +35 -1
- package/src/prompts/goals/goal-budget-limit.md +16 -0
- package/src/prompts/goals/goal-continuation.md +28 -0
- package/src/prompts/goals/goal-mode-active.md +23 -0
- package/src/prompts/system/plan-mode-active.md +5 -5
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +1 -1
- package/src/prompts/tools/bash.md +6 -0
- package/src/prompts/tools/github.md +4 -4
- package/src/prompts/tools/goal.md +13 -0
- package/src/prompts/tools/hashline.md +101 -117
- package/src/prompts/tools/read.md +55 -36
- package/src/prompts/tools/resolve.md +6 -5
- package/src/sdk.ts +12 -5
- package/src/session/agent-session.ts +428 -106
- package/src/session/blob-store.ts +36 -3
- package/src/session/messages.ts +67 -2
- package/src/session/session-manager.ts +131 -12
- package/src/session/session-storage.ts +33 -15
- package/src/session/streaming-output.ts +309 -13
- package/src/slash-commands/builtin-registry.ts +18 -0
- package/src/ssh/ssh-executor.ts +5 -0
- package/src/system-prompt.ts +4 -2
- package/src/task/discovery.ts +5 -2
- package/src/task/executor.ts +19 -8
- package/src/task/index.ts +3 -0
- package/src/task/render.ts +21 -15
- package/src/task/types.ts +4 -0
- package/src/tools/ast-edit.ts +21 -120
- package/src/tools/ast-grep.ts +21 -119
- package/src/tools/bash-command-fixup.ts +47 -0
- package/src/tools/bash-interactive.ts +9 -1
- package/src/tools/bash.ts +66 -19
- package/src/tools/browser/attach.ts +3 -3
- package/src/tools/browser/launch.ts +81 -18
- package/src/tools/browser/registry.ts +1 -5
- package/src/tools/browser/render.ts +2 -2
- package/src/tools/browser/tab-supervisor.ts +51 -14
- package/src/tools/conflict-detect.ts +15 -4
- package/src/tools/eval.ts +12 -2
- package/src/tools/find.ts +20 -38
- package/src/tools/gh.ts +44 -10
- package/src/tools/index.ts +22 -11
- package/src/tools/inspect-image.ts +3 -10
- package/src/tools/job.ts +16 -7
- package/src/tools/output-meta.ts +202 -37
- package/src/tools/path-utils.ts +125 -2
- package/src/tools/read.ts +548 -237
- package/src/tools/render-utils.ts +92 -0
- package/src/tools/renderers.ts +2 -0
- package/src/tools/resolve.ts +72 -44
- package/src/tools/search.ts +120 -186
- package/src/tools/ssh.ts +3 -2
- package/src/tools/write.ts +64 -9
- package/src/utils/file-mentions.ts +1 -1
- package/src/utils/image-loading.ts +7 -3
- package/src/utils/image-resize.ts +32 -43
- package/src/vim/parser.ts +0 -17
- package/src/vim/render.ts +1 -1
- package/src/vim/types.ts +1 -1
- package/src/web/search/providers/anthropic.ts +5 -0
- package/src/web/search/providers/exa.ts +3 -0
- package/src/web/search/providers/gemini.ts +40 -95
- package/src/web/search/providers/jina.ts +5 -2
- package/src/web/search/providers/zai.ts +5 -2
- package/src/prompts/tools/exit-plan-mode.md +0 -6
- package/src/tools/exit-plan-mode.ts +0 -97
- package/src/utils/fuzzy.ts +0 -108
- package/src/utils/image-convert.ts +0 -27
|
@@ -9,10 +9,12 @@ import * as os from "node:os";
|
|
|
9
9
|
import * as path from "node:path";
|
|
10
10
|
import type { ToolCallContext } from "@oh-my-pi/pi-agent-core";
|
|
11
11
|
import type { Ellipsis } from "@oh-my-pi/pi-natives";
|
|
12
|
+
import type { Component } from "@oh-my-pi/pi-tui";
|
|
12
13
|
import { replaceTabs, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
13
14
|
import { pluralize } from "@oh-my-pi/pi-utils";
|
|
14
15
|
import { settings } from "../config/settings";
|
|
15
16
|
import type { Theme } from "../modes/theme/theme";
|
|
17
|
+
import { Hasher } from "../tui/utils";
|
|
16
18
|
import { formatDimensionNote, type ResizedImage } from "../utils/image-resize";
|
|
17
19
|
|
|
18
20
|
export { Ellipsis } from "@oh-my-pi/pi-natives";
|
|
@@ -642,6 +644,96 @@ export function formatParseErrors(errors: string[]): string[] {
|
|
|
642
644
|
return [header, ...capped.map(err => `- ${err}`)];
|
|
643
645
|
}
|
|
644
646
|
|
|
647
|
+
// =============================================================================
|
|
648
|
+
// Renderer helpers shared by search / find / ast tools
|
|
649
|
+
// =============================================================================
|
|
650
|
+
|
|
651
|
+
/**
|
|
652
|
+
* Group `rawLines` by blank-line separators, mirroring the historical search /
|
|
653
|
+
* ast-grep / ast-edit renderer behavior: if any blank line is present, splits on
|
|
654
|
+
* runs of blank lines; otherwise collapses non-empty lines into a single group.
|
|
655
|
+
*/
|
|
656
|
+
export function splitGroupsByBlankLine(rawLines: string[]): string[][] {
|
|
657
|
+
const hasSeparators = rawLines.some(line => line.trim().length === 0);
|
|
658
|
+
const groups: string[][] = [];
|
|
659
|
+
if (hasSeparators) {
|
|
660
|
+
let current: string[] = [];
|
|
661
|
+
for (const line of rawLines) {
|
|
662
|
+
if (line.trim().length === 0) {
|
|
663
|
+
if (current.length > 0) {
|
|
664
|
+
groups.push(current);
|
|
665
|
+
current = [];
|
|
666
|
+
}
|
|
667
|
+
continue;
|
|
668
|
+
}
|
|
669
|
+
current.push(line);
|
|
670
|
+
}
|
|
671
|
+
if (current.length > 0) groups.push(current);
|
|
672
|
+
} else {
|
|
673
|
+
const nonEmpty = rawLines.filter(line => line.trim().length > 0);
|
|
674
|
+
if (nonEmpty.length > 0) {
|
|
675
|
+
groups.push(nonEmpty);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
return groups;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* Standard width+expand keyed render cache used by every search-style tool
|
|
683
|
+
* renderer. `compute` re-runs only when the cache key changes; the returned
|
|
684
|
+
* Component is the canonical `{ render, invalidate }` pair.
|
|
685
|
+
*/
|
|
686
|
+
export function createCachedComponent(
|
|
687
|
+
getExpanded: () => boolean,
|
|
688
|
+
compute: (width: number, expanded: boolean) => string[],
|
|
689
|
+
): Component {
|
|
690
|
+
let cached: { key: bigint; lines: string[] } | undefined;
|
|
691
|
+
return {
|
|
692
|
+
render(width: number): string[] {
|
|
693
|
+
const expanded = getExpanded();
|
|
694
|
+
const key = new Hasher().bool(expanded).u32(width).digest();
|
|
695
|
+
if (cached?.key === key) return cached.lines;
|
|
696
|
+
const lines = compute(width, expanded);
|
|
697
|
+
cached = { key, lines };
|
|
698
|
+
return lines;
|
|
699
|
+
},
|
|
700
|
+
invalidate() {
|
|
701
|
+
cached = undefined;
|
|
702
|
+
},
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Append the indented bullet list of parse errors (capped at
|
|
708
|
+
* {@link PARSE_ERRORS_LIMIT}) to `lines`, with an overflow summary line if the
|
|
709
|
+
* total exceeds the cap. No-op when `parseErrors` is empty.
|
|
710
|
+
*/
|
|
711
|
+
export function appendParseErrorsBulletList(
|
|
712
|
+
lines: string[],
|
|
713
|
+
parseErrors: readonly string[] | undefined,
|
|
714
|
+
theme: Theme,
|
|
715
|
+
): void {
|
|
716
|
+
if (!parseErrors || parseErrors.length === 0) return;
|
|
717
|
+
const capped = parseErrors.slice(0, PARSE_ERRORS_LIMIT);
|
|
718
|
+
for (const err of capped) {
|
|
719
|
+
lines.push(theme.fg("warning", ` - ${err}`));
|
|
720
|
+
}
|
|
721
|
+
if (parseErrors.length > PARSE_ERRORS_LIMIT) {
|
|
722
|
+
lines.push(theme.fg("dim", ` … ${parseErrors.length - PARSE_ERRORS_LIMIT} more`));
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
/**
|
|
727
|
+
* Human-readable summary string for the parse-issues count, capped by
|
|
728
|
+
* {@link PARSE_ERRORS_LIMIT}.
|
|
729
|
+
*/
|
|
730
|
+
export function formatParseErrorsCountLabel(parseErrors: readonly string[]): string {
|
|
731
|
+
const total = parseErrors.length;
|
|
732
|
+
return total > PARSE_ERRORS_LIMIT
|
|
733
|
+
? `${PARSE_ERRORS_LIMIT} / ${total} parse issues`
|
|
734
|
+
: `${total} parse issue${total !== 1 ? "s" : ""}`;
|
|
735
|
+
}
|
|
736
|
+
|
|
645
737
|
// =============================================================================
|
|
646
738
|
// LSP Batching
|
|
647
739
|
// =============================================================================
|
package/src/tools/renderers.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { Component } from "@oh-my-pi/pi-tui";
|
|
7
7
|
import { editToolRenderer } from "../edit/renderer";
|
|
8
8
|
import type { RenderResultOptions } from "../extensibility/custom-tools/types";
|
|
9
|
+
import { goalToolRenderer } from "../goals/tools/goal-tool";
|
|
9
10
|
import { lspToolRenderer } from "../lsp/render";
|
|
10
11
|
import type { Theme } from "../modes/theme/theme";
|
|
11
12
|
import { taskToolRenderer } from "../task/render";
|
|
@@ -68,6 +69,7 @@ export const toolRenderers: Record<string, ToolRenderer> = {
|
|
|
68
69
|
task: taskToolRenderer as ToolRenderer,
|
|
69
70
|
todo_write: todoWriteToolRenderer as ToolRenderer,
|
|
70
71
|
github: githubToolRenderer as ToolRenderer,
|
|
72
|
+
goal: goalToolRenderer as ToolRenderer,
|
|
71
73
|
web_search: webSearchToolRenderer as ToolRenderer,
|
|
72
74
|
write: writeToolRenderer as ToolRenderer,
|
|
73
75
|
};
|
package/src/tools/resolve.ts
CHANGED
|
@@ -14,6 +14,12 @@ import { ToolError } from "./tool-errors";
|
|
|
14
14
|
const resolveSchema = Type.Object({
|
|
15
15
|
action: Type.Union([Type.Literal("apply"), Type.Literal("discard")]),
|
|
16
16
|
reason: Type.String({ description: "reason for action", examples: ["approved by user"] }),
|
|
17
|
+
extra: Type.Optional(
|
|
18
|
+
Type.Record(Type.String(), Type.Unknown(), {
|
|
19
|
+
description:
|
|
20
|
+
'Free-form metadata interpreted by the resolving tool (e.g. plan-mode approval requires `{ title: "<PLAN_TITLE>" }`).',
|
|
21
|
+
}),
|
|
22
|
+
),
|
|
17
23
|
});
|
|
18
24
|
|
|
19
25
|
type ResolveParams = Static<typeof resolveSchema>;
|
|
@@ -21,17 +27,12 @@ type ResolveParams = Static<typeof resolveSchema>;
|
|
|
21
27
|
export interface ResolveToolDetails {
|
|
22
28
|
action: "apply" | "discard";
|
|
23
29
|
reason: string;
|
|
30
|
+
extra?: Record<string, unknown>;
|
|
24
31
|
sourceToolName?: string;
|
|
25
32
|
label?: string;
|
|
26
33
|
sourceResultDetails?: unknown;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
|
-
function resolveReasonPreview(reason?: string): string | undefined {
|
|
30
|
-
const trimmed = reason?.trim();
|
|
31
|
-
if (!trimmed) return undefined;
|
|
32
|
-
return truncateToWidth(trimmed, 72, Ellipsis.Omit);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
36
|
/**
|
|
36
37
|
* Queue a resolve-protocol handler on the tool-choice queue. Forces the next
|
|
37
38
|
* LLM call to invoke the hidden `resolve` tool, wraps the caller's apply/reject
|
|
@@ -47,49 +48,25 @@ export function queueResolveHandler(
|
|
|
47
48
|
options: {
|
|
48
49
|
label: string;
|
|
49
50
|
sourceToolName: string;
|
|
50
|
-
apply(reason: string): Promise<AgentToolResult<unknown>>;
|
|
51
|
-
reject?(reason: string): Promise<AgentToolResult<unknown> | undefined>;
|
|
51
|
+
apply(reason: string, extra?: Record<string, unknown>): Promise<AgentToolResult<unknown>>;
|
|
52
|
+
reject?(reason: string, extra?: Record<string, unknown>): Promise<AgentToolResult<unknown> | undefined>;
|
|
52
53
|
},
|
|
53
54
|
): void {
|
|
54
55
|
const queue = session.getToolChoiceQueue?.();
|
|
55
56
|
const forced = session.buildToolChoice?.("resolve");
|
|
56
57
|
if (!queue || !forced || typeof forced === "string") return;
|
|
57
58
|
|
|
58
|
-
const detailsFor = (params: ResolveParams): ResolveToolDetails => ({
|
|
59
|
-
action: params.action,
|
|
60
|
-
reason: params.reason,
|
|
61
|
-
sourceToolName: options.sourceToolName,
|
|
62
|
-
label: options.label,
|
|
63
|
-
});
|
|
64
|
-
|
|
65
59
|
queue.pushOnce(forced, {
|
|
66
60
|
label: `pending-action:${options.sourceToolName}`,
|
|
67
61
|
now: true,
|
|
68
62
|
onRejected: () => "requeue",
|
|
69
|
-
onInvoked: async (input: unknown) =>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
},
|
|
77
|
-
});
|
|
78
|
-
if (params.action === "apply") {
|
|
79
|
-
const result = await options.apply(params.reason);
|
|
80
|
-
return withResolveDetails(result);
|
|
81
|
-
}
|
|
82
|
-
if (params.action === "discard" && options.reject != null) {
|
|
83
|
-
const result = await options.reject(params.reason);
|
|
84
|
-
if (result != null) {
|
|
85
|
-
return withResolveDetails(result);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
content: [{ type: "text" as const, text: `Discarded: ${options.label}. Reason: ${params.reason}` }],
|
|
90
|
-
details: detailsFor(params),
|
|
91
|
-
};
|
|
92
|
-
},
|
|
63
|
+
onInvoked: async (input: unknown) =>
|
|
64
|
+
runResolveInvocation(input as ResolveParams, {
|
|
65
|
+
sourceToolName: options.sourceToolName,
|
|
66
|
+
label: options.label,
|
|
67
|
+
apply: options.apply,
|
|
68
|
+
reject: options.reject,
|
|
69
|
+
}),
|
|
93
70
|
});
|
|
94
71
|
|
|
95
72
|
session.steer?.({
|
|
@@ -103,6 +80,57 @@ export function queueResolveHandler(
|
|
|
103
80
|
});
|
|
104
81
|
}
|
|
105
82
|
|
|
83
|
+
/**
|
|
84
|
+
* Shared invocation runner used by both queued (in-flight) handlers and
|
|
85
|
+
* standing handlers (e.g. plan-mode approval). Discriminates on action,
|
|
86
|
+
* routes through the caller's apply/reject, and wraps the resulting tool
|
|
87
|
+
* payload with `ResolveToolDetails` so the renderer and event-controller
|
|
88
|
+
* see a consistent shape.
|
|
89
|
+
*/
|
|
90
|
+
export async function runResolveInvocation(
|
|
91
|
+
params: ResolveParams,
|
|
92
|
+
options: {
|
|
93
|
+
sourceToolName: string;
|
|
94
|
+
label: string;
|
|
95
|
+
apply(reason: string, extra?: Record<string, unknown>): Promise<AgentToolResult<unknown>>;
|
|
96
|
+
reject?(reason: string, extra?: Record<string, unknown>): Promise<AgentToolResult<unknown> | undefined>;
|
|
97
|
+
},
|
|
98
|
+
): Promise<AgentToolResult<ResolveToolDetails>> {
|
|
99
|
+
const baseDetails: ResolveToolDetails = {
|
|
100
|
+
action: params.action,
|
|
101
|
+
reason: params.reason,
|
|
102
|
+
sourceToolName: options.sourceToolName,
|
|
103
|
+
label: options.label,
|
|
104
|
+
...(params.extra != null ? { extra: params.extra } : {}),
|
|
105
|
+
};
|
|
106
|
+
if (params.action === "apply") {
|
|
107
|
+
const result = await options.apply(params.reason, params.extra);
|
|
108
|
+
return {
|
|
109
|
+
...result,
|
|
110
|
+
details: {
|
|
111
|
+
...baseDetails,
|
|
112
|
+
...(result.details != null ? { sourceResultDetails: result.details } : {}),
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
if (params.action === "discard" && options.reject != null) {
|
|
117
|
+
const result = await options.reject(params.reason, params.extra);
|
|
118
|
+
if (result != null) {
|
|
119
|
+
return {
|
|
120
|
+
...result,
|
|
121
|
+
details: {
|
|
122
|
+
...baseDetails,
|
|
123
|
+
...(result.details != null ? { sourceResultDetails: result.details } : {}),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return {
|
|
129
|
+
content: [{ type: "text" as const, text: `Discarded: ${options.label}. Reason: ${params.reason}` }],
|
|
130
|
+
details: baseDetails,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
106
134
|
export class ResolveTool implements AgentTool<typeof resolveSchema, ResolveToolDetails> {
|
|
107
135
|
readonly name = "resolve";
|
|
108
136
|
readonly label = "Resolve";
|
|
@@ -112,10 +140,9 @@ export class ResolveTool implements AgentTool<typeof resolveSchema, ResolveToolD
|
|
|
112
140
|
readonly strict = true;
|
|
113
141
|
readonly intent = (args: Partial<ResolveParams>) => {
|
|
114
142
|
if (args.action === "discard") {
|
|
115
|
-
return args.reason ? `discarding: ${args.reason}` : "
|
|
116
|
-
} else {
|
|
117
|
-
return args.reason ? `accepting: ${args.reason}` : "accepting changes";
|
|
143
|
+
return args.reason ? `discarding: ${args.reason}` : "discarding changes";
|
|
118
144
|
}
|
|
145
|
+
return args.reason ? `accepting: ${args.reason}` : "accepting changes";
|
|
119
146
|
};
|
|
120
147
|
|
|
121
148
|
constructor(private readonly session: ToolSession) {
|
|
@@ -130,7 +157,7 @@ export class ResolveTool implements AgentTool<typeof resolveSchema, ResolveToolD
|
|
|
130
157
|
_context?: AgentToolContext,
|
|
131
158
|
): Promise<AgentToolResult<ResolveToolDetails>> {
|
|
132
159
|
return untilAborted(signal, async () => {
|
|
133
|
-
const invoker = this.session.peekQueueInvoker?.();
|
|
160
|
+
const invoker = this.session.peekQueueInvoker?.() ?? this.session.peekStandingResolveHandler?.();
|
|
134
161
|
if (!invoker) {
|
|
135
162
|
throw new ToolError("No pending action to resolve. Nothing to apply or discard.");
|
|
136
163
|
}
|
|
@@ -142,7 +169,8 @@ export class ResolveTool implements AgentTool<typeof resolveSchema, ResolveToolD
|
|
|
142
169
|
|
|
143
170
|
export const resolveToolRenderer = {
|
|
144
171
|
renderCall(args: ResolveParams, _options: RenderResultOptions, uiTheme: Theme): Component {
|
|
145
|
-
const
|
|
172
|
+
const reasonTrimmed = args.reason?.trim();
|
|
173
|
+
const reason = reasonTrimmed ? truncateToWidth(reasonTrimmed, 72, Ellipsis.Omit) : undefined;
|
|
146
174
|
const text = renderStatusLine(
|
|
147
175
|
{
|
|
148
176
|
icon: "pending",
|