pi-subagents 0.50.0 → 0.52.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 +103 -0
- package/agents/oracle.md +3 -1
- package/agents/reviewer.md +1 -0
- package/agents/scout.md +2 -2
- package/agents/worker.md +2 -1
- package/async-retention-discovery-worker.mjs +180 -0
- package/docs/agents.md +40 -2
- package/docs/configuration.md +30 -12
- package/docs/extension-api.md +42 -1
- package/docs/models.md +2 -0
- package/docs/observability.md +41 -5
- package/docs/tool-reference.md +38 -39
- package/docs/workflows.md +171 -3
- package/package.json +4 -2
- package/skills/pi-subagents/SKILL.md +6 -4
- package/skills/pi-subagents/references/constraints-and-recipes.md +12 -6
- package/skills/pi-subagents/references/execution-controls.md +29 -15
- package/skills/pi-subagents/references/management-authoring-rpc.md +3 -3
- package/skills/pi-subagents/references/prompting-and-roles.md +4 -2
- package/src/agents/agent-management.ts +124 -351
- package/src/agents/agents.ts +157 -31
- package/src/agents/skills.ts +1 -1
- package/src/api/external-job-provider.ts +185 -0
- package/src/api/preflight.ts +36 -8
- package/src/api/shared-types.ts +2 -0
- package/src/extension/config.ts +3 -3
- package/src/extension/doctor.ts +3 -6
- package/src/extension/fanout-child.ts +2 -2
- package/src/extension/index.ts +166 -88
- package/src/extension/public-execution.ts +31 -2
- package/src/extension/schemas.ts +12 -35
- package/src/extension/tool-description.ts +35 -24
- package/src/inspectors/herdr/actions.ts +2 -2
- package/src/inspectors/herdr/inspector-runner.ts +2 -1
- package/src/inspectors/herdr/project-panes.ts +2 -2
- package/src/intercom/native-supervisor-channel.ts +32 -10
- package/src/missions/lifecycle.ts +6 -1
- package/src/missions/store.ts +4 -9
- package/src/missions/workflow-state.ts +2 -2
- package/src/profiles/profiles.ts +3 -1
- package/src/runs/background/active-run-index.ts +31 -8
- package/src/runs/background/async-execution.ts +68 -40
- package/src/runs/background/async-job-tracker.ts +20 -4
- package/src/runs/background/async-resume.ts +47 -15
- package/src/runs/background/async-retention.ts +886 -0
- package/src/runs/background/async-status.ts +39 -53
- package/src/runs/background/chain-append.ts +3 -33
- package/src/runs/background/completion-dedupe.ts +5 -1
- package/src/runs/background/completion-replay.ts +22 -12
- package/src/runs/background/control-channel.ts +14 -68
- package/src/runs/background/fleet-view.ts +68 -19
- package/src/runs/background/index-segment.ts +59 -0
- package/src/runs/background/inspect-rpc.ts +443 -0
- package/src/runs/background/notify.ts +31 -5
- package/src/runs/background/result-files.ts +158 -90
- package/src/runs/background/result-watcher.ts +116 -20
- package/src/runs/background/resume-guidance.ts +8 -5
- package/src/runs/background/retained-children.ts +13 -3
- package/src/runs/background/run-id-query.ts +7 -0
- package/src/runs/background/run-id-resolver.ts +11 -9
- package/src/runs/background/run-status.ts +27 -18
- package/src/runs/background/scheduled-runs.ts +24 -4
- package/src/runs/background/stale-run-reconciler.ts +6 -3
- package/src/runs/background/steering.ts +11 -1
- package/src/runs/background/subagent-runner.ts +253 -140
- package/src/runs/background/subagent-wait.ts +8 -8
- package/src/runs/background/terminal-run-index.ts +129 -0
- package/src/runs/background/wait-completions.ts +21 -4
- package/src/runs/background/wait-subscriptions.ts +81 -2
- package/src/runs/foreground/async-steering-action.ts +21 -14
- package/src/runs/foreground/execution.ts +3 -1
- package/src/runs/foreground/subagent-executor.ts +666 -1579
- package/src/runs/foreground/workflow-detach-reconcile.ts +194 -0
- package/src/runs/foreground/workflow-foreground-steering.ts +6 -5
- package/src/runs/shared/acceptance.ts +4 -4
- package/src/runs/shared/chain-outputs.ts +1 -3
- package/src/runs/shared/external-job-bridge.ts +444 -0
- package/src/runs/shared/external-job-runner.ts +286 -0
- package/src/runs/shared/mcp-direct-tool-allowlist.ts +14 -0
- package/src/runs/shared/model-fallback.ts +98 -38
- package/src/runs/shared/orca-progress-tabs.ts +84 -22
- package/src/runs/shared/parallel-handoff.ts +46 -4
- package/src/runs/shared/parallel-utils.ts +4 -15
- package/src/runs/shared/permissions.ts +5 -1
- package/src/runs/shared/pi-args.ts +8 -1
- package/src/runs/shared/session-lease.ts +0 -6
- package/src/runs/shared/subagent-control.ts +26 -4
- package/src/runs/shared/subagent-prompt-runtime.ts +12 -6
- package/src/runs/shared/workflow-graph.ts +1 -23
- package/src/runs/shared/worktree.ts +14 -2
- package/src/shared/atomic-json.ts +22 -2
- package/src/shared/capacity-resilient-json.ts +102 -0
- package/src/shared/completion-owner.ts +14 -0
- package/src/shared/file-system-retry.ts +49 -1
- package/src/shared/fork-context.ts +42 -0
- package/src/shared/prompt-resources.ts +0 -40
- package/src/shared/settings.ts +3 -27
- package/src/shared/types.ts +71 -26
- package/src/shared/utils.ts +8 -0
- package/src/shared/watch-strategy.ts +10 -0
- package/src/slash/slash-bridge.ts +2 -1
- package/src/slash/slash-commands.ts +29 -3
- package/src/tui/fleet.ts +63 -15
- package/src/watchdog/change-signature.ts +1 -1
- package/src/watchdog/lsp-diagnostics.ts +1 -0
- package/src/workflows/chat-progress.ts +2 -2
- package/src/workflows/scripted-workflow.ts +220 -67
- package/src/runs/foreground/chain-clarify.ts +0 -1354
- package/src/runs/foreground/chain-execution.ts +0 -1581
|
@@ -39,6 +39,7 @@ interface EventBus {
|
|
|
39
39
|
|
|
40
40
|
interface SlashBridgeOptions {
|
|
41
41
|
events: EventBus;
|
|
42
|
+
asyncByDefault: boolean;
|
|
42
43
|
getContext: () => ExtensionContext | null;
|
|
43
44
|
execute: (
|
|
44
45
|
id: string,
|
|
@@ -79,7 +80,7 @@ export function registerSlashSubagentBridge(options: SlashBridgeOptions): {
|
|
|
79
80
|
const request = data as Partial<SlashSubagentRequest>;
|
|
80
81
|
if (typeof request.requestId !== "string" || !request.params) return;
|
|
81
82
|
const { requestId } = request as SlashSubagentRequest;
|
|
82
|
-
const normalized = normalizePublicSubagentExecution((request as SlashSubagentRequest).params);
|
|
83
|
+
const normalized = normalizePublicSubagentExecution((request as SlashSubagentRequest).params, { asyncByDefault: options.asyncByDefault });
|
|
83
84
|
if (!normalized.ok) {
|
|
84
85
|
options.events.emit(SLASH_SUBAGENT_RESPONSE_EVENT, {
|
|
85
86
|
requestId,
|
|
@@ -3,7 +3,7 @@ import * as fs from "node:fs";
|
|
|
3
3
|
import * as path from "node:path";
|
|
4
4
|
import { keyText, type ExtensionAPI, type ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
5
5
|
import { Key, matchesKey, truncateToWidth, type Component, type KeyId, type TUI } from "@earendil-works/pi-tui";
|
|
6
|
-
import { BUILTIN_AGENT_NAMES, discoverAgents } from "../agents/agents.ts";
|
|
6
|
+
import { BUILTIN_AGENT_NAMES, discoverAgents, findBlockingAgentDiagnostic, resolveAgentName } from "../agents/agents.ts";
|
|
7
7
|
import { resolveExistingReadPaths } from "../shared/settings.ts";
|
|
8
8
|
import {
|
|
9
9
|
DEFAULT_PROVIDER_MODELS_MAX_AGE_DAYS,
|
|
@@ -18,6 +18,7 @@ import type { SubagentParamsLike } from "../runs/foreground/subagent-executor.ts
|
|
|
18
18
|
import { findModelInfo, toModelInfo } from "../shared/model-info.ts";
|
|
19
19
|
import { formatTokens, shortenPath } from "../shared/formatters.ts";
|
|
20
20
|
import { listAsyncRuns, formatAsyncRunProgressLabel, type AsyncRunSummary } from "../runs/background/async-status.ts";
|
|
21
|
+
import { encodeInspectReply, handleInspectRpcArgs, INSPECT_WIDGET_KEY } from "../runs/background/inspect-rpc.ts";
|
|
21
22
|
import { listScheduledRunSummaries } from "../runs/background/scheduled-runs.ts";
|
|
22
23
|
import { SUBAGENT_FANOUT_CHILD_ENV } from "../runs/shared/pi-args.ts";
|
|
23
24
|
import type { SlashSubagentResponse, SlashSubagentUpdate } from "./slash-bridge.ts";
|
|
@@ -671,8 +672,16 @@ export function registerSlashCommands(
|
|
|
671
672
|
const task = firstSpace === -1 ? "" : input.slice(firstSpace + 1).trim();
|
|
672
673
|
|
|
673
674
|
if (!state.baseCwd) { ctx.ui.notify("Subagent session cwd is not initialized yet", "error"); return; }
|
|
674
|
-
const
|
|
675
|
-
|
|
675
|
+
const discovered = discoverAgents(state.baseCwd, "both");
|
|
676
|
+
const resolvedAgent = resolveAgentName(agentName, discovered.agents);
|
|
677
|
+
const candidates = resolvedAgent.error
|
|
678
|
+
? discovered.agents.filter((agent) => resolveAgentName(agentName, [agent]).agent)
|
|
679
|
+
: resolvedAgent.agent;
|
|
680
|
+
const diagnostic = findBlockingAgentDiagnostic(agentName, candidates, discovered.agentDiagnostics);
|
|
681
|
+
if (diagnostic || resolvedAgent.error || !resolvedAgent.agent) {
|
|
682
|
+
ctx.ui.notify(diagnostic ? `Agent '${agentName}' has invalid configuration: ${diagnostic.error}` : resolvedAgent.error ?? `Unknown agent: ${agentName}`, "error");
|
|
683
|
+
return;
|
|
684
|
+
}
|
|
676
685
|
|
|
677
686
|
let finalTask = task;
|
|
678
687
|
if (inline.reads && Array.isArray(inline.reads) && inline.reads.length > 0) {
|
|
@@ -703,6 +712,23 @@ export function registerSlashCommands(
|
|
|
703
712
|
},
|
|
704
713
|
});
|
|
705
714
|
|
|
715
|
+
pi.registerCommand("subagents-inspect-rpc", {
|
|
716
|
+
description: "Host integration bridge: answer an async child inspection request with a correlated widget payload (no model turn)",
|
|
717
|
+
handler: async (args, ctx) => {
|
|
718
|
+
if (ctx.mode === "tui") {
|
|
719
|
+
ctx.ui.notify("Inspection replies are emitted only on RPC surfaces. Use /subagents or subagent({ action: \"status\", view: \"transcript\" }) interactively.", "info");
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
722
|
+
if (!ctx.hasUI) return;
|
|
723
|
+
const reply = handleInspectRpcArgs(args, { state });
|
|
724
|
+
// Emit-then-retract in one handler: stdio delivers the two widget
|
|
725
|
+
// updates in order, the host buffers the payload by requestId, and
|
|
726
|
+
// the dedicated key never accumulates visible state.
|
|
727
|
+
ctx.ui.setWidget(INSPECT_WIDGET_KEY, encodeInspectReply(reply));
|
|
728
|
+
ctx.ui.setWidget(INSPECT_WIDGET_KEY, undefined);
|
|
729
|
+
},
|
|
730
|
+
});
|
|
731
|
+
|
|
706
732
|
pi.registerCommand("subagents-guide", {
|
|
707
733
|
description: "Show a packaged subagents guide topic",
|
|
708
734
|
getArgumentCompletions: (prefix) => prefix.includes(" ") ? null : SUBAGENT_GUIDE_TOPICS
|
package/src/tui/fleet.ts
CHANGED
|
@@ -14,10 +14,12 @@ import { listAsyncRuns, type AsyncRunSummary } from "../runs/background/async-st
|
|
|
14
14
|
import { steerAsyncRun } from "../runs/foreground/async-steering-action.ts";
|
|
15
15
|
import type { SteerDeliveryMode } from "../runs/background/control-channel.ts";
|
|
16
16
|
import { stopAsyncRun } from "../runs/foreground/async-stop-action.ts";
|
|
17
|
+
import { resolveWorkflowForegroundSteeringTarget, steerWorkflowForegroundTarget } from "../runs/foreground/workflow-foreground-steering.ts";
|
|
17
18
|
import { contextModeBadge, contextModeLabel } from "../runs/shared/context-mode.ts";
|
|
18
19
|
import { FLEET_STATUS_WIDGET_KEY } from "./fleet-status.ts";
|
|
19
20
|
import { readFleetTranscript, renderFleetTranscript, type FleetTranscript } from "./fleet-transcript.ts";
|
|
20
21
|
import { handleHerdrInspectorAction } from "../inspectors/herdr/actions.ts";
|
|
22
|
+
import type { HerdrClient } from "../inspectors/herdr/client.ts";
|
|
21
23
|
import { getLivePromptAudit, type LivePromptAudit, type PromptAuditView } from "../runs/foreground/prompt-audit.ts";
|
|
22
24
|
|
|
23
25
|
const REFRESH_MS = 750;
|
|
@@ -108,6 +110,7 @@ export interface FleetViewOptions {
|
|
|
108
110
|
fleetKeybindings?: FleetKeybindingsConfig;
|
|
109
111
|
actions?: FleetActionHandlers;
|
|
110
112
|
copyText?: (text: string) => Promise<void> | void;
|
|
113
|
+
herdrClient?: HerdrClient;
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
function belongsToCurrentSession(sessionId: string | undefined, currentSessionId: string | null): boolean {
|
|
@@ -193,9 +196,22 @@ export function collectFleetSnapshot(
|
|
|
193
196
|
const workflowParentIds = new Set([...trackedJobs.values()]
|
|
194
197
|
.filter((job) => job.mode === "workflow" && belongsToCurrentSession(job.sessionId, state.currentSessionId))
|
|
195
198
|
.map((job) => job.asyncId));
|
|
199
|
+
const workflowForegroundChildCounts = new Map<string, number>();
|
|
200
|
+
const liveWorkflowForegroundControls = new Set<ForegroundRunControl>();
|
|
201
|
+
for (const control of state.foregroundControls.values()) {
|
|
202
|
+
const activeChildCount = control.activeChildren?.size ?? 0;
|
|
203
|
+
if (!control.parentWorkflowRunId
|
|
204
|
+
|| !workflowParentIds.has(control.parentWorkflowRunId)
|
|
205
|
+
|| !belongsToCurrentSession(control.sessionId, state.currentSessionId)
|
|
206
|
+
|| !control.workflowSteeringDir
|
|
207
|
+
|| activeChildCount === 0) continue;
|
|
208
|
+
liveWorkflowForegroundControls.add(control);
|
|
209
|
+
workflowForegroundChildCounts.set(control.parentWorkflowRunId, (workflowForegroundChildCounts.get(control.parentWorkflowRunId) ?? 0) + activeChildCount);
|
|
210
|
+
}
|
|
196
211
|
for (const control of [...state.foregroundControls.values()].sort((left, right) => right.updatedAt - left.updatedAt)) {
|
|
197
212
|
activeForegroundIds.add(control.runId);
|
|
198
|
-
if (control.parentWorkflowRunId && workflowParentIds.has(control.parentWorkflowRunId)
|
|
213
|
+
if (control.parentWorkflowRunId && workflowParentIds.has(control.parentWorkflowRunId)
|
|
214
|
+
&& ((workflowForegroundChildCounts.get(control.parentWorkflowRunId) ?? 0) <= 1 || !liveWorkflowForegroundControls.has(control))) continue;
|
|
199
215
|
if (control.activeChildren) {
|
|
200
216
|
for (const child of [...control.activeChildren.values()].sort((left, right) => left.index - right.index)) {
|
|
201
217
|
items.push({
|
|
@@ -478,10 +494,15 @@ function externalElapsedEnd(run: ExternalRun): number {
|
|
|
478
494
|
return terminal ? (run.endedAt ?? run.updatedAt ?? Date.now()) : Date.now();
|
|
479
495
|
}
|
|
480
496
|
|
|
481
|
-
function asyncDetail(item: Extract<FleetItem, { kind: "async" }
|
|
497
|
+
function asyncDetail(item: Extract<FleetItem, { kind: "async" }>, state: SubagentState): string[] {
|
|
482
498
|
const status = readStatus(item.run.asyncDir);
|
|
483
499
|
if (status) {
|
|
484
|
-
|
|
500
|
+
const trackedJob = state.fleetJobs?.get(item.runId) ?? state.asyncJobs.get(item.runId);
|
|
501
|
+
return formatAsyncRunTranscript(status, item.run.asyncDir, {
|
|
502
|
+
index: item.index,
|
|
503
|
+
lines: TRANSCRIPT_LINES,
|
|
504
|
+
sessionRoots: uniquePaths([...(state.trustedSessionRoots ?? []), trackedJob?.sessionRoot]),
|
|
505
|
+
}).split("\n");
|
|
485
506
|
}
|
|
486
507
|
const outputPath = item.index !== undefined ? path.join(item.run.asyncDir, `output-${item.index}.log`) : undefined;
|
|
487
508
|
return [
|
|
@@ -527,7 +548,7 @@ function detailLines(item: FleetItem | undefined, error: string | undefined, sta
|
|
|
527
548
|
? foregroundRecentDetail(item, state)
|
|
528
549
|
: item.kind === "external"
|
|
529
550
|
? externalDetail(item)
|
|
530
|
-
: asyncDetail(item);
|
|
551
|
+
: asyncDetail(item, state);
|
|
531
552
|
if (error) lines.unshift(`Fleet scan warning: ${error}`, "");
|
|
532
553
|
return lines;
|
|
533
554
|
}
|
|
@@ -835,6 +856,18 @@ export class SubagentFleetComponent implements Component {
|
|
|
835
856
|
return { item };
|
|
836
857
|
}
|
|
837
858
|
|
|
859
|
+
private selectedSteerAction(): { runId: string; asyncDir: string; index?: number } | { reason: string } {
|
|
860
|
+
const item = this.snapshot.items[this.selected];
|
|
861
|
+
if (item?.kind === "foreground-active" && item.control.parentWorkflowRunId) {
|
|
862
|
+
const parent = this.state.asyncJobs.get(item.control.parentWorkflowRunId) ?? this.state.fleetJobs?.get(item.control.parentWorkflowRunId);
|
|
863
|
+
if (!parent || !isActionableAsyncState(parent.status)) return { reason: "The parent workflow is no longer available for steering." };
|
|
864
|
+
return { runId: item.runId, asyncDir: parent.asyncDir, ...(item.index !== undefined ? { index: item.index } : {}) };
|
|
865
|
+
}
|
|
866
|
+
const target = this.selectedAsyncAction();
|
|
867
|
+
if ("reason" in target) return target;
|
|
868
|
+
return { runId: target.item.runId, asyncDir: target.item.run.asyncDir, ...(target.item.index !== undefined ? { index: target.item.index } : {}) };
|
|
869
|
+
}
|
|
870
|
+
|
|
838
871
|
private selectedHerdrInspectAction(): { runId: string; asyncDir: string; index?: number } | { reason: string } {
|
|
839
872
|
const item = this.snapshot.items[this.selected];
|
|
840
873
|
if (!item) return { reason: "No child is selected." };
|
|
@@ -992,12 +1025,12 @@ export class SubagentFleetComponent implements Component {
|
|
|
992
1025
|
this.setActionNotice({ text: "Steer message cannot be empty.", isError: true });
|
|
993
1026
|
return;
|
|
994
1027
|
}
|
|
995
|
-
const target = this.
|
|
1028
|
+
const target = this.selectedSteerAction();
|
|
996
1029
|
if ("reason" in target || !this.options.actions) {
|
|
997
1030
|
this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
|
|
998
1031
|
return;
|
|
999
1032
|
}
|
|
1000
|
-
this.runAction(() => this.options.actions!.steer({
|
|
1033
|
+
this.runAction(() => this.options.actions!.steer({ ...target, message, mode: this.steerMode }));
|
|
1001
1034
|
return;
|
|
1002
1035
|
}
|
|
1003
1036
|
if (matchesKey(data, "tab") || data === "\t") {
|
|
@@ -1065,7 +1098,7 @@ export class SubagentFleetComponent implements Component {
|
|
|
1065
1098
|
return;
|
|
1066
1099
|
}
|
|
1067
1100
|
if (matchesFleetAction(data, this.keybindings, "steer")) {
|
|
1068
|
-
const target = this.
|
|
1101
|
+
const target = this.selectedSteerAction();
|
|
1069
1102
|
if ("reason" in target || !this.options.actions) this.setActionNotice({ text: "reason" in target ? target.reason : "Fleet controls are unavailable in this context.", isError: true });
|
|
1070
1103
|
else {
|
|
1071
1104
|
this.actionNotice = undefined;
|
|
@@ -1274,23 +1307,38 @@ export async function openSubagentFleet(ctx: ExtensionContext, state: SubagentSt
|
|
|
1274
1307
|
await copyToClipboard(text);
|
|
1275
1308
|
});
|
|
1276
1309
|
const actions = options.actions ?? {
|
|
1277
|
-
steer: async (input: { runId: string; asyncDir: string; index?: number; message: string; mode: SteerDeliveryMode }) =>
|
|
1278
|
-
|
|
1279
|
-
runId
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1310
|
+
steer: async (input: { runId: string; asyncDir: string; index?: number; message: string; mode: SteerDeliveryMode }) => {
|
|
1311
|
+
const status = readStatus(input.asyncDir);
|
|
1312
|
+
const liveWorkflowRunId = status?.mode === "workflow" && state.workflowControllers?.has(status.runId || input.runId)
|
|
1313
|
+
? status.runId || input.runId
|
|
1314
|
+
: undefined;
|
|
1315
|
+
if (liveWorkflowRunId) {
|
|
1316
|
+
const route = state.foregroundControls.get(input.runId)?.parentWorkflowRunId === liveWorkflowRunId
|
|
1317
|
+
? resolveWorkflowForegroundSteeringTarget({ state, childRunId: input.runId, asyncDirRoot: options.asyncDirRoot ?? DIRS.async })
|
|
1318
|
+
: resolveWorkflowForegroundSteeringTarget({ state, workflowRunId: liveWorkflowRunId, asyncDirRoot: options.asyncDirRoot ?? DIRS.async });
|
|
1319
|
+
if (!route.ok) return { text: route.message, isError: true };
|
|
1320
|
+
return firstToolResultText(await steerWorkflowForegroundTarget({ target: route.target, message: input.message, mode: input.mode, ...(input.index !== undefined ? { index: input.index } : {}) }), `Failed to steer foreground run ${input.runId}.`);
|
|
1321
|
+
}
|
|
1322
|
+
return firstToolResultText(await steerAsyncRun({
|
|
1323
|
+
state,
|
|
1324
|
+
runId: input.runId,
|
|
1325
|
+
...(input.index !== undefined ? { index: input.index } : {}),
|
|
1326
|
+
message: input.message,
|
|
1327
|
+
mode: input.mode,
|
|
1328
|
+
location: { asyncDir: input.asyncDir, resolvedId: input.runId } as Parameters<typeof steerAsyncRun>[0]["location"],
|
|
1329
|
+
}), `Failed to steer async run ${input.runId}.`);
|
|
1330
|
+
},
|
|
1285
1331
|
stop: (input: { runId: string; asyncDir: string; index?: number }) => firstToolResultText(stopAsyncRun(state, input.runId, undefined, { asyncDir: input.asyncDir, resolvedId: input.runId }), `Failed to stop async run ${input.runId}.`),
|
|
1286
1332
|
inspect: async (input: { runId: string; asyncDir: string; index?: number }) => firstToolResultText(await handleHerdrInspectorAction("inspector.open", {
|
|
1287
1333
|
id: input.runId,
|
|
1288
1334
|
dir: input.asyncDir,
|
|
1335
|
+
focus: true,
|
|
1289
1336
|
...(input.index !== undefined ? { index: input.index } : {}),
|
|
1290
1337
|
}, {
|
|
1291
1338
|
state,
|
|
1292
1339
|
sessionRoots: state.trustedSessionRoots,
|
|
1293
1340
|
cwd: state.baseCwd,
|
|
1341
|
+
...(options.herdrClient ? { client: options.herdrClient } : {}),
|
|
1294
1342
|
...(state.authorityPolicy ? { authorityPolicy: state.authorityPolicy } : {}),
|
|
1295
1343
|
...(state.missionStoreConfig ? { missions: state.missionStoreConfig } : {}),
|
|
1296
1344
|
}), `Failed to open Herdr inspector for async run ${input.runId}.`),
|
|
@@ -38,7 +38,7 @@ export interface WatchdogRepoChangeSignature {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function git(cwd: string, args: string[]): string | undefined {
|
|
41
|
-
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 });
|
|
41
|
+
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8", maxBuffer: 10 * 1024 * 1024, windowsHide: true });
|
|
42
42
|
if (result.status !== 0) return undefined;
|
|
43
43
|
return result.stdout;
|
|
44
44
|
}
|
|
@@ -444,6 +444,7 @@ async function collectWithTypeScriptLanguageServer(input: {
|
|
|
444
444
|
}): Promise<WatchdogLspResult> {
|
|
445
445
|
const started = Date.now();
|
|
446
446
|
const child = spawn(input.command.command, input.command.args, {
|
|
447
|
+
windowsHide: true,
|
|
447
448
|
cwd: input.root,
|
|
448
449
|
stdio: "pipe",
|
|
449
450
|
env: { ...process.env, NO_COLOR: "1" },
|
|
@@ -26,7 +26,7 @@ interface ResolveWorkflowChatProgressInput {
|
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
function git(cwd: string, args: string[]): string | undefined {
|
|
29
|
-
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8" });
|
|
29
|
+
const result = spawnSync("git", ["-C", cwd, ...args], { encoding: "utf-8", windowsHide: true });
|
|
30
30
|
if (result.status !== 0) return undefined;
|
|
31
31
|
const output = result.stdout.trim();
|
|
32
32
|
return output || undefined;
|
|
@@ -90,7 +90,7 @@ export function resolveWorkflowChatProgress(input: ResolveWorkflowChatProgressIn
|
|
|
90
90
|
else mode = requestedMode;
|
|
91
91
|
|
|
92
92
|
if (mode === "live-card" && !sameRepo) return { error: "chatProgress: 'live-card' is only available for workflowScript runs in the same Git repository." };
|
|
93
|
-
if (mode === "live-card" && input.background) return { error: "chatProgress: 'live-card'
|
|
93
|
+
if (mode === "live-card" && input.background) return { error: "chatProgress: 'live-card' is unavailable for async workflowScript. Async workflows have no inline live card; omit chatProgress or use auto/off. Use async:false only when the parent must block." };
|
|
94
94
|
return { projection: { mode, repoRelation, ...(repoLabel ? { repoLabel } : {}) } };
|
|
95
95
|
}
|
|
96
96
|
|