@oh-my-pi/pi-coding-agent 13.18.0 → 14.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 +316 -1
- package/package.json +86 -24
- package/scripts/format-prompts.ts +2 -2
- package/src/autoresearch/apply-contract-to-state.ts +24 -0
- package/src/autoresearch/contract.ts +0 -44
- package/src/autoresearch/dashboard.ts +1 -2
- package/src/autoresearch/git.ts +116 -30
- package/src/autoresearch/helpers.ts +49 -0
- package/src/autoresearch/index.ts +28 -187
- package/src/autoresearch/prompt.md +26 -9
- package/src/autoresearch/state.ts +0 -6
- package/src/autoresearch/tools/init-experiment.ts +202 -117
- package/src/autoresearch/tools/log-experiment.ts +123 -178
- package/src/autoresearch/tools/run-experiment.ts +48 -10
- package/src/autoresearch/types.ts +2 -2
- package/src/capability/index.ts +4 -2
- package/src/cli/file-processor.ts +3 -3
- package/src/cli/grep-cli.ts +8 -8
- package/src/cli/grievances-cli.ts +78 -0
- package/src/cli/read-cli.ts +67 -0
- package/src/cli/setup-cli.ts +4 -4
- package/src/cli/update-cli.ts +3 -3
- package/src/cli.ts +2 -0
- package/src/commands/grep.ts +6 -1
- package/src/commands/grievances.ts +20 -0
- package/src/commands/read.ts +33 -0
- package/src/commit/agentic/agent.ts +5 -8
- package/src/commit/agentic/index.ts +22 -26
- package/src/commit/agentic/tools/analyze-file.ts +3 -3
- 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/agentic/validation.ts +1 -1
- package/src/commit/analysis/conventional.ts +4 -4
- package/src/commit/analysis/summary.ts +3 -3
- package/src/commit/changelog/generate.ts +4 -4
- package/src/commit/changelog/index.ts +5 -9
- package/src/commit/map-reduce/map-phase.ts +4 -4
- package/src/commit/map-reduce/reduce-phase.ts +4 -4
- package/src/commit/pipeline.ts +13 -16
- package/src/config/keybindings.ts +7 -6
- package/src/config/prompt-templates.ts +44 -226
- package/src/config/resolve-config-value.ts +4 -2
- package/src/config/settings-schema.ts +98 -2
- package/src/config/settings.ts +25 -26
- package/src/dap/client.ts +674 -0
- package/src/dap/config.ts +150 -0
- package/src/dap/defaults.json +211 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1255 -0
- package/src/dap/types.ts +600 -0
- package/src/debug/log-viewer.ts +3 -2
- package/src/discovery/builtin.ts +1 -2
- package/src/discovery/codex.ts +2 -2
- package/src/discovery/github.ts +2 -1
- package/src/discovery/helpers.ts +2 -2
- package/src/discovery/opencode.ts +2 -2
- package/src/edit/diff.ts +818 -0
- package/src/edit/index.ts +309 -0
- package/src/edit/line-hash.ts +67 -0
- package/src/edit/modes/chunk.ts +454 -0
- package/src/{patch → edit/modes}/hashline.ts +741 -361
- package/src/{patch/applicator.ts → edit/modes/patch.ts} +420 -117
- package/src/{patch/fuzzy.ts → edit/modes/replace.ts} +519 -197
- package/src/{patch → edit}/normalize.ts +97 -76
- package/src/{patch/shared.ts → edit/renderer.ts} +181 -108
- package/src/exec/bash-executor.ts +4 -2
- package/src/exec/idle-timeout-watchdog.ts +126 -0
- package/src/exec/non-interactive-env.ts +5 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +6 -18
- package/src/extensibility/custom-commands/bundled/review/index.ts +45 -43
- package/src/extensibility/custom-commands/loader.ts +1 -2
- package/src/extensibility/custom-tools/loader.ts +34 -11
- package/src/extensibility/custom-tools/types.ts +1 -1
- package/src/extensibility/extensions/loader.ts +9 -4
- package/src/extensibility/extensions/runner.ts +24 -1
- package/src/extensibility/extensions/types.ts +4 -2
- package/src/extensibility/hooks/loader.ts +5 -6
- package/src/extensibility/hooks/types.ts +2 -2
- package/src/extensibility/plugins/doctor.ts +2 -1
- package/src/extensibility/plugins/marketplace/fetcher.ts +2 -57
- package/src/extensibility/plugins/marketplace/source-resolver.ts +4 -4
- package/src/extensibility/slash-commands.ts +3 -7
- package/src/index.ts +3 -1
- package/src/internal-urls/docs-index.generated.ts +11 -11
- package/src/ipy/executor.ts +58 -17
- package/src/ipy/gateway-coordinator.ts +6 -4
- package/src/ipy/kernel.ts +45 -22
- package/src/ipy/runtime.ts +2 -2
- package/src/lsp/client.ts +7 -4
- package/src/lsp/clients/lsp-linter-client.ts +4 -4
- package/src/lsp/config.ts +2 -2
- package/src/lsp/defaults.json +688 -154
- package/src/lsp/index.ts +234 -45
- package/src/lsp/lspmux.ts +2 -2
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +12 -1
- package/src/lsp/utils.ts +8 -1
- package/src/main.ts +125 -47
- package/src/memories/index.ts +4 -5
- package/src/modes/acp/acp-agent.ts +563 -163
- package/src/modes/acp/acp-event-mapper.ts +9 -1
- package/src/modes/acp/acp-mode.ts +4 -2
- package/src/modes/components/agent-dashboard.ts +3 -4
- package/src/modes/components/diff.ts +6 -7
- 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/read-tool-group.ts +6 -12
- package/src/modes/components/session-observer-overlay.ts +472 -0
- package/src/modes/components/settings-defs.ts +24 -0
- package/src/modes/components/status-line.ts +15 -61
- package/src/modes/components/tool-execution.ts +1 -1
- package/src/modes/components/welcome.ts +1 -1
- package/src/modes/controllers/btw-controller.ts +2 -2
- package/src/modes/controllers/command-controller.ts +4 -2
- 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 +15 -8
- package/src/modes/controllers/selector-controller.ts +26 -0
- package/src/modes/index.ts +20 -2
- package/src/modes/interactive-mode.ts +278 -69
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/rpc-client.ts +178 -13
- package/src/modes/rpc/rpc-mode.ts +73 -3
- package/src/modes/rpc/rpc-types.ts +53 -1
- package/src/modes/session-observer-registry.ts +146 -0
- package/src/modes/shared.ts +0 -42
- package/src/modes/theme/theme.ts +80 -8
- package/src/modes/types.ts +4 -2
- package/src/modes/utils/keybinding-matchers.ts +9 -0
- package/src/prompts/system/custom-system-prompt.md +5 -0
- package/src/prompts/system/system-prompt.md +8 -1
- package/src/prompts/tools/chunk-edit.md +219 -0
- package/src/prompts/tools/debug.md +43 -0
- package/src/prompts/tools/grep.md +3 -0
- package/src/prompts/tools/lsp.md +5 -5
- package/src/prompts/tools/read-chunk.md +17 -0
- package/src/prompts/tools/read.md +19 -5
- package/src/sdk.ts +216 -165
- package/src/secrets/index.ts +1 -1
- package/src/secrets/obfuscator.ts +25 -17
- package/src/session/agent-session.ts +381 -286
- package/src/session/agent-storage.ts +12 -12
- package/src/session/compaction/branch-summarization.ts +3 -3
- package/src/session/compaction/compaction.ts +5 -6
- package/src/session/compaction/utils.ts +3 -3
- package/src/session/history-storage.ts +62 -19
- package/src/session/messages.ts +3 -3
- package/src/session/session-dump-format.ts +203 -0
- package/src/session/session-manager.ts +15 -5
- package/src/session/session-storage.ts +4 -2
- package/src/session/streaming-output.ts +1 -1
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +56 -8
- package/src/ssh/connection-manager.ts +2 -2
- package/src/ssh/sshfs-mount.ts +5 -5
- package/src/stt/downloader.ts +4 -4
- package/src/stt/recorder.ts +4 -4
- package/src/stt/transcriber.ts +2 -2
- package/src/system-prompt.ts +25 -13
- package/src/task/agents.ts +5 -6
- package/src/task/commands.ts +2 -5
- package/src/task/executor.ts +32 -4
- package/src/task/index.ts +91 -82
- package/src/task/template.ts +2 -2
- package/src/task/types.ts +25 -0
- package/src/task/worktree.ts +131 -149
- package/src/tools/ask.ts +2 -3
- package/src/tools/ast-edit.ts +7 -7
- package/src/tools/ast-grep.ts +7 -7
- package/src/tools/auto-generated-guard.ts +36 -41
- package/src/tools/await-tool.ts +2 -2
- package/src/tools/bash.ts +5 -23
- package/src/tools/browser.ts +4 -5
- package/src/tools/calculator.ts +2 -3
- package/src/tools/cancel-job.ts +2 -2
- package/src/tools/checkpoint.ts +3 -3
- package/src/tools/debug.ts +1007 -0
- package/src/tools/exit-plan-mode.ts +3 -3
- package/src/tools/fetch.ts +67 -3
- package/src/tools/find.ts +4 -5
- package/src/tools/fs-cache-invalidation.ts +5 -0
- package/src/tools/gemini-image.ts +13 -5
- package/src/tools/gh.ts +130 -308
- package/src/tools/grep.ts +57 -9
- package/src/tools/index.ts +44 -22
- package/src/tools/inspect-image.ts +4 -4
- package/src/tools/output-meta.ts +1 -1
- package/src/tools/python.ts +19 -6
- package/src/tools/read.ts +211 -146
- package/src/tools/render-mermaid.ts +2 -3
- package/src/tools/render-utils.ts +20 -6
- package/src/tools/renderers.ts +3 -1
- package/src/tools/report-tool-issue.ts +80 -0
- package/src/tools/resolve.ts +70 -39
- package/src/tools/search-tool-bm25.ts +2 -2
- package/src/tools/ssh.ts +2 -2
- package/src/tools/todo-write.ts +2 -2
- package/src/tools/tool-timeouts.ts +1 -0
- package/src/tools/write.ts +5 -6
- package/src/tui/tree-list.ts +3 -1
- package/src/utils/clipboard.ts +80 -0
- package/src/utils/commit-message-generator.ts +2 -3
- package/src/utils/edit-mode.ts +49 -0
- package/src/utils/external-editor.ts +11 -5
- package/src/utils/file-display-mode.ts +6 -5
- package/src/utils/file-mentions.ts +8 -7
- package/src/utils/git.ts +1400 -0
- package/src/utils/image-loading.ts +98 -0
- package/src/utils/title-generator.ts +2 -3
- package/src/utils/tools-manager.ts +6 -6
- package/src/web/scrapers/choosealicense.ts +1 -1
- package/src/web/search/index.ts +3 -3
- package/src/web/search/render.ts +6 -4
- package/src/autoresearch/command-initialize.md +0 -34
- 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/patch/diff.ts +0 -433
- package/src/patch/index.ts +0 -888
- package/src/patch/parser.ts +0 -532
- package/src/patch/types.ts +0 -292
- package/src/prompts/agents/oracle.md +0 -77
- package/src/tools/gh-cli.ts +0 -125
- package/src/tools/pending-action.ts +0 -49
- package/src/utils/child-process.ts +0 -88
- package/src/utils/frontmatter.ts +0 -117
- package/src/utils/image-input.ts +0 -274
- package/src/utils/mime.ts +0 -53
- package/src/utils/prompt-format.ts +0 -170
package/src/task/executor.ts
CHANGED
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
import path from "node:path";
|
|
7
7
|
import type { AgentEvent, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
8
8
|
import type { SearchDb } from "@oh-my-pi/pi-natives";
|
|
9
|
-
import { logger, untilAborted } from "@oh-my-pi/pi-utils";
|
|
9
|
+
import { logger, prompt, untilAborted } from "@oh-my-pi/pi-utils";
|
|
10
10
|
import type { TSchema } from "@sinclair/typebox";
|
|
11
11
|
import Ajv, { type ValidateFunction } from "ajv";
|
|
12
12
|
import { ModelRegistry } from "../config/model-registry";
|
|
13
13
|
import { resolveModelOverride } from "../config/model-resolver";
|
|
14
|
-
import {
|
|
14
|
+
import type { PromptTemplate } from "../config/prompt-templates";
|
|
15
15
|
import { Settings } from "../config/settings";
|
|
16
16
|
import { SETTINGS_SCHEMA, type SettingPath } from "../config/settings-schema";
|
|
17
17
|
import type { CustomTool } from "../extensibility/custom-tools/types";
|
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
type ReviewFinding,
|
|
39
39
|
type SingleResult,
|
|
40
40
|
TASK_SUBAGENT_EVENT_CHANNEL,
|
|
41
|
+
TASK_SUBAGENT_LIFECYCLE_CHANNEL,
|
|
41
42
|
TASK_SUBAGENT_PROGRESS_CHANNEL,
|
|
42
43
|
} from "./types";
|
|
43
44
|
|
|
@@ -630,6 +631,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
630
631
|
task,
|
|
631
632
|
assignment,
|
|
632
633
|
progress: { ...progress },
|
|
634
|
+
sessionFile: subtaskSessionFile,
|
|
633
635
|
});
|
|
634
636
|
}
|
|
635
637
|
lastProgressEmitMs = Date.now();
|
|
@@ -963,7 +965,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
963
965
|
skills: options.skills,
|
|
964
966
|
promptTemplates: options.promptTemplates,
|
|
965
967
|
systemPrompt: defaultPrompt =>
|
|
966
|
-
|
|
968
|
+
prompt.render(subagentSystemPromptTemplate, {
|
|
967
969
|
base: defaultPrompt,
|
|
968
970
|
agent: agent.systemPrompt,
|
|
969
971
|
worktree: worktree ?? "",
|
|
@@ -983,6 +985,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
983
985
|
|
|
984
986
|
activeSession = session;
|
|
985
987
|
|
|
988
|
+
// Emit lifecycle start event
|
|
989
|
+
if (options.eventBus) {
|
|
990
|
+
options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
|
|
991
|
+
id,
|
|
992
|
+
agent: agent.name,
|
|
993
|
+
agentSource: agent.source,
|
|
994
|
+
description: options.description,
|
|
995
|
+
status: "started",
|
|
996
|
+
sessionFile: subtaskSessionFile,
|
|
997
|
+
index,
|
|
998
|
+
});
|
|
999
|
+
}
|
|
1000
|
+
|
|
986
1001
|
const subagentToolNames = session.getActiveToolNames();
|
|
987
1002
|
const parentOwnedToolNames = new Set(["todo_write"]);
|
|
988
1003
|
const filteredSubagentTools = subagentToolNames.filter(name => !parentOwnedToolNames.has(name));
|
|
@@ -1091,7 +1106,7 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1091
1106
|
while (!submitResultCalled && retryCount < MAX_SUBMIT_RESULT_RETRIES && !abortSignal.aborted) {
|
|
1092
1107
|
try {
|
|
1093
1108
|
retryCount++;
|
|
1094
|
-
const reminder =
|
|
1109
|
+
const reminder = prompt.render(submitReminderTemplate, {
|
|
1095
1110
|
retryCount,
|
|
1096
1111
|
maxRetries: MAX_SUBMIT_RESULT_RETRIES,
|
|
1097
1112
|
});
|
|
@@ -1238,6 +1253,19 @@ export async function runSubprocess(options: ExecutorOptions): Promise<SingleRes
|
|
|
1238
1253
|
progress.status = wasAborted ? "aborted" : exitCode === 0 ? "completed" : "failed";
|
|
1239
1254
|
scheduleProgress(true);
|
|
1240
1255
|
|
|
1256
|
+
// Emit lifecycle end event after finalization so submit_result status is reflected
|
|
1257
|
+
if (options.eventBus) {
|
|
1258
|
+
options.eventBus.emit(TASK_SUBAGENT_LIFECYCLE_CHANNEL, {
|
|
1259
|
+
id,
|
|
1260
|
+
agent: agent.name,
|
|
1261
|
+
agentSource: agent.source,
|
|
1262
|
+
description: options.description,
|
|
1263
|
+
status: progress.status as "completed" | "failed" | "aborted",
|
|
1264
|
+
sessionFile: subtaskSessionFile,
|
|
1265
|
+
index,
|
|
1266
|
+
});
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1241
1269
|
return {
|
|
1242
1270
|
index,
|
|
1243
1271
|
id,
|
package/src/task/index.ts
CHANGED
|
@@ -17,11 +17,9 @@ import * as os from "node:os";
|
|
|
17
17
|
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
|
-
import { $env, Snowflake } from "@oh-my-pi/pi-utils";
|
|
21
|
-
import { $ } from "bun";
|
|
20
|
+
import { $env, prompt, Snowflake } from "@oh-my-pi/pi-utils";
|
|
22
21
|
import type { ToolSession } from "..";
|
|
23
22
|
import { resolveAgentModelPatterns } from "../config/model-resolver";
|
|
24
|
-
import { renderPromptTemplate } from "../config/prompt-templates";
|
|
25
23
|
import type { Theme } from "../modes/theme/theme";
|
|
26
24
|
import planModeSubagentPrompt from "../prompts/system/plan-mode-subagent.md" with { type: "text" };
|
|
27
25
|
import taskDescriptionTemplate from "../prompts/tools/task.md" with { type: "text" };
|
|
@@ -30,6 +28,7 @@ import { formatBytes, formatDuration } from "../tools/render-utils";
|
|
|
30
28
|
// Import review tools for side effects (registers subagent tool handlers)
|
|
31
29
|
import "../tools/review";
|
|
32
30
|
import { generateCommitMessage } from "../utils/commit-message-generator";
|
|
31
|
+
import * as git from "../utils/git";
|
|
33
32
|
import { discoverAgents, getAgent } from "./discovery";
|
|
34
33
|
import { runSubprocess } from "./executor";
|
|
35
34
|
import { resolveIsolationBackendForTaskExecution } from "./isolation-backend";
|
|
@@ -109,8 +108,21 @@ export { loadBundledAgents as BUNDLED_AGENTS } from "./agents";
|
|
|
109
108
|
export { discoverCommands, expandCommand, getCommand } from "./commands";
|
|
110
109
|
export { discoverAgents, getAgent } from "./discovery";
|
|
111
110
|
export { AgentOutputManager } from "./output-manager";
|
|
112
|
-
export type {
|
|
113
|
-
|
|
111
|
+
export type {
|
|
112
|
+
AgentDefinition,
|
|
113
|
+
AgentProgress,
|
|
114
|
+
SingleResult,
|
|
115
|
+
SubagentLifecyclePayload,
|
|
116
|
+
SubagentProgressPayload,
|
|
117
|
+
TaskParams,
|
|
118
|
+
TaskToolDetails,
|
|
119
|
+
} from "./types";
|
|
120
|
+
export {
|
|
121
|
+
TASK_SUBAGENT_EVENT_CHANNEL,
|
|
122
|
+
TASK_SUBAGENT_LIFECYCLE_CHANNEL,
|
|
123
|
+
TASK_SUBAGENT_PROGRESS_CHANNEL,
|
|
124
|
+
taskSchema,
|
|
125
|
+
} from "./types";
|
|
114
126
|
|
|
115
127
|
/**
|
|
116
128
|
* Render the tool description from a cached agent list and current settings.
|
|
@@ -123,7 +135,7 @@ function renderDescription(
|
|
|
123
135
|
disabledAgents: string[],
|
|
124
136
|
): string {
|
|
125
137
|
const filteredAgents = disabledAgents.length > 0 ? agents.filter(a => !disabledAgents.includes(a.name)) : agents;
|
|
126
|
-
return
|
|
138
|
+
return prompt.render(taskDescriptionTemplate, {
|
|
127
139
|
agents: filteredAgents,
|
|
128
140
|
MAX_CONCURRENCY: maxConcurrency,
|
|
129
141
|
isolationEnabled,
|
|
@@ -766,7 +778,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
766
778
|
contextFile: contextFilePath,
|
|
767
779
|
enableLsp: false,
|
|
768
780
|
signal,
|
|
769
|
-
eventBus:
|
|
781
|
+
eventBus: this.session.eventBus,
|
|
770
782
|
onProgress: progress => {
|
|
771
783
|
progressMap.set(index, {
|
|
772
784
|
...structuredClone(progress),
|
|
@@ -820,7 +832,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
820
832
|
contextFile: contextFilePath,
|
|
821
833
|
enableLsp: false,
|
|
822
834
|
signal,
|
|
823
|
-
eventBus:
|
|
835
|
+
eventBus: this.session.eventBus,
|
|
824
836
|
onProgress: progress => {
|
|
825
837
|
progressMap.set(index, {
|
|
826
838
|
...structuredClone(progress),
|
|
@@ -864,7 +876,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
864
876
|
} catch (mergeErr) {
|
|
865
877
|
// Agent succeeded but branch commit failed — clean up stale branch
|
|
866
878
|
const branchName = `omp/task/${task.id}`;
|
|
867
|
-
await
|
|
879
|
+
await git.branch.tryDelete(repoRoot, branchName);
|
|
868
880
|
const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
869
881
|
return { ...result, error: `Merge failed: ${msg}` };
|
|
870
882
|
}
|
|
@@ -978,93 +990,90 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
978
990
|
let changesApplied: boolean | null = null;
|
|
979
991
|
let mergedBranchesForNestedPatches: Set<string> | null = null;
|
|
980
992
|
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;
|
|
993
|
+
try {
|
|
994
|
+
if (mergeMode === "branch") {
|
|
995
|
+
// Branch mode: merge task branches sequentially
|
|
996
|
+
const branchEntries = results
|
|
997
|
+
.filter(r => r.branchName && r.exitCode === 0 && !r.aborted)
|
|
998
|
+
.map(r => ({ branchName: r.branchName!, taskId: r.id, description: r.description }));
|
|
993
999
|
|
|
994
|
-
if (
|
|
995
|
-
|
|
1000
|
+
if (branchEntries.length === 0) {
|
|
1001
|
+
changesApplied = true;
|
|
996
1002
|
} else {
|
|
997
|
-
const
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1003
|
+
const mergeResult = await mergeTaskBranches(repoRoot, branchEntries);
|
|
1004
|
+
mergedBranchesForNestedPatches = new Set(mergeResult.merged);
|
|
1005
|
+
changesApplied = mergeResult.failed.length === 0;
|
|
1006
|
+
|
|
1007
|
+
if (changesApplied) {
|
|
1008
|
+
mergeSummary = `\n\nMerged ${mergeResult.merged.length} branch${mergeResult.merged.length === 1 ? "" : "es"}: ${mergeResult.merged.join(", ")}`;
|
|
1009
|
+
} else {
|
|
1010
|
+
const mergedPart =
|
|
1011
|
+
mergeResult.merged.length > 0 ? `Merged: ${mergeResult.merged.join(", ")}.\n` : "";
|
|
1012
|
+
const failedPart = `Failed: ${mergeResult.failed.join(", ")}.`;
|
|
1013
|
+
const conflictPart = mergeResult.conflict ? `\nConflict: ${mergeResult.conflict}` : "";
|
|
1014
|
+
mergeSummary = `\n\n<system-notification>Branch merge failed. ${mergedPart}${failedPart}${conflictPart}\nUnmerged branches remain for manual resolution.</system-notification>`;
|
|
1015
|
+
}
|
|
1002
1016
|
}
|
|
1003
|
-
}
|
|
1004
1017
|
|
|
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;
|
|
1018
|
+
// Clean up merged branches (keep failed ones for manual resolution)
|
|
1019
|
+
const allBranches = branchEntries.map(b => b.branchName);
|
|
1020
|
+
if (changesApplied) {
|
|
1021
|
+
await cleanupTaskBranches(repoRoot, allBranches);
|
|
1022
|
+
}
|
|
1016
1023
|
} 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;
|
|
1024
|
+
// Patch mode: combine and apply patches
|
|
1025
|
+
const patchesInOrder = results.map(result => result.patchPath).filter(Boolean) as string[];
|
|
1026
|
+
const missingPatch = results.some(result => !result.patchPath);
|
|
1027
|
+
if (missingPatch) {
|
|
1028
|
+
changesApplied = false;
|
|
1026
1029
|
} else {
|
|
1027
|
-
const
|
|
1028
|
-
|
|
1030
|
+
const patchStats = await Promise.all(
|
|
1031
|
+
patchesInOrder.map(async patchPath => ({
|
|
1032
|
+
patchPath,
|
|
1033
|
+
size: (await fs.stat(patchPath)).size,
|
|
1034
|
+
})),
|
|
1029
1035
|
);
|
|
1030
|
-
const
|
|
1031
|
-
if (
|
|
1036
|
+
const nonEmptyPatches = patchStats.filter(patch => patch.size > 0).map(patch => patch.patchPath);
|
|
1037
|
+
if (nonEmptyPatches.length === 0) {
|
|
1032
1038
|
changesApplied = true;
|
|
1033
1039
|
} else {
|
|
1034
|
-
const
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
.
|
|
1047
|
-
|
|
1048
|
-
|
|
1040
|
+
const patchTexts = await Promise.all(
|
|
1041
|
+
nonEmptyPatches.map(async patchPath => Bun.file(patchPath).text()),
|
|
1042
|
+
);
|
|
1043
|
+
const combinedPatch = patchTexts
|
|
1044
|
+
.map(text => (text.endsWith("\n") ? text : `${text}\n`))
|
|
1045
|
+
.join("");
|
|
1046
|
+
if (!combinedPatch.trim()) {
|
|
1047
|
+
changesApplied = true;
|
|
1048
|
+
} else {
|
|
1049
|
+
changesApplied = await git.patch.canApplyText(repoRoot, combinedPatch);
|
|
1050
|
+
if (changesApplied) {
|
|
1051
|
+
try {
|
|
1052
|
+
await git.patch.applyText(repoRoot, combinedPatch);
|
|
1053
|
+
} catch {
|
|
1054
|
+
changesApplied = false;
|
|
1055
|
+
}
|
|
1049
1056
|
}
|
|
1050
|
-
} finally {
|
|
1051
|
-
await fs.rm(combinedPatchPath, { force: true });
|
|
1052
1057
|
}
|
|
1053
1058
|
}
|
|
1054
1059
|
}
|
|
1055
|
-
}
|
|
1056
1060
|
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1061
|
+
if (changesApplied) {
|
|
1062
|
+
mergeSummary = "\n\nApplied patches: yes";
|
|
1063
|
+
} else {
|
|
1064
|
+
const notification =
|
|
1065
|
+
"<system-notification>Patches were not applied and must be handled manually.</system-notification>";
|
|
1066
|
+
const patchList =
|
|
1067
|
+
patchPaths.length > 0
|
|
1068
|
+
? `\n\nPatch artifacts:\n${patchPaths.map(patch => `- ${patch}`).join("\n")}`
|
|
1069
|
+
: "";
|
|
1070
|
+
mergeSummary = `\n\n${notification}${patchList}`;
|
|
1071
|
+
}
|
|
1067
1072
|
}
|
|
1073
|
+
} catch (mergeErr) {
|
|
1074
|
+
const msg = mergeErr instanceof Error ? mergeErr.message : String(mergeErr);
|
|
1075
|
+
changesApplied = false;
|
|
1076
|
+
mergeSummary = `\n\n<system-notification>Merge phase failed: ${msg}\nTask outputs are preserved but changes were not applied.</system-notification>`;
|
|
1068
1077
|
}
|
|
1069
1078
|
}
|
|
1070
1079
|
|
|
@@ -1147,7 +1156,7 @@ export class TaskTool implements AgentTool<TaskSchema, TaskToolDetails, Theme> {
|
|
|
1147
1156
|
|
|
1148
1157
|
const outputIds = results.filter(r => !r.aborted || r.output.trim()).map(r => `agent://${r.id}`);
|
|
1149
1158
|
const backendSummaryPrefix = isolationBackendWarning ? `\n\n${isolationBackendWarning}` : "";
|
|
1150
|
-
const summary =
|
|
1159
|
+
const summary = prompt.render(taskSummaryTemplate, {
|
|
1151
1160
|
successCount,
|
|
1152
1161
|
totalCount: results.length,
|
|
1153
1162
|
cancelledCount,
|
package/src/task/template.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { prompt } from "@oh-my-pi/pi-utils";
|
|
2
2
|
import subagentUserPromptTemplate from "../prompts/system/subagent-user-prompt.md" with { type: "text" };
|
|
3
3
|
import type { TaskItem } from "./types";
|
|
4
4
|
|
|
@@ -25,7 +25,7 @@ export function renderTemplate(context: string | undefined, task: TaskItem): Ren
|
|
|
25
25
|
return { task: assignment || context!, assignment: assignment || context!, id, description };
|
|
26
26
|
}
|
|
27
27
|
return {
|
|
28
|
-
task:
|
|
28
|
+
task: prompt.render(subagentUserPromptTemplate, { context, assignment }),
|
|
29
29
|
assignment,
|
|
30
30
|
id,
|
|
31
31
|
description,
|
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({
|