@oh-my-pi/pi-coding-agent 13.17.6 → 13.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +72 -0
- package/package.json +7 -11
- package/src/autoresearch/git.ts +25 -30
- package/src/autoresearch/tools/log-experiment.ts +61 -74
- package/src/cli/args.ts +0 -1
- package/src/commit/agentic/agent.ts +0 -3
- package/src/commit/agentic/index.ts +19 -22
- package/src/commit/agentic/tools/git-file-diff.ts +3 -6
- package/src/commit/agentic/tools/git-hunk.ts +3 -3
- package/src/commit/agentic/tools/git-overview.ts +6 -9
- package/src/commit/agentic/tools/index.ts +6 -8
- package/src/commit/agentic/tools/propose-commit.ts +4 -7
- package/src/commit/agentic/tools/recent-commits.ts +3 -3
- package/src/commit/agentic/tools/split-commit.ts +4 -4
- package/src/commit/changelog/index.ts +5 -9
- package/src/commit/pipeline.ts +10 -12
- package/src/config/keybindings.ts +7 -6
- package/src/config/settings-schema.ts +45 -1
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +4 -16
- package/src/extensibility/custom-commands/bundled/review/index.ts +43 -41
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/types.ts +3 -1
- package/src/extensibility/hooks/types.ts +1 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -57
- package/src/extensibility/plugins/marketplace/source-resolver.ts +4 -4
- package/src/index.ts +1 -0
- package/src/internal-urls/types.ts +1 -1
- package/src/main.ts +24 -2
- package/src/modes/acp/acp-event-mapper.ts +0 -1
- package/src/modes/components/footer.ts +9 -29
- package/src/modes/components/hook-editor.ts +3 -3
- package/src/modes/components/hook-selector.ts +6 -1
- package/src/modes/components/session-observer-overlay.ts +472 -0
- package/src/modes/components/settings-defs.ts +19 -0
- package/src/modes/components/status-line.ts +15 -61
- package/src/modes/controllers/command-controller.ts +1 -0
- package/src/modes/controllers/event-controller.ts +59 -2
- package/src/modes/controllers/extension-ui-controller.ts +1 -0
- package/src/modes/controllers/input-controller.ts +3 -0
- package/src/modes/controllers/selector-controller.ts +26 -0
- package/src/modes/interactive-mode.ts +195 -43
- package/src/modes/session-observer-registry.ts +146 -0
- package/src/modes/shared.ts +0 -42
- package/src/modes/types.ts +2 -0
- package/src/modes/utils/keybinding-matchers.ts +9 -0
- package/src/prompts/agents/designer.md +1 -1
- package/src/prompts/agents/explore.md +1 -1
- package/src/prompts/agents/librarian.md +1 -1
- package/src/prompts/agents/oracle.md +1 -1
- package/src/prompts/agents/plan.md +1 -1
- package/src/prompts/agents/reviewer.md +1 -1
- package/src/prompts/system/custom-system-prompt.md +5 -0
- package/src/prompts/system/system-prompt.md +6 -0
- package/src/prompts/tools/read.md +27 -18
- package/src/sdk.ts +28 -13
- package/src/secrets/index.ts +1 -1
- package/src/secrets/obfuscator.ts +24 -16
- package/src/session/agent-session.ts +75 -30
- package/src/session/artifacts.ts +2 -2
- package/src/session/session-manager.ts +15 -5
- package/src/system-prompt.ts +4 -0
- package/src/task/executor.ts +28 -0
- package/src/task/index.ts +89 -79
- package/src/task/types.ts +25 -0
- package/src/task/worktree.ts +127 -145
- package/src/tools/exit-plan-mode.ts +1 -0
- package/src/tools/fetch.ts +173 -98
- package/src/tools/gh.ts +120 -297
- package/src/tools/index.ts +0 -4
- package/src/tools/path-utils.ts +12 -1
- package/src/tools/read.ts +74 -85
- package/src/tools/renderers.ts +0 -2
- package/src/utils/external-editor.ts +11 -5
- package/src/utils/git.ts +1400 -0
- package/src/web/search/render.ts +6 -4
- package/src/commit/git/errors.ts +0 -9
- package/src/commit/git/index.ts +0 -210
- package/src/commit/git/operations.ts +0 -54
- package/src/prompts/tools/fetch.md +0 -11
- package/src/tools/gh-cli.ts +0 -125
package/src/task/index.ts
CHANGED
|
@@ -18,7 +18,6 @@ import path from "node:path";
|
|
|
18
18
|
import type { AgentTool, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
|
|
19
19
|
import type { Usage } from "@oh-my-pi/pi-ai";
|
|
20
20
|
import { $env, Snowflake } from "@oh-my-pi/pi-utils";
|
|
21
|
-
import { $ } from "bun";
|
|
22
21
|
import type { ToolSession } from "..";
|
|
23
22
|
import { resolveAgentModelPatterns } from "../config/model-resolver";
|
|
24
23
|
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
@@ -30,6 +29,7 @@ import { formatBytes, formatDuration } from "../tools/render-utils";
|
|
|
30
29
|
// Import review tools for side effects (registers subagent tool handlers)
|
|
31
30
|
import "../tools/review";
|
|
32
31
|
import { generateCommitMessage } from "../utils/commit-message-generator";
|
|
32
|
+
import * as git from "../utils/git";
|
|
33
33
|
import { discoverAgents, getAgent } from "./discovery";
|
|
34
34
|
import { runSubprocess } from "./executor";
|
|
35
35
|
import { resolveIsolationBackendForTaskExecution } from "./isolation-backend";
|
|
@@ -109,8 +109,21 @@ export { loadBundledAgents as BUNDLED_AGENTS } from "./agents";
|
|
|
109
109
|
export { discoverCommands, expandCommand, getCommand } from "./commands";
|
|
110
110
|
export { discoverAgents, getAgent } from "./discovery";
|
|
111
111
|
export { AgentOutputManager } from "./output-manager";
|
|
112
|
-
export type {
|
|
113
|
-
|
|
112
|
+
export type {
|
|
113
|
+
AgentDefinition,
|
|
114
|
+
AgentProgress,
|
|
115
|
+
SingleResult,
|
|
116
|
+
SubagentLifecyclePayload,
|
|
117
|
+
SubagentProgressPayload,
|
|
118
|
+
TaskParams,
|
|
119
|
+
TaskToolDetails,
|
|
120
|
+
} from "./types";
|
|
121
|
+
export {
|
|
122
|
+
TASK_SUBAGENT_EVENT_CHANNEL,
|
|
123
|
+
TASK_SUBAGENT_LIFECYCLE_CHANNEL,
|
|
124
|
+
TASK_SUBAGENT_PROGRESS_CHANNEL,
|
|
125
|
+
taskSchema,
|
|
126
|
+
} from "./types";
|
|
114
127
|
|
|
115
128
|
/**
|
|
116
129
|
* Render the tool description from a cached agent list and current settings.
|
|
@@ -496,7 +509,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
496
509
|
}
|
|
497
510
|
|
|
498
511
|
const planModeState = this.session.getPlanModeState?.();
|
|
499
|
-
const planModeTools = ["read", "grep", "find", "ls", "lsp", "
|
|
512
|
+
const planModeTools = ["read", "grep", "find", "ls", "lsp", "web_search"];
|
|
500
513
|
const effectiveAgent: typeof agent = planModeState?.enabled
|
|
501
514
|
? {
|
|
502
515
|
...agent,
|
|
@@ -766,7 +779,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
766
779
|
contextFile: contextFilePath,
|
|
767
780
|
enableLsp: false,
|
|
768
781
|
signal,
|
|
769
|
-
eventBus:
|
|
782
|
+
eventBus: this.session.eventBus,
|
|
770
783
|
onProgress: progress => {
|
|
771
784
|
progressMap.set(index, {
|
|
772
785
|
...structuredClone(progress),
|
|
@@ -820,7 +833,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
820
833
|
contextFile: contextFilePath,
|
|
821
834
|
enableLsp: false,
|
|
822
835
|
signal,
|
|
823
|
-
eventBus:
|
|
836
|
+
eventBus: this.session.eventBus,
|
|
824
837
|
onProgress: progress => {
|
|
825
838
|
progressMap.set(index, {
|
|
826
839
|
...structuredClone(progress),
|
|
@@ -864,7 +877,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
864
877
|
} catch (mergeErr) {
|
|
865
878
|
// Agent succeeded but branch commit failed — clean up stale branch
|
|
866
879
|
const branchName = `omp/task/${task.id}`;
|
|
867
|
-
await
|
|
880
|
+
await git.branch.tryDelete(repoRoot, branchName);
|
|
868
881
|
const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
869
882
|
return { ...result, error: `Merge failed: ${msg}` };
|
|
870
883
|
}
|
|
@@ -978,93 +991,90 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
978
991
|
let changesApplied: boolean | null = null;
|
|
979
992
|
let mergedBranchesForNestedPatches: Set<string> | null = null;
|
|
980
993
|
if (isIsolated && repoRoot) {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
if (branchEntries.length === 0) {
|
|
988
|
-
changesApplied = true;
|
|
989
|
-
} else {
|
|
990
|
-
const mergeResult = await mergeTaskBranches(repoRoot, branchEntries);
|
|
991
|
-
mergedBranchesForNestedPatches = new Set(mergeResult.merged);
|
|
992
|
-
changesApplied = mergeResult.failed.length === 0;
|
|
994
|
+
try {
|
|
995
|
+
if (mergeMode === "branch") {
|
|
996
|
+
// Branch mode: merge task branches sequentially
|
|
997
|
+
const branchEntries = results
|
|
998
|
+
.filter(r => r.branchName && r.exitCode === 0 && !r.aborted)
|
|
999
|
+
.map(r => ({ branchName: r.branchName!, taskId: r.id, description: r.description }));
|
|
993
1000
|
|
|
994
|
-
if (
|
|
995
|
-
|
|
1001
|
+
if (branchEntries.length === 0) {
|
|
1002
|
+
changesApplied = true;
|
|
996
1003
|
} else {
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1004
|
+
const mergeResult = await mergeTaskBranches(repoRoot, branchEntries);
|
|
1005
|
+
mergedBranchesForNestedPatches = new Set(mergeResult.merged);
|
|
1006
|
+
changesApplied = mergeResult.failed.length === 0;
|
|
1007
|
+
|
|
1008
|
+
if (changesApplied) {
|
|
1009
|
+
mergeSummary = `\n\nMerged ${mergeResult.merged.length} branch${mergeResult.merged.length === 1 ? "" : "es"}: ${mergeResult.merged.join(", ")}`;
|
|
1010
|
+
} else {
|
|
1011
|
+
const mergedPart =
|
|
1012
|
+
mergeResult.merged.length > 0 ? `Merged: ${mergeResult.merged.join(", ")}.\n` : "";
|
|
1013
|
+
const failedPart = `Failed: ${mergeResult.failed.join(", ")}.`;
|
|
1014
|
+
const conflictPart = mergeResult.conflict ? `\nConflict: ${mergeResult.conflict}` : "";
|
|
1015
|
+
mergeSummary = `\n\n<system-notification>Branch merge failed. ${mergedPart}${failedPart}${conflictPart}\nUnmerged branches remain for manual resolution.</system-notification>`;
|
|
1016
|
+
}
|
|
1002
1017
|
}
|
|
1003
|
-
}
|
|
1004
1018
|
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
} else {
|
|
1011
|
-
// Patch mode: combine and apply patches
|
|
1012
|
-
const patchesInOrder = results.map(result => result.patchPath).filter(Boolean) as string[];
|
|
1013
|
-
const missingPatch = results.some(result => !result.patchPath);
|
|
1014
|
-
if (missingPatch) {
|
|
1015
|
-
changesApplied = false;
|
|
1019
|
+
// Clean up merged branches (keep failed ones for manual resolution)
|
|
1020
|
+
const allBranches = branchEntries.map(b => b.branchName);
|
|
1021
|
+
if (changesApplied) {
|
|
1022
|
+
await cleanupTaskBranches(repoRoot, allBranches);
|
|
1023
|
+
}
|
|
1016
1024
|
} else {
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
);
|
|
1023
|
-
const nonEmptyPatches = patchStats.filter(patch => patch.size > 0).map(patch => patch.patchPath);
|
|
1024
|
-
if (nonEmptyPatches.length === 0) {
|
|
1025
|
-
changesApplied = true;
|
|
1025
|
+
// Patch mode: combine and apply patches
|
|
1026
|
+
const patchesInOrder = results.map(result => result.patchPath).filter(Boolean) as string[];
|
|
1027
|
+
const missingPatch = results.some(result => !result.patchPath);
|
|
1028
|
+
if (missingPatch) {
|
|
1029
|
+
changesApplied = false;
|
|
1026
1030
|
} else {
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1031
|
+
const patchStats = await Promise.all(
|
|
1032
|
+
patchesInOrder.map(async patchPath => ({
|
|
1033
|
+
patchPath,
|
|
1034
|
+
size: (await fs.stat(patchPath)).size,
|
|
1035
|
+
})),
|
|
1029
1036
|
);
|
|
1030
|
-
const
|
|
1031
|
-
if (
|
|
1037
|
+
const nonEmptyPatches = patchStats.filter(patch => patch.size > 0).map(patch => patch.patchPath);
|
|
1038
|
+
if (nonEmptyPatches.length === 0) {
|
|
1032
1039
|
changesApplied = true;
|
|
1033
1040
|
} else {
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
.
|
|
1047
|
-
|
|
1048
|
-
|
|
1041
|
+
const patchTexts = await Promise.all(
|
|
1042
|
+
nonEmptyPatches.map(async patchPath => Bun.file(patchPath).text()),
|
|
1043
|
+
);
|
|
1044
|
+
const combinedPatch = patchTexts
|
|
1045
|
+
.map(text => (text.endsWith("\n") ? text : `${text}\n`))
|
|
1046
|
+
.join("");
|
|
1047
|
+
if (!combinedPatch.trim()) {
|
|
1048
|
+
changesApplied = true;
|
|
1049
|
+
} else {
|
|
1050
|
+
changesApplied = await git.patch.canApplyText(repoRoot, combinedPatch);
|
|
1051
|
+
if (changesApplied) {
|
|
1052
|
+
try {
|
|
1053
|
+
await git.patch.applyText(repoRoot, combinedPatch);
|
|
1054
|
+
} catch {
|
|
1055
|
+
changesApplied = false;
|
|
1056
|
+
}
|
|
1049
1057
|
}
|
|
1050
|
-
} finally {
|
|
1051
|
-
await fs.rm(combinedPatchPath, { force: true });
|
|
1052
1058
|
}
|
|
1053
1059
|
}
|
|
1054
1060
|
}
|
|
1055
|
-
}
|
|
1056
1061
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1062
|
+
if (changesApplied) {
|
|
1063
|
+
mergeSummary = "\n\nApplied patches: yes";
|
|
1064
|
+
} else {
|
|
1065
|
+
const notification =
|
|
1066
|
+
"<system-notification>Patches were not applied and must be handled manually.</system-notification>";
|
|
1067
|
+
const patchList =
|
|
1068
|
+
patchPaths.length > 0
|
|
1069
|
+
? `\n\nPatch artifacts:\n${patchPaths.map(patch => `- ${patch}`).join("\n")}`
|
|
1070
|
+
: "";
|
|
1071
|
+
mergeSummary = `\n\n${notification}${patchList}`;
|
|
1072
|
+
}
|
|
1067
1073
|
}
|
|
1074
|
+
} catch (mergeErr) {
|
|
1075
|
+
const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
1076
|
+
changesApplied = false;
|
|
1077
|
+
mergeSummary = `\n\n<system-notification>Merge phase failed: ${msg}\nTask outputs are preserved but changes were not applied.</system-notification>`;
|
|
1068
1078
|
}
|
|
1069
1079
|
}
|
|
1070
1080
|
|
package/src/task/types.ts
CHANGED
|
@@ -31,6 +31,31 @@ export const TASK_SUBAGENT_EVENT_CHANNEL = "task:subagent:event";
|
|
|
31
31
|
/** EventBus channel for aggregated subagent progress */
|
|
32
32
|
export const TASK_SUBAGENT_PROGRESS_CHANNEL = "task:subagent:progress";
|
|
33
33
|
|
|
34
|
+
/** EventBus channel for subagent lifecycle (start/end) */
|
|
35
|
+
export const TASK_SUBAGENT_LIFECYCLE_CHANNEL = "task:subagent:lifecycle";
|
|
36
|
+
|
|
37
|
+
/** Payload emitted on TASK_SUBAGENT_PROGRESS_CHANNEL */
|
|
38
|
+
export interface SubagentProgressPayload {
|
|
39
|
+
index: number;
|
|
40
|
+
agent: string;
|
|
41
|
+
agentSource: AgentSource;
|
|
42
|
+
task: string;
|
|
43
|
+
assignment?: string;
|
|
44
|
+
progress: AgentProgress;
|
|
45
|
+
sessionFile?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Payload emitted on TASK_SUBAGENT_LIFECYCLE_CHANNEL */
|
|
49
|
+
export interface SubagentLifecyclePayload {
|
|
50
|
+
id: string;
|
|
51
|
+
agent: string;
|
|
52
|
+
agentSource: AgentSource;
|
|
53
|
+
description?: string;
|
|
54
|
+
status: "started" | "completed" | "failed" | "aborted";
|
|
55
|
+
sessionFile?: string;
|
|
56
|
+
index: number;
|
|
57
|
+
}
|
|
58
|
+
|
|
34
59
|
/** Single task item for parallel execution */
|
|
35
60
|
export const taskItemSchema = Type.Object({
|
|
36
61
|
id: Type.String({
|